Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building Cairo.jl for AWS Lambda #133

Closed
samoconnor opened this issue Apr 26, 2016 · 6 comments
Closed

Building Cairo.jl for AWS Lambda #133

samoconnor opened this issue Apr 26, 2016 · 6 comments

Comments

@samoconnor
Copy link

samoconnor commented Apr 26, 2016

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)
@nalimilan
Copy link
Contributor

Thanks. Could you make a PR? Note that if you add Harfbuzz as a dependency, you also have to add it to all providers, else it will break Windows, Mac (as well as force having build tools installed on Linux).

@nalimilan
Copy link
Contributor

Though about point 1: I'm not sure I really understand what happens, but it sounds like a bug in the image. The package manager shouldn't pretend things work if they don't. Anyway, JuliaPackaging/BinDeps.jl#168 could be a reasonable workaround.

@samoconnor
Copy link
Author

Could you make a PR?

@nalimilan At this point I don't think what I've done to get the build working is worthy of a PR. It feels like a hack. I don't think I understand how BinDeps is supposed to work, but I hope that someone who does can improve build.jl using the information I've provided.

Though about point 1: I'm not sure I really understand what happens, but it sounds like a bug in the image. The package manager shouldn't pretend things work if they don't.

There is a "build" box (Amazon Linux on EC2) and a multitude of "deployment" boxes (Amazon Linux on the Lambda sandbox). The "build" box is configured to have the same system libraries as the Lambda sandbox.

When Pkg.add("Cairo") is run on the "build" box, it uses yum to install new system libraries on the "build" box under /usr/lib64. Everything works fine on the build box, but the build is dependant on local system libraries.
When julia/v0.4/Cairo/* is deployed to the Lambda sandbox; and deps.jl says @checked_lib _jl_libgobject "/usr/lib64/libpango-1.0.so"; that file does not exist in /usr/lib64. There is no way to modify /usr/lib64 in the sandbox.

Anyway, JuliaPackaging/BinDeps.jl#168 could be a reasonable workaround.

I think it would make sense to have ENV["JULIA_BINDEPS_DISABLE_YUM"], ENV["JULIA_BINDEPS_DISABLE_APT"], ENV["JULIA_BINDEPS_DISABLE_AUTOTOOLS"] etc to allow a particular source to be disabled. Or perhaps ENV["JULIA_BINDEPS_DISABLE"] = "apt yum"

It is probably also necessary to have something like ENV["JULIA_BINDEPS_IGNORE"] = "freetype fontconfig". You could try to do this by specifying required version numbers, but that does not take into account library-build-time configuration options. e.g. at one point I had the correct version of harfbuzz installed but because it was compiled without freetype support, pango would not build.

@nalimilan
Copy link
Contributor

@nalimilan At this point I don't think what I've done to get the build working is worthy of a PR. It feels like a hack. I don't think I understand how BinDeps is supposed to work, but I hope that someone who does can improve build.jl using the information I've provided.

At least the patch you showed seems to include legitimate fixes, so why not submit them?

samoconnor pushed a commit to samoconnor/Cairo.jl that referenced this issue Apr 28, 2016
@samoconnor
Copy link
Author

@nalimilan I've cleaned things up a little and submitted a PR: #134

@giordano
Copy link
Contributor

giordano commented Sep 7, 2019

PR #292 should probably have made all of this not needed, but I can't check as I don't have access to AWS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants