Creating fully self-contained and pre-compiled library

I think in my many follow-ups and edits, my current pain point was lost.

So I can compile the “hello world” example, but when trying to load the library in julia, I get an error about a missing entrypoint named ijl_autoinit_and_adopt_thread.

However, when calling the library from Go, for example, it works. What happens when Libdl.dlopen-ing (not even ccall-ing) a shared library in julia? Why is this entrypoint called (and/or by whom)?

(“But why calling it from julia?!”, you might ask. Because tests and “validation scenarios” will be available for the julia-code version, and I will want to run them again against the juliac-generated library to ensure that it works exactly the same.)


Edit: one step further. Noted that I used the release-version of julia (1.11.x) to load and call the juliac-generated DLL. So, when also using nightly to call the generated DLL, I can load it (Libdl.dlopen) and get the symbol (Libdl.dlsym). But when I then call the function, I get a fatal crash.

Here’s a minimal example:

libmwe.jl:

Base.@ccallable function answer()::Cint
    return 42
end

Compile using:

julia.exe ../share/julia/juliac/juliac.jl --output-lib libmwe --experimental --trim --compile-ccallable libmwe.jl

In the julia REPL (in the directory where the .dll is located), execute:

 @ccall "libmwe.dll".answer()::Cint

This throws the following error with trace:

[3980] signal 22: SIGABRT
in expression starting at REPL[1]:1
crt_sig_handler at C:/workdir/src\signals-win.c:99
raise at C:\WINDOWS\System32\msvcrt.dll (unknown line)
abort at C:\WINDOWS\System32\msvcrt.dll (unknown line)
jl_init_threadtls at C:/workdir/src\threading.c:334
ijl_adopt_thread at C:/workdir/src\threading.c:447
.text at C:\julia-nightly\bin_compiled\libmwe.dll (unknown line)
top-level scope at .\REPL[1]:1
jl_toplevel_eval_flex at C:/workdir/src\toplevel.c:762
__repl_entry_eval_expanded_with_loc at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:304
jl_apply at C:/workdir/src\julia.h:2375 [inlined]
jl_f_invokelatest at C:/workdir/src\builtins.c:877
toplevel_eval_with_hooks at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:311
toplevel_eval_with_hooks at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:315
toplevel_eval_with_hooks at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:308 [inlined]
eval_user_input at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:333
repl_backend_loop at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:460
#start_repl_backend#41 at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:435
start_repl_backend at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:432 [inlined]
#run_repl#50 at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:671
run_repl at C:\workdir\usr\share\julia\stdlib\v1.13\REPL\src\REPL.jl:657
jfptr_run_repl_28061.1 at C:\julia-nightly\share\julia\compiled\v1.13\REPL\u0gqU_fBDF2.dll (unknown line)
run_std_repl at .\client.jl:481
jfptr_run_std_repl_75693.1 at C:\julia-nightly\lib\julia\sys.dll (unknown line)
jl_apply at C:/workdir/src\julia.h:2375 [inlined]
jl_f_invokelatest at C:/workdir/src\builtins.c:877
run_main_repl at .\client.jl:502
repl_main at .\client.jl:589 [inlined]
_start at .\client.jl:564
jfptr__start_43814.1 at C:\julia-nightly\lib\julia\sys.dll (unknown line)
jl_apply at C:/workdir/src\julia.h:2375 [inlined]
true_main at C:/workdir/src\jlapi.c:971
jl_repl_entrypoint at C:/workdir/src\jlapi.c:1138
mainCRTStartup at C:/workdir/cli\loader_exe.c:58
BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line)
RtlUserThreadStart at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
Allocations: 1 (Pool: 1; Big: 0); GC: 0

I double-checked, and calling the answer function in that library from a Go programm works perfectly fine. The Go code for reference:

package main

import "fmt"

/*
#cgo LDFLAGS: -L. -llibmwe
int answer();
*/
import "C"

func main() {
	answer := C.answer()
	fmt.Println("This is Go. Value returned by answer: ", answer)
}

Edit 2: just opened an issue: Library generated with juliac errors when called from julia itself, but works when called by other program · Issue #59237 · JuliaLang/julia