Skip to content

Instantly share code, notes, and snippets.

@tshort
Created December 18, 2019 14:01
Show Gist options
  • Save tshort/5772fbf8287d06c361901b8de1b90142 to your computer and use it in GitHub Desktop.
Save tshort/5772fbf8287d06c361901b8de1b90142 to your computer and use it in GitHub Desktop.
Example of compilation using StaticCompiler.jl (a very experimental package)
# Run the following from within `StandaloneCompiler/test`.
# Amin Yahyaabadi (@aminya) is working on a PR to make some of this easier.
include("jlrun.jl")
function fib(n)
a, b = 0, 1
while n > 0
a, b = b, a + b
n = n - 1
end
a
end
# Quick test to see if this compiles right and
# can be called from within Julia.
# This uses machinery designed for tests.
# `@jlrun` compiles the function to a dynamic
# library then calls it from Julia.
@test fib(10) == @jlrun fib(10)
# Here's how to do that manually in Linux. (You shouldn't need to be in the `test` folder.)
using StaticCompiler
m = irgen(fib, Tuple{Int})
StaticCompiler.fix_globals!(m) # not really needed for `fib`, but we'll do it anyway.
StaticCompiler.optimize!(m)
LLVM.verify(m)
write_object(m, "libfib.o")
libdir = joinpath(dirname(Sys.BINDIR), "lib")
# Create the shared library that includes a `fib` function:
run(`gcc -shared -fPIC -o libfib.so -L$libdir libfib.o -ljulia`)
# Call `fib` in the shared library.
dylib = Libdl.dlopen(abspath("libfib.so"))
ccall(Libdl.dlsym(dylib, "jl_init_globals"), Cvoid, ())
@show res = ccall(Libdl.dlsym(dylib, :fib), Int, (Int,), 10)
Libdl.dlclose(dylib)
# You should be able to use that shared library from something else (R or Python for example).
# Here's how to use that shared library from C.
Ctxt = """
#include <stdio.h>
#include <julia.h>
extern long long fib(long long);
extern void jl_init_with_image(const char *, const char *);
extern void jl_init_globals(void);
int main()
{
jl_init_with_image(".", "blank.ji");
jl_init_globals();
printf("%lld", fib(10));
jl_atexit_hook(0);
return 0;
}
"""
write("fibmain.c", Ctxt)
# Here's a bit of hackery. We need a file for initialization.
# Create `blank.ji`.
julia_path = joinpath(Sys.BINDIR, Base.julia_exename())
base_dir = dirname(Base.find_source_file("sysimg.jl"))
wd = pwd()
open(println, "blank.jl", "w")
cd(base_dir) do
run(`$(julia_path) --output-ji $(wd)/blank.ji $(wd)/blank.jl`)
end
includedir = joinpath(dirname(Sys.BINDIR), "include", "julia")
run(`gcc -c -std=gnu99 -I$includedir -DJULIA_ENABLE_THREADING=1 -fPIC fibmain.c`)
rpath = `-Wl,-rpath,\$ORIGIN:\$ORIGIN/../lib`
flags = ``
standalonedir = pwd()
run(`gcc -o fibmain fibmain.o -L$libdir -L$standalonedir -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-rpath,'.' -Wl,-rpath,$libdir -ljulia -lfib -O2 $rpath $flags`)
# You should now have an executable `fibmain` that runs `fib(10)`.
# This is for Linux; other platforms with have different `gcc` invocations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment