Skip to content

Commit 2a9c133

Browse files
authored
juliac: add pre-compilation step to build pipeline (#57207)
This is required to avoid obscure loading / package errors during the trimming build process.
1 parent cf4ab83 commit 2a9c133

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

contrib/juliac.jl

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
# Julia compiler wrapper script
22
# NOTE: The interface and location of this script are considered unstable/experimental
33

4-
cmd = Base.julia_cmd()
5-
cmd = `$cmd --startup-file=no --history-file=no`
4+
julia_cmd = `$(Base.julia_cmd()) --startup-file=no --history-file=no`
65
output_type = nothing # exe, sharedlib, sysimage
76
outname = nothing
87
file = nothing
@@ -55,55 +54,77 @@ isnothing(outname) && error("No output file specified")
5554
isnothing(file) && error("No input file specified")
5655

5756
absfile = abspath(file)
58-
cflags = readchomp(`$(cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --cflags `)
57+
cflags = readchomp(`$(julia_cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --cflags `)
5958
cflags = Base.shell_split(cflags)
60-
allflags = readchomp(`$(cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --allflags`)
59+
allflags = readchomp(`$(julia_cmd) $(joinpath(Sys.BINDIR, Base.DATAROOTDIR,"julia", "julia-config.jl")) --allflags`)
6160
allflags = Base.shell_split(allflags)
6261
tmpdir = mktempdir(cleanup=false)
6362
initsrc_path = joinpath(tmpdir, "init.c")
6463
init_path = joinpath(tmpdir, "init.a")
6564
img_path = joinpath(tmpdir, "img.a")
6665
bc_path = joinpath(tmpdir, "img-bc.a")
6766

68-
open(initsrc_path, "w") do io
69-
print(io, """
70-
#include <julia.h>
71-
__attribute__((constructor)) void static_init(void) {
72-
if (jl_is_initialized())
73-
return;
74-
julia_init(JL_IMAGE_IN_MEMORY);
75-
jl_exception_clear();
76-
}
77-
""")
78-
end
7967

80-
cmd = addenv(`$cmd --project=$(Base.active_project()) --output-o $img_path --output-incremental=no --strip-ir --strip-metadata $julia_args $(joinpath(@__DIR__,"juliac-buildscript.jl")) $absfile $output_type $add_ccallables`, "OPENBLAS_NUM_THREADS" => 1, "JULIA_NUM_THREADS" => 1)
81-
verbose && println("Running: $cmd")
82-
if !success(pipeline(cmd; stdout, stderr))
83-
println(stderr, "\nFailed to compile $file")
84-
exit(1)
68+
function precompile_env()
69+
# Pre-compile the environment
70+
# (otherwise obscure error messages will occur)
71+
cmd = addenv(`$julia_cmd --project=$(Base.active_project()) -e "using Pkg; Pkg.precompile()"`)
72+
verbose && println("Running: $cmd")
73+
if !success(pipeline(cmd; stdout, stderr))
74+
println(stderr, "\nError encountered during pre-compilation of environment.")
75+
exit(1)
76+
end
8577
end
8678

87-
run(`cc $(cflags) -g -c -o $init_path $initsrc_path`)
79+
function compile_products()
80+
# Compile the Julia code
81+
cmd = addenv(`$julia_cmd --project=$(Base.active_project()) --output-o $img_path --output-incremental=no --strip-ir --strip-metadata $julia_args $(joinpath(@__DIR__,"juliac-buildscript.jl")) $absfile $output_type $add_ccallables`, "OPENBLAS_NUM_THREADS" => 1, "JULIA_NUM_THREADS" => 1)
82+
verbose && println("Running: $cmd")
83+
if !success(pipeline(cmd; stdout, stderr))
84+
println(stderr, "\nFailed to compile $file")
85+
exit(1)
86+
end
8887

89-
if output_type == "--output-lib" || output_type == "--output-sysimage"
90-
of, ext = splitext(outname)
91-
soext = "." * Base.BinaryPlatforms.platform_dlext()
92-
if ext == ""
93-
outname = of * soext
88+
# Compile the initialization code
89+
open(initsrc_path, "w") do io
90+
print(io, """
91+
#include <julia.h>
92+
__attribute__((constructor)) void static_init(void) {
93+
if (jl_is_initialized())
94+
return;
95+
julia_init(JL_IMAGE_IN_MEMORY);
96+
jl_exception_clear();
97+
}
98+
""")
9499
end
100+
run(`cc $(cflags) -g -c -o $init_path $initsrc_path`)
95101
end
96102

97-
julia_libs = Base.shell_split(Base.isdebugbuild() ? "-ljulia-debug -ljulia-internal-debug" : "-ljulia -ljulia-internal")
98-
try
99-
if output_type == "--output-lib"
100-
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
101-
elseif output_type == "--output-sysimage"
102-
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $(julia_libs)`)
103-
else
104-
run(`cc $(allflags) -o $outname -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
103+
function link_products()
104+
global outname
105+
if output_type == "--output-lib" || output_type == "--output-sysimage"
106+
of, ext = splitext(outname)
107+
soext = "." * Base.BinaryPlatforms.platform_dlext()
108+
if ext == ""
109+
outname = of * soext
110+
end
111+
end
112+
113+
julia_libs = Base.shell_split(Base.isdebugbuild() ? "-ljulia-debug -ljulia-internal-debug" : "-ljulia -ljulia-internal")
114+
try
115+
if output_type == "--output-lib"
116+
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
117+
elseif output_type == "--output-sysimage"
118+
run(`cc $(allflags) -o $outname -shared -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $(julia_libs)`)
119+
else
120+
run(`cc $(allflags) -o $outname -Wl,$(Base.Linking.WHOLE_ARCHIVE) $img_path -Wl,$(Base.Linking.NO_WHOLE_ARCHIVE) $init_path $(julia_libs)`)
121+
end
122+
catch e
123+
println("\nCompilation failed: ", e)
124+
exit(1)
105125
end
106-
catch
107-
println("\nCompilation failed.")
108-
exit(1)
109126
end
127+
128+
precompile_env()
129+
compile_products()
130+
link_products()

0 commit comments

Comments
 (0)