Skip to content

Commit d7361a5

Browse files
author
KristofferC
committed
fixup many issues with bundling and precompiling stdlibs
1 parent cfd7658 commit d7361a5

File tree

1 file changed

+144
-3
lines changed

1 file changed

+144
-3
lines changed

src/PackageCompiler.jl

Lines changed: 144 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,14 +1036,22 @@ function create_distribution(project_dir::String,
10361036
try_rm_dir(dist_dir; force)
10371037
ensure_default_depot_paths(dist_dir)
10381038

1039-
stdlibs = gather_stdlibs_project(ctx)
1040-
stdlibs = unique(vcat(stdlibs, map(pkg -> pkg.name, stdlibs_in_default_sysimage())))
1041-
bundle_julia_libraries(dist_dir, stdlibs)
1039+
# For distributions, we need to bundle libraries for ALL stdlibs from the running Julia
1040+
all_stdlibs = readdir(Sys.STDLIB)
1041+
bundle_julia_libraries(dist_dir, all_stdlibs)
10421042

10431043
manifest_pkg_entries = gather_dependency_entries(ctx)
10441044
bundle_default_stdlibs(dist_dir)
10451045
bundle_custom_stdlibs(ctx, dist_dir, manifest_pkg_entries, copy_globs)
10461046
bundle_julia_test_files(dist_dir)
1047+
bundle_julia_base_files(dist_dir)
1048+
bundle_julia_compiler_files(dist_dir)
1049+
bundle_julia_support_files(dist_dir)
1050+
1051+
# Get stdlibs that will be in the sysimage (as deps of custom packages)
1052+
stdlib_deps_in_sysimage = gather_dependency_entries(ctx; include_stdlibs=true)
1053+
stdlib_deps_names = [pkg.name for pkg in stdlib_deps_in_sysimage]
1054+
bundle_stdlib_project(dist_dir, stdlib_deps_names)
10471055

10481056
bundle_julia_libexec(ctx, dist_dir)
10491057
bundle_julia_executable(dist_dir)
@@ -1064,6 +1072,8 @@ function create_distribution(project_dir::String,
10641072
script,
10651073
import_into_main=false)
10661074

1075+
precompile_stdlibs(dist_dir, sysimage_path, cpu_target)
1076+
10671077
return nothing
10681078
end
10691079

@@ -1403,6 +1413,137 @@ function bundle_julia_test_files(dest_dir)
14031413
end
14041414
end
14051415

1416+
function bundle_julia_base_files(dest_dir)
1417+
src_base = abspath(Sys.BINDIR, "..", "share", "julia", "base")
1418+
if isdir(src_base)
1419+
dest_base = joinpath(dest_dir, "share", "julia", "base")
1420+
if isdir(dest_base)
1421+
rm(dest_base; recursive=true, force=true)
1422+
end
1423+
cp(src_base, dest_base; force=true)
1424+
end
1425+
end
1426+
1427+
function bundle_julia_compiler_files(dest_dir)
1428+
src_compiler = abspath(Sys.BINDIR, "..", "share", "julia", "Compiler")
1429+
if isdir(src_compiler)
1430+
dest_compiler = joinpath(dest_dir, "share", "julia", "Compiler")
1431+
if isdir(dest_compiler)
1432+
rm(dest_compiler; recursive=true, force=true)
1433+
end
1434+
cp(src_compiler, dest_compiler; force=true)
1435+
end
1436+
end
1437+
1438+
function bundle_julia_support_files(dest_dir)
1439+
src_share = abspath(Sys.BINDIR, "..", "share", "julia")
1440+
dest_share = joinpath(dest_dir, "share", "julia")
1441+
1442+
# Bundle individual files and directories
1443+
for item in ["julia-config.jl", "juliac", "terminfo"]
1444+
src_item = joinpath(src_share, item)
1445+
dest_item = joinpath(dest_share, item)
1446+
if isfile(src_item)
1447+
cp(src_item, dest_item; force=true)
1448+
elseif isdir(src_item)
1449+
if isdir(dest_item)
1450+
rm(dest_item; recursive=true, force=true)
1451+
end
1452+
cp(src_item, dest_item; force=true)
1453+
end
1454+
end
1455+
end
1456+
1457+
function bundle_stdlib_project(dest_dir, packages_in_sysimage::Vector{String})
1458+
# Dynamically generate stdlib Project.toml and Manifest.toml from running Julia's stdlibs
1459+
# Include all stdlibs in manifest for dependency resolution, but only list non-sysimage ones in Project.toml
1460+
dest_stdlib = joinpath(dest_dir, "share", "julia", "stdlib")
1461+
mkpath(dest_stdlib)
1462+
1463+
# Get list of packages in the sysimage
1464+
sysimage_pkgs = Set(map(pkg -> pkg.name, stdlibs_in_default_sysimage()))
1465+
union!(sysimage_pkgs, packages_in_sysimage)
1466+
1467+
# Collect stdlib packages for Project.toml (only non-sysimage)
1468+
stdlib_deps = Dict{String, String}()
1469+
# Collect ALL stdlib packages for Manifest.toml (needed for dependency resolution)
1470+
all_stdlib_deps = Dict{String, String}()
1471+
for pkg_name in readdir(Sys.STDLIB)
1472+
pkg_project = joinpath(Sys.STDLIB, pkg_name, "Project.toml")
1473+
if isfile(pkg_project)
1474+
proj = TOML.parsefile(pkg_project)
1475+
if haskey(proj, "uuid")
1476+
all_stdlib_deps[pkg_name] = proj["uuid"]
1477+
# Only add to Project.toml if not in sysimage
1478+
if !(pkg_name in sysimage_pkgs)
1479+
stdlib_deps[pkg_name] = proj["uuid"]
1480+
end
1481+
end
1482+
end
1483+
end
1484+
1485+
# Generate Project.toml
1486+
project = Dict("deps" => stdlib_deps)
1487+
open(joinpath(dest_stdlib, "Project.toml"), "w") do io
1488+
TOML.print(io, project)
1489+
end
1490+
1491+
# Generate Manifest.toml
1492+
manifest = Dict{String, Any}()
1493+
manifest["julia_version"] = string(VERSION)
1494+
manifest["manifest_format"] = "2.0"
1495+
manifest["deps"] = Dict{String, Any}()
1496+
1497+
# Add each stdlib as a manifest entry (use all_stdlib_deps for complete dependency resolution)
1498+
for (name, uuid) in all_stdlib_deps
1499+
pkg_proj = TOML.parsefile(joinpath(Sys.STDLIB, name, "Project.toml"))
1500+
entry = Dict{String, Any}("uuid" => uuid)
1501+
if haskey(pkg_proj, "version")
1502+
entry["version"] = pkg_proj["version"]
1503+
end
1504+
if haskey(pkg_proj, "deps")
1505+
entry["deps"] = collect(keys(pkg_proj["deps"]))
1506+
end
1507+
manifest["deps"][name] = [entry]
1508+
end
1509+
1510+
open(joinpath(dest_stdlib, "Manifest.toml"), "w") do io
1511+
TOML.print(io, manifest)
1512+
end
1513+
end
1514+
1515+
function precompile_stdlibs(dist_dir, sysimage_path, cpu_target)
1516+
julia_exe = joinpath(dist_dir, "bin", "julia")
1517+
depot_path = joinpath(dist_dir, "share", "julia")
1518+
stdlib_dir = joinpath(depot_path, "stdlib")
1519+
compiled_dir = joinpath(depot_path, "compiled")
1520+
mkpath(compiled_dir)
1521+
1522+
# Precompile all packages in the stdlib that aren't in the sysimage
1523+
precompile_code = """
1524+
println("Active project: ", Base.active_project())
1525+
println("DEPOT_PATH: ", Base.DEPOT_PATH)
1526+
Base.Precompilation.precompilepkgs(configs=[
1527+
`` => Base.CacheFlags(debug_level=2, opt_level=3),
1528+
`` => Base.CacheFlags(check_bounds=1, debug_level=2, opt_level=3)
1529+
]; io=stdout)
1530+
"""
1531+
1532+
# Set JULIA_PROJECT to the stdlib directory so precompilepkgs knows what to precompile
1533+
# Set JULIA_LOAD_PATH to @stdlib like Julia's makefile does
1534+
env = Dict(
1535+
"JULIA_DEPOT_PATH" => depot_path,
1536+
"JULIA_LOAD_PATH" => "@stdlib",
1537+
"JULIA_CPU_TARGET" => cpu_target,
1538+
"JULIA_PROJECT" => stdlib_dir
1539+
)
1540+
1541+
cmd = setenv(`$julia_exe --sysimage=$sysimage_path --startup-file=no -e $precompile_code`, env)
1542+
1543+
@info "Precompiling stdlibs for the distribution..."
1544+
run(cmd)
1545+
end
1546+
14061547
function bundle_default_stdlibs(dest_dir)
14071548
src_stdlib = abspath(Sys.BINDIR, "..", "share", "julia", "stdlib")
14081549
dest_stdlib = joinpath(dest_dir, "share", "julia", "stdlib")

0 commit comments

Comments
 (0)