Created
December 18, 2019 14:01
-
-
Save tshort/5772fbf8287d06c361901b8de1b90142 to your computer and use it in GitHub Desktop.
Example of compilation using StaticCompiler.jl (a very experimental package)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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