BinaryBuilder and GCC multi-versioning

I have just merged https://github.com/JuliaPackaging/BinaryBuilder.jl/pull/355 . This has some implications for those of you building things that depend on specific versions of GCC. In particular, if anything links against libgfortran, you’re going to need to compile GCC-version-specific tarballs. This is denoted through extra abi tags added to the end of triplets; e.g. we can have things like x86_64-linux-gnu-gcc7 now. The only compiler ABI stuff that we’re tracking right now is GCC major version (with the possible values gcc4, gcc7 and gcc8, which link to libgfortran 3, 4 and 5 respectively), although we have the machinery in place to start differentiating on things such as cxx11 string ABI choice, which may or may not happen in the future.

As builder repository owners, the main change is that I have added a new audit pass that will check to see if any of your binaries link against libgfortran. If they do, and the current target is (for instance) x86_64-linux-gnu (e.g. no “gcc version tag”) then it will print out a big fat warning. The warning will tell you to update your build_tarballs.jl file to include the line platforms = expand_gcc_versions(platforms). What this does is just take a single Platform object that looks like x86_64-linux-gnu and turn it into [x86_64-linux-gnu-gcc4, x86_64-linux-gnu-gcc7, x86_64-linux-gnu-gcc8]. In essence, it will force BinaryBuilder to do the full combinatorial explosion of GCC versions for all of your platforms. Here’s an example of how simple a change this is for you.

From the BinaryProvider side, build.jl for right now the main difference is that build.jl files are going to use a choose_download(download_info, platform_key_abi()) function rather than just try to pull a value out of the dict directly (e.g. download_info[platform_key_abi()]). This is because we need the ability to pull out the entry that corresponds to our GCC version precisely, OR pull out the entry that has no GCC version encoded within it. (e…g. for pure-C dependencies, rather than FORTRAN dependencies). This isn’t a big change, and BB will automatically start generating build.jl files that conform to this, but it’s a good thing to know. You can see an example of what this looks like in the generated build.jl for OpenblasBuilder.

This is the critical step we’ve needed in order to have BinaryProvider downloads for things like Arpack.jl that work for from-source builds of Julia and not “just” the official Julia binaries. An incredible amount of work went into this release of BinaryBuilder, and we thank you all for your patience.

21 Likes

Is there a way to disable specific compiler versions in the expansion? For example, I’m building something that doesn’t work on gcc4, but now, with the expansion, BinaryBuilder tries this and throws an error.

1 Like

OK, got it. One can explicitly provide the gcc versions, like in the OpenblasBuilder example.

platforms = [
    Linux(:aarch64, libc=:glibc, compiler_abi=CompilerABI(:gcc4)), 
    Linux(:aarch64, libc=:glibc, compiler_abi=CompilerABI(:gcc7)),
#and so on
]
1 Like

One more question for clarification:
How invasive is this change? If I have one dependency that is now versioned, how does that affect the other items in the dependency chain? Do they now all have to be versioned? Or can we mix and match.

What do I do if the library doesn’t support gcc-4.8.5?
Do I just ignore the fact the build fails while running the wizard, cross my fingers and hope everything magically works out and I get a deps.jl file where I can edit the platforms variable, like in your comment?

Or is there a better way?

I want to wrap SLEEF. My plan for now is is, in case of gcc4 or non-x86 architectures, to just default to calling the regular versions.

This comment has been cross-posted from slack.

If you have a gfortran library that you build for GCC 4/7/8, then have a pure-C library that is built with only GCC 4, it should be able to link against the gfortran library that was built for GCC 7 or GCC 8. The only ABIs that change are the gfortran and C++ ABIs. So items further on up the dependency chain should only need to be versioned if they themselves require it.

If your library cannot be built with GCC-4.8.5, then you should build it against only GCC 7 and 8. You can do this by specifying explicitly which triplets you want to compile for, either on the command line (e.g. julia --color=yes build_tarballs.jl --verbose x86_64-linux-gnu-gcc7,x86_64-linux-gnu-gcc8,etc...) or within your build_tarballs.jl file with something like:

platforms = [p for p in supported_platforms() if compiler_abi(p).gcc_version != :gcc4]

If your library relies on GCC multiversioning (e.g. it uses gfortran) and it cannot be built with GCC 4, then you will simply have to support the platforms it can be built with. If it can be built with GCC 5 or 6 but not 4, we could conceivably add an escape hatch for you to be able to compile against those versions (Which are ABI-compatible with GCC 4) but that is not supported yet.

1 Like