Compiling and building binaries from your julia code

Ok, in the next days I am going to create a last PR with preliminary Julia v0.7 support in a separate script juliac_v07.jl, so that I do not forget what I have in mind, then we will test it once Julia v0.7 alpha is released.

See line 40 of program2.c:

jl_options.image_file = "libhello.so";

Should this line be modified as follows or removed altogether for Julia v0.7?

jl_options.image_file = "hello.o";

Thanks

One question: Could this tool be useful to create a shared library to include Julia functions in Matlab? Or is the call overhead too high?

I need to call a function 10 000 times per second, so loading the Julia library each time might be too much overhead.

I really have no idea if the overhead would be too high or not. Haven’t used matlab in many years now! Probably should be easy to hook up the hello.jl example and see what you get.

-viral

3 Likes

To load an .so file into Matlab I also need a header file. Where can I find/
what can I use as hello.h file?

you could also check out https://github.com/twadleigh/mexjulia

Well, this is not in a usable state for Linux users:
https://github.com/twadleigh/mexjulia/issues/32

So I need a different solution.

Hi, please could anyone help with the “static-julia” compilation on Windows?
I’ve downloaded the latest version of the “static-julia” project. Trying to compile the “hello” example I’m getting error listed below. Thanks.

Build shared library "libhello.dll":
`'c:\cygwin64\bin\x86_64-w64-mingw32-gcc.exe' -m64 -shared -o libhello.dll hello.o -std=gnu99 '-IC:\Users\Igor Cerovsky\AppData\Local\Julia-0.6.0\include\julia' -DJULIA_ENABLE_THREADING=1 '-LC:\Users\Igor Cerovsky\AppData\Local\Julia-0.6.0\bin' -Wl,--stack,8388608 -ljulia -lopenlibm -Wl,--export-all-symbols`
C:/cygwin64/lib/gcc/x86_64-w64-mingw32/6.4.0/collect2.exe: error while loading shared libraries: ?: cannot open shared object file: No such file or directory
ERROR: LoadError: failed process: Process(`'c:\cygwin64\bin\x86_64-w64-mingw32-gcc.exe' -m64 -shared -o libhello.dll hello.o -std=gnu99 '-IC:\Users\Igor Cerovsky\AppData\Local\Julia-0.6.0\include\julia' -DJULIA_ENABLE_THREADING=1 '-LC:\Users\Igor Cerovsky\AppData\Local\Julia-0.6.0\bin' -Wl,--stack,8388608 -ljulia -lopenlibm -Wl,--export-all-symbols`, ProcessExited(1)) [1]
1 Like

This is pretty fantastic, thanks @viralbshah! So I understand that there’s a pretty big (~34M on my machine for a program that just does a single println) ‘system image’ shared lib produced that I guess (and output of nm libhello.dylib seems to confirm) includes every function that could possibly be called out of the packages used by the program being compiled. Some questions related (and not) to this arise in my mind:

  1. Aside from the overhead of the library having a ton of symbols that won’t be used at runtime, is the generated code guaranteed to be free of ‘startup overhead’ as is seen in the REPL? Put another way, is every execution of the same program identical (modulo OS-level cacheing etc)?

  2. Could the library (or single binary in 0.7) be stripped of the unused symbols?

  3. Does garbage collection act the same in these binaries/libraries as when executing a .jl script? Would the GC present a barrier to applications where deterministic timing is important, e.g. real-time controllers?

  4. Can the generated binary make use of threads? In the parallel-processing sense (map-reduce etc) as well as long running task threads. I haven’t gotten into using threading in Julia yet so apologies if this might be more of a general Julia question!

As you might guess from my questions, I’m excited at the prospect of using Julia to develop something like an embedded real-time control system and static-julia seems like a it might be a good starting point.

I’m also interested in real-time environments (for live audio processing), but it’s a tough nut to crack.

Even if your code is compiled statically it doesn’t change the memory allocation/GC model, so the code will still not be real-time safe. If you can get away with “mostly safe” then you can get pretty far by avoiding as much heap allocation as possible so the GC doesn’t have much to do.

In ages past there was some exciting work towards making the GC incremental with a time-bounded pause times, but I think it was never ready for prime time and didn’t get merged.

I think I could get away with “mostly safe”, certainly if there was a path towards stronger safety guarantees down the road. I haven’t read anything about Julia yet that indicates that it shouldn’t be possible in principle to have some subset of Julia programs that could be real time safe, in some future hypothetical version of Julia.

I also noticed that it fails when using some packages (e.g. Gtk compiles but segfault, Cairo doesn’t compile, …) do we know the potentials reasons why some packages fail ? I guess calling external libraries in particular can go wrong in several ways. Or in other words if I want to make Cairo compile-compatible, what should I look for ?

I agree, and there have even been recent changes that allow more things to be stack-allocated, further reducing the GC pressure.

It will have lesser startup overhead, but for eliminating most of the startup overhead, we will need something like Tim Holy’s SnoopCompile. Jameson recently fixed it to work on 0.6/0.7 - so that would be the thing to further investigate. Completely dynamic things will still invoke the jit, but the goal post 1.0 should be to have tools that help understand these things and simplify them.

GC will be present. The much longer term plan should be to have either a DSL or a restricted subset of Julia for real-time controllers. I think it would be a great research project at a university, or for someone with the right skill and enough time to put into something like this. There have been many discussions (offline), but nothing that has been written up.

Threading in Julia is still early, but it should work in these binaries as expected. Same for distributed computing stuff. It will be a bit more work to build further tooling to make all this easy - but if it doesn’t work, it would be good to get issues on the static-julia repo.

-viral

2 Likes

Ability to deploy a package binary at some point is very important, as well as an ability to write Julia in such a way that all inferences about the code structure/types can be made at compile time. The latter will also enable the same or better experience that users of “Intellisense” and C# enjoy. Please please make sure that everything needed will be baked in 1.0 :slight_smile:

I just recently put snoopcompile and the static-compilation script into one package: https://github.com/SimonDanisch/PackageCompiler.jl - so that should make things already a bit easier.

@jonathanBieler

After making a fairly large package (Makie) and it’s dependencies precompilable, I came up with the following list:

  • non const globals are problematic, or globals defined in functions - removing those got me to 90% of making the package save for static compilation

  • type unstable code had some inference issues (around 2 occurrence, where I’m still not sure what was happening) - both cases happened with dictionaries… Only way to find those was investigating the segfaults with gdb, but then it was relatively easy to just juggle around the code a bit. - The non const globals might be related since they introduce type instabilities, not sure though…

  • some generated functions needed reordering of the functions they call ( actually, even for normal code all functions that get called in a generated function should be defined before it)

  • I uncovered one out of bounds issue, that somehow was not coming up without static-compilation

  • I used julia-debug to uncover those bugs, but actually, the last errors I was trying to uncover where due to using julia-debug - so Makie just works correctly statically compiled with a release build right now!

  • you’re pretty much on your own and need to use gdb to find the issues and I still don’t know what the underlying julia issues are and when they will get fixed :wink: See: https://github.com/JuliaLang/julia/issues/24533

20 Likes

I am so excited to try this over the weekend. Thank you very much for this effort!

The solution:

  • use the mingw-w64 compiler from http://mingw-w64.org/doku.php/download/mingw-builds with default settings
  • set the PATH to cc = is_windows() ? raw"c:\Program Files\mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\x86_64-w64-mingw32-gcc.exe" : "gcc" (I’ve used the absolute path purposely); or set system PATH
  • copy all required *.dll files to the hello.exe folder from c:\Program Files\mingw-w64\x86_64-7.2.0-win32-seh-rt_v5-rev1\mingw64\bin\ and YOUR_JULIA_INSTALL\Julia-0.6.0\bin\
  • run the hello.exe in Unicode friendly console; I use Visual Studio Code
shell> d:/work/J-CPP/static-julia-master/builddir/hello.exe
hello, world
f() = 0.369760359689711
       ┌────────────────────────────────────────┐
   100 │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠎│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡰⠁⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠊⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠔⠁⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⡠⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠔⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠤⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣀⠤⠒⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⡠⠔⠊⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       │⠀⠀⠀⠀⠀⠀⢀⣀⠤⠔⠊⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
     0 │⣀⠤⠤⠔⠒⠉⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀│
       └────────────────────────────────────────┘
       1                                       10

3 Likes

Please notice that static-julia was merged with PackageCompiler.jl, any further development will happen there.

6 Likes