Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In Julia 1.12+, in create_fresh_base_sysimage(), use the BuildSettings mechanism to pass the list of sysimages to include in the fresh (non-incremental) base sysimage #997

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 46 additions & 11 deletions src/PackageCompiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -210,14 +210,22 @@ function get_julia_cmd()
end
end

function generate_sysimg_jl_contents(stdlibs::Vector{String})
original_sysimg_source_path = Base.find_source_file("sysimg.jl")
original_sysimg_content = read(original_sysimg_source_path, String)
if VERSION >= v"1.12-"
# In Julia 1.12+, we use BuildSettings, and thus we don't need to rewrite sysimg.jl
# to change the list of stdlibs.
new_sysimage_content = original_sysimg_content
else
# Julia 1.11 and earlier do not support BuildSettings.
# So we need to rewrite sysimg.jl to change the list of stdlibs.

function rewrite_sysimg_jl_only_needed_stdlibs(stdlibs::Vector{String})
sysimg_source_path = Base.find_source_file("sysimg.jl")
sysimg_content = read(sysimg_source_path, String)
# replaces the hardcoded list of stdlibs in sysimg.jl with
# the stdlibs that is given as argument
return replace(sysimg_content,
r"stdlibs = \[(.*?)\]"s => string("stdlibs = [", join(":" .* stdlibs, ",\n"), "]"))
# Replaces the hardcoded list of stdlibs in sysimg.jl with
# the stdlibs that is given as argument
new_sysimg_content = replace(sysimg_content, r"stdlibs = \[(.*?)\]"s => string("stdlibs = [", join(":" .* stdlibs, ",\n"), "]"))
end
return new_sysimg_content
end

function create_fresh_base_sysimage(stdlibs::Vector{String}; cpu_target::String, sysimage_build_args::Cmd)
Expand All @@ -237,7 +245,7 @@ function create_fresh_base_sysimage(stdlibs::Vector{String}; cpu_target::String,
# we can't strip the IR from the base sysimg, so we filter out this flag
# also presumably `--compile=all` and maybe a few others we missed here...
sysimage_build_args_strs = map(p -> "$(p...)", values(sysimage_build_args))
filter!(p -> !contains(p, "--compile") && p ∉ ("--strip-ir",), sysimage_build_args_strs)
filter!(p -> !contains(p, "--compile") && p ("--strip-ir",), sysimage_build_args_strs)
sysimage_build_args = Cmd(sysimage_build_args_strs)

cd(base_dir) do
Expand All @@ -254,16 +262,43 @@ function create_fresh_base_sysimage(stdlibs::Vector{String}; cpu_target::String,

spinner = TerminalSpinners.Spinner(msg = "PackageCompiler: compiling fresh sysimage (incremental=false)")
TerminalSpinners.@spin spinner begin
# Use that to create sys.ji
new_sysimage_content = rewrite_sysimg_jl_only_needed_stdlibs(stdlibs)
new_sysimage_content = generate_sysimg_jl_contents(stdlibs)
new_sysimage_content *= "\nempty!(Base.atexit_hooks)\n"
new_sysimage_source_path = joinpath(tmp, "sysimage_packagecompiler_$(uuid1()).jl")
write(new_sysimage_source_path, new_sysimage_content)

if VERSION >= v"1.12-"
build_settings_source_path = joinpath(tmp, "buildsettings_packagecompiler_$(uuid1()).jl")
open(build_settings_source_path, "w") do io
stdlibs_string = join(stdlibs, ',')
println(io, """
INCLUDE_STDLIBS = "$(stdlibs_string)"
""")
end

# The second positional argument `""` is to pass BUILDROOT="" to Base.jl.
# If we don't have the "", then Base.jl will assume that one of our other
# arguments is the BUILDROOT, which obviously is incorrect.
# https://github.com/JuliaLang/PackageCompiler.jl/issues/989
#
# The --build-settings argument is to pass our BuildSettings file.
# BuildSettings is only available in Julia 1.12+
# https://github.com/JuliaLang/julia/pull/54387
buildsettings_args = `$new_sysimage_source_path "" --build-settings $(build_settings_source_path)`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move all the logic for rewriting the sysimage.jl file into the else branch to show that it is dead on newer julia versions and just use the Base.find_source_file("sysimg.jl") as the argument here to show nothing weird is going on.

else
# Julia 1.11 and earlier do not support BuildSettings.
#
# Julia 1.11 and earlier do not require us to pass BUILDROOT as a positional
# argument.
buildsettings_args = `$new_sysimage_source_path`
end

try
# Use the previously-created corecompiler.ji to create sys.ji
cmd = addenv(`$(get_julia_cmd()) --cpu-target $cpu_target
--sysimage=$tmp_corecompiler_ji
$sysimage_build_args --output-o=$tmp_sys_o
$new_sysimage_source_path`,
$buildsettings_args`,
"JULIA_LOAD_PATH" => "@stdlib")
@debug "running $cmd"

Expand Down
Loading