Compile your Julia project with PackageCompiler for portability

Julia is a JIT language; however, sometimes it might be nice to have an executable. There are two ways to interact with PackageCompiler: Using the CLI using juliac and by adding PackageCompiler as part of your script. This article will go over both.

ASSERTS

Initial Setup

  1. Install Julia 1.1.0 if absent
  2. Install PackageCompiler and Deps
1
2
3
4
# ArgParse is required for PackageCompiler
julia -e 'using Pkg;
      Pkg.add("ArgParse");
      Pkg.add("PackageCompiler")'

Alias PackageCompiler to juliac

The full command to compile is julia /variable/path/to/juliac.jl. The path to this file is dependent on where PackageCompiler is stored and different on every system. We are going to save time by using an alias.

Use your shell of choice below.

bash

1
2
3
4
$ juliac_path='julia -e println(normpath(Base.find_package(\
  "PackageCompiler"),"..", "..")'
$ echo "juliac ${juliac_path}juliac.jl" >> ~/.bashrc
$ source ~/.bashrc

powershell

1
2
3
PS> $juliac_dir = julia -e 'println(normpath(Base.find_package(`
    \"PackageCompiler\"),\"..\",\"..\"))'
PS> Add-Content -Path $profile -Value "function juliac { julia `"${juliac_dir`" }"

Hello World!

Code

No introduction is complete without a Hello World. In this example, we’ll compile a Julia version.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# hello_world.jl

function AwesomeFuntion()
  println("Hello World!")
end

# Required PackageCompiler boilerplate
Base.@ccallable function julia_main(ARGS::Vector{String})::Cint
    AwesomeFunction()
    return 0
end

Compiling

We will use juliac hello_world.jl -tavern hello_world to generate the executable. I will cover options here briefly for sake of completeness (use juliac -h for full details).

  • -t Remove temp build files
  • -a Automatically build required dependencies
  • -v Verbose
  • -e Make executable
  • -r Implies -O3 -g0 [Max (-O)ptimize and debu(-g) at the lowest level]
  • -n Output file name

Time to compile will be several minutes, so go grab a ☕!

Once it has compiled, execute it:

1
2
3
$ cd builddir  # builddir is default output directory
$ ./hello_world
Hello World!

Packaging

The two relevant files in builddir are hello_world and a dynamically linked library, hello_world.$(dll). We can use a wildcard to tar both of them.

tar -cvzf hello_world.tar.gz builddir/*

To end result shoud be approximately 26MB, regardless of system.

Conclusion

In this article, we constructed a Julia binary.

See Also

Further Reading