How to statically compile to a binary

The front page https://julialang.org says at the “General Purpose” tab that you can “statically compile your code”.

So I have installed PackageCompiler as I described here.

I am able to create a dynamic binary as follows:

julia ~/.julia/packages/PackageCompiler/oT98U/juliac.jl -vae --compile=all hello.jl

when you examine it:

$ ldd builddir/hello
	linux-vdso.so.1 (0x00007ffc27946000)
	hello.so => /home/certik/repos/julia_comp/builddir/hello.so (0x0000151ddd2c7000)
	libjulia.so.1 => /home/certik/ext/julia-1.1.0/lib/libjulia.so.1 (0x0000151ddcb57000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000151ddc766000)
	libLLVM-6.0.so => /home/certik/ext/julia-1.1.0/lib/julia/libLLVM-6.0.so (0x0000151dd9a40000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x0000151dd983c000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x0000151dd9634000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x0000151dd9415000)
	libstdc++.so.6 => /home/certik/ext/julia-1.1.0/lib/julia/libstdc++.so.6 (0x0000151dd9097000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x0000151dd8cf9000)
	libgcc_s.so.1 => /home/certik/ext/julia-1.1.0/lib/julia/libgcc_s.so.1 (0x0000151dd8ae1000)
	/lib64/ld-linux-x86-64.so.2 (0x0000151de4c7b000)

it links to Julia and to hello.so:

$ ldd builddir/hello.so 
	linux-vdso.so.1 (0x00007ffc48392000)
	libjulia.so.1 => /home/certik/ext/julia-1.1.0/lib/libjulia.so.1 (0x000014d4bc419000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000014d4bc028000)
	libLLVM-6.0.so => /home/certik/ext/julia-1.1.0/lib/julia/libLLVM-6.0.so (0x000014d4b9302000)
	libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x000014d4b90fe000)
	librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x000014d4b8ef6000)
	libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x000014d4b8cd7000)
	libstdc++.so.6 => /home/certik/ext/julia-1.1.0/lib/julia/libstdc++.so.6 (0x000014d4b8959000)
	libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000014d4b85bb000)
	libgcc_s.so.1 => /home/certik/ext/julia-1.1.0/lib/julia/libgcc_s.so.1 (0x000014d4b83a3000)
	/lib64/ld-linux-x86-64.so.2 (0x000014d4c433a000)

Which also links to Julia and LLVM (libjulia.so.1 and libLLVM-6.0.so).

Question 1: How do I create a static binary? (Or are static binaries not supported yet?)

Question 2: Why is the hello.so library so large (131MB)? (Is there a way to make it smaller?)

$ ll -h builddir/hello.so 
-rwxr-xr-x 1 certik certik 131M May  3 11:18 builddir/hello.so*

Question 3: Why does the compilation of this simple script take 2min 38s ? (Is there a way to make it compile faster?)

$ time julia ~/.julia/packages/PackageCompiler/oT98U/juliac.jl -vae --compile=all hello.jl
...
real	2m38.828s
user	2m35.881s
sys	0m6.016s

Thanks for any feedback on this.

2 Likes

I am also looking for a way to compile a Julia code and “bundle” everything necessary inside the executable. I know it will be probably very big (hundreds of MiB), but it will be very good for my use case.

2 Likes

Not the most helpful comment, but I wonder if it would make sense for julialang.org not to emphasize static compilation until PackageCompiler is significantly more mature. I must confess, I’ve also found static compilation to be quite an effort in the current state. The progress has been great, but, unless I’m missing something, this still has a way to go before static compilation is a smooth process.

The last I spent any time with PackageCompiler, I found compile_incremental to be far more helpful and functional than anything else. It might be worth considering whether that approach could work for you before resorting to compiling static binaries or even using compile_package.

2 Likes

@Ronis_BR, @ExpandingMan thanks a lot for the feedback. Do you think it would be fair to say about Julia that “Ahead-of-time compilation to static executables is not yet as easy as with C++ or Fortran”?

That’s definitely true. C++ and Fortran were designed specifically for compilation into static binaries, Julia’s compiler on the other hand is rather novel. I like to think of it as an ahead-of-time compiler that gets called “on demand”. This has all sorts of huge advantages for writing generic code, but the disadvantage is that it is significantly harder to determine what exactly should be incorporated in a statically compiled binary. There’s no fundamental reason why this can’t be done, and lots of great progress has been made, but it will probably take a bit of time for the process to be really robust.

(Bear in mind the disclamer that I’ve made absolutely zero contribution to PackageCompiler myself, so people who work on that package and actually know what they’re talking about may be either more optimistic or more pessimistic.)

2 Likes

Thanks @ExpandingMan, I appreciate your answer!