Skip to content

Building Cairo.jl for AWS Lambda #133

@samoconnor

Description

@samoconnor

Cairo.jl does not build cleanly for AWS Lambda.

The AWS Lambda sandbox runs on Amazon Linux.
An equivalent EC2 image is used to build binaries that will run on AWS Lambda.

There are a number of problems with the way Cairo.jl's BinDeps configuration works at present:

  1. It tries to use yum to install dependencies. This "works" on the EC2 build box, but creates binaries that depend on libraries that do not exists in the Lambda sandbox. I have worked around this by disabling yum on EC2 chmod 000 /usr/bin/yum.
  2. It sees that libfreetype and libfontconfig are installed, and therefore does not try to build them from source, but this causes the pango build to fail later because pango requires more recent versions. I've worked around this by modifying the aliases = entries to specify specific version numbers.
  3. It seems that pango requires libharfbuzz, but there is no rule to build this in build.jl. I've added an Autotools rule for this.
  4. libgobject is in the same "group" as all the other deps. This results in an empty # Load dependencies section in deps.jl because libgobject is satisfied by a system lib and the others in the group are satisfied by Autotools.
  5. There seem to be a number of deps that are labeled runtime = false that are in fact needed at runtime. e.g. libpng, libpixman, libffi, libfontconfig
  6. fontconfig needs the option --enable-libxml2, otherwise it requires expat to be installed.

After some experimentation (see patch below), I've managed to get the build working with the following output in deps.jl:

@checked_lib _jl_libgobject "/usr/lib64/libgobject-2.0.so"
@checked_lib _jl_libpango "/var/task/julia/v0.4/Cairo/deps/usr/lib/libpango-1.0.so"
@checked_lib _jl_libpangocairo "/var/task/julia/v0.4/Cairo/deps/usr/lib/libpangocairo-1.0.so"
@checked_lib _jl_libcairo "/var/task/julia/v0.4/Cairo/deps/usr/lib/libcairo.so" 

The end result is that built in system libraries are used for libgobject, libpng, libpixman, libffi and libz; and everything else is built form source and installed to /var/task/julia/v0.4/Cairo/deps/usr/lib/.

Libraries available on the Lambda Sandbox:

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libgob*'`)
/usr/lib64/libgobject-2.0.so.0
/usr/lib64/libgobject-2.0.so.0.3600.3

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libpng*'`)
/usr/lib64/libpng.so.3
/usr/lib64/libpng.so.3.49.0
/usr/lib64/libpng12.so.0
/usr/lib64/libpng12.so.0.49.0

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libpix*'`)
/usr/lib64/libpixman-1.so.0
/usr/lib64/libpixman-1.so.0.32.4

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libffi*'`)
/usr/lib64/libffi.so.6
/usr/lib64/libffi.so.6.0.1

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libfreetype*'`)
/usr/lib64/libfreetype.so.6
/usr/lib64/libfreetype.so.6.3.22

julia> @lambda_eval aws run(`bash -c 'ls /usr/lib64/libfontc*'`)
/usr/lib64/libfontconfig.so.1
/usr/lib64/libfontconfig.so.1.4.4
/usr/lib64/libfontenc.so.1
/usr/lib64/libfontenc.so.1.0.0

julia> @lambda_eval aws run(`bash -c 'ls /lib64/libz*'`)
/lib64/libz.so.1
/lib64/libz.so.1.2.8
diff --git a/deps/build.jl b/deps/build.jl
index 06f8c63..7107924 100644
--- a/deps/build.jl
+++ b/deps/build.jl
@@ -11,11 +11,12 @@ deps = [
     pixman = library_dependency("pixman", aliases = ["libpixman","libpixman-1","libpixman-1-0","libpixman-1.0"], depends = [libpng], runtime = false, group = group)
     libffi = library_dependency("ffi", aliases = ["libffi"], runtime = false, group = group)
     gettext = library_dependency("gettext", aliases = ["libintl", "preloadable_libintl", "libgettextpo"], os = :Unix, group = group)
-    gobject = library_dependency("gobject", aliases = ["libgobject-2.0-0", "libgobject-2.0", "libgobject-2_0-0", "libgobject-2.0.so.0"], depends=[libffi, gettext], group = group)
-    freetype = library_dependency("freetype", aliases = ["libfreetype"], runtime = false, group = group)
-    fontconfig = library_dependency("fontconfig", aliases = ["libfontconfig-1", "libfontconfig", "libfontconfig.so.1"], depends = [freetype], runtime = false, group = group)
+    gobject = library_dependency("gobject", aliases = ["libgobject-2.0-0", "libgobject-2.0", "libgobject-2_0-0", "libgobject-2.0.so.0"], depends=[libffi, gettext])
+    freetype = library_dependency("freetype", aliases = ["libfreetype.so.6.10.0"], group = group)
+    fontconfig = library_dependency("fontconfig", aliases = ["libfontconfig.so.1.8.0"], depends = [freetype], group = group)
     cairo = library_dependency("cairo", aliases = ["libcairo-2", "libcairo","libcairo.so.2"], depends = [gobject,fontconfig,libpng], group = group)
-    pango = library_dependency("pango", aliases = ["libpango-1.0-0", "libpango-1.0","libpango-1.0.so.0", "libpango-1_0-0"], group = group)
+    harfbuzz = library_dependency("harfbuzz", aliases = ["libharfbuzz", "libharfbuzz.so.0"], depends = [cairo,freetype], group = group)
+    pango = library_dependency("pango", depends = [harfbuzz], aliases = ["libpango-1.0-0", "libpango-1.0","libpango-1.0.so.0", "libpango-1_0-0"], group = group)
     pangocairo = library_dependency("pangocairo", aliases = ["libpangocairo-1.0-0", "libpangocairo-1.0", "libpangocairo-1.0.so.0"], depends = [cairo], group = group)
     zlib = library_dependency("zlib", aliases = ["libzlib","zlib1"], os = :Windows, group = group)
 ]
@@ -77,10 +78,11 @@ const png_version = "1.5.14"

 provides(Sources,
     @compat Dict(
+        URI("https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-1.2.6.tar.bz2") => harfbuzz,
         URI("http://www.cairographics.org/releases/pixman-0.28.2.tar.gz") => pixman,
         URI("http://www.cairographics.org/releases/cairo-1.12.16.tar.xz") => cairo,
         URI("http://download.savannah.gnu.org/releases/freetype/freetype-2.4.11.tar.gz") => freetype,
-        URI("http://www.freedesktop.org/software/fontconfig/release/fontconfig-2.10.2.tar.gz") => fontconfig,
+        URI("http://www.freedesktop.org/software/fontconfig/release/fontconfig-2.11.1.tar.gz") => fontconfig,
         URI("http://ftp.gnu.org/pub/gnu/gettext/gettext-0.18.2.tar.gz") => gettext,
         URI("ftp://ftp.simplesystems.org/pub/libpng/png/src/history/libpng15/libpng-$(png_version).tar.gz") => libpng,
         URI("ftp://sourceware.org/pub/libffi/libffi-3.0.11.tar.gz") => libffi,
@@ -95,7 +97,7 @@ provides(BuildProcess,
     @compat Dict(
         Autotools(libtarget = "pixman/libpixman-1.la", installed_libname = xx("libpixman-1-0.","libpixman-1.","libpixman-1.0.")*BinDeps.shlib_ext) => pixman,
         Autotools(libtarget = xx("objs/.libs/libfreetype.la","libfreetype.la")) => freetype,
-        Autotools(libtarget = "src/libfontconfig.la") => fontconfig,
+        Autotools(libtarget = "src/libfontconfig.la", configure_options = ["--enable-libxml2"]) => fontconfig,
         Autotools(libtarget = "src/libcairo.la", configure_options = append!(append!(
                 AbstractString[],
                 OS_NAME != :Linux ? AbstractString["--without-x","--disable-xlib","--disable-xcb"] : AbstractString[]),
@@ -103,7 +105,8 @@ provides(BuildProcess,
         Autotools(libtarget = "gettext-tools/gnulib-lib/.libs/libgettextlib.la") => gettext,
         Autotools(libtarget = "libffi.la") => libffi,
         Autotools(libtarget = "gobject/libgobject-2.0.la") => gobject,
-        Autotools(libtarget = "pango/libpango-1.0.la") => [pango,pangocairo]
+        Autotools(libtarget = "pango/libpango-1.0.la") => [pango,pangocairo],
+        Autotools(libtarget = "src/libharfbuzz.la") => harfbuzz
     ))

 provides(BuildProcess,Autotools(libtarget = "libpng15.la"),libpng,os = :Unix)

ldd output

[root@ip-172-31-16-106 deps]# ldd usr/lib/libpangocairo-1.0.so
    linux-vdso.so.1 =>  (0x00007ffd28151000)
    libcairo.so.2 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libcairo.so.2 (0x00007f9f4a657000)
    libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f9f4a434000)
    libpixman-1.so.0 => /usr/lib64/libpixman-1.so.0 (0x00007f9f4a189000)
    libpng12.so.0 => /usr/lib64/libpng12.so.0 (0x00007f9f49f63000)
    librt.so.1 => /lib64/librt.so.1 (0x00007f9f49d5a000)
    libpangoft2-1.0.so.0 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libpangoft2-1.0.so.0 (0x00007f9f49b47000)
    libpango-1.0.so.0 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libpango-1.0.so.0 (0x00007f9f498fd000)
    libgobject-2.0.so.0 => /usr/lib64/libgobject-2.0.so.0 (0x00007f9f496ad000)
    libgmodule-2.0.so.0 => /usr/lib64/libgmodule-2.0.so.0 (0x00007f9f494aa000)
    libgthread-2.0.so.0 => /usr/lib64/libgthread-2.0.so.0 (0x00007f9f492a9000)
    libharfbuzz.so.0 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libharfbuzz.so.0 (0x00007f9f4902c000)
    libglib-2.0.so.0 => /usr/lib64/libglib-2.0.so.0 (0x00007f9f48d04000)
    libm.so.6 => /lib64/libm.so.6 (0x00007f9f48a02000)
    libfontconfig.so.1 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libfontconfig.so.1 (0x00007f9f487c5000)
    libxml2.so.2 => /usr/lib64/libxml2.so.2 (0x00007f9f4845e000)
    libfreetype.so.6 => /var/task/julia/v0.4/Cairo/deps/usr/lib/libfreetype.so.6 (0x00007f9f481d1000)
    libz.so.1 => /lib64/libz.so.1 (0x00007f9f47fba000)
    libc.so.6 => /lib64/libc.so.6 (0x00007f9f47bf8000)
    /lib64/ld-linux-x86-64.so.2 (0x000055fa2827c000)
    libffi.so.6 => /usr/lib64/libffi.so.6 (0x00007f9f479ef000)
    libdl.so.2 => /lib64/libdl.so.2 (0x00007f9f477eb000)
    liblzma.so.5 => /usr/lib64/liblzma.so.5 (0x00007f9f475c6000)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions