Skip to content

Commit 63865ac

Browse files
author
KristofferC
committed
only bundle libraries that are needed by Base or an stdlib dependency
(cherry picked from commit af35e310c64476fb3721a0a1c63a1bce8855086e)
1 parent 55073e1 commit 63865ac

File tree

2 files changed

+286
-19
lines changed

2 files changed

+286
-19
lines changed

Project.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "2.0.9"
44

55
[deps]
66
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
7+
Glob = "c27321d9-0574-5035-807b-f59d2c89b15c"
78
LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
89
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
910
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

src/PackageCompiler.jl

Lines changed: 285 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ using LazyArtifacts
99
using UUIDs: UUID, uuid1
1010
using RelocatableFolders
1111
using TOML
12+
using Glob
1213

1314
export create_sysimage, create_app, create_library
1415

@@ -93,10 +94,12 @@ sysimage_modules() = map(x->x.name, Base._sysimage_modules)
9394
stdlibs_in_sysimage() = intersect(_STDLIBS, sysimage_modules())
9495

9596
# TODO: Also check UUIDs for stdlibs, not only names
96-
function gather_stdlibs_project(ctx)
97+
function gather_stdlibs_project(ctx; only_in_sysimage::Bool=true)
9798
@assert ctx.env.manifest !== nothing
98-
sysimage_stdlibs = stdlibs_in_sysimage()
99-
return String[pkg.name for (_, pkg) in ctx.env.manifest if pkg.name in sysimage_stdlibs]
99+
stdlibs = only_in_sysimage ? stdlibs_in_sysimage() : _STDLIBS
100+
stdlib_names = String[pkg.name for (_, pkg) in ctx.env.manifest]
101+
filter!(pkg -> pkg in stdlibs, stdlib_names)
102+
return stdlib_names
100103
end
101104

102105
function check_packages_in_project(ctx, packages)
@@ -700,12 +703,15 @@ function create_app(package_dir::String,
700703
executables = [ctx.env.pkg.name => "julia_main"]
701704
end
702705
try_rm_dir(app_dir; force)
703-
bundle_artifacts(ctx, app_dir; include_lazy_artifacts)
704-
bundle_julia_libraries(app_dir)
706+
707+
stdlibs = filter_stdlibs ? gather_stdlibs_project(ctx; only_in_sysimage=false) : _STDLIBS
708+
bundle_julia_libraries(app_dir, stdlibs)
705709
bundle_julia_executable(app_dir)
706710
bundle_project(ctx, app_dir)
707711
bundle_cert(app_dir)
708712

713+
bundle_artifacts(ctx, app_dir; include_lazy_artifacts)
714+
709715
sysimage_path = joinpath(app_dir, "lib", "julia", "sys." * Libdl.dlext)
710716

711717
package_name = ctx.env.pkg.name
@@ -885,10 +891,11 @@ function create_library(package_dir::String,
885891
lib_name = something(lib_name, ctx.env.pkg.name)
886892
try_rm_dir(dest_dir; force)
887893
mkpath(dest_dir)
888-
bundle_julia_libraries(dest_dir)
889-
bundle_artifacts(ctx, dest_dir; include_lazy_artifacts)
894+
stdlibs = filter_stdlibs ? gather_stdlibs_project(ctx; only_in_sysimage=false) : _STDLIBS
895+
bundle_julia_libraries(dest_dir, stdlibs)
890896
bundle_headers(dest_dir, header_files)
891897
bundle_cert(dest_dir)
898+
bundle_artifacts(ctx, dest_dir; include_lazy_artifacts)
892899

893900
lib_dir = Sys.iswindows() ? joinpath(dest_dir, "bin") : joinpath(dest_dir, "lib")
894901

@@ -1018,20 +1025,275 @@ function bundle_julia_executable(dir::String)
10181025
cp(joinpath(Sys.BINDIR::String, name), joinpath(bindir, name); force=true)
10191026
end
10201027

1021-
function bundle_julia_libraries(dest_dir)
1022-
app_libdir = joinpath(dest_dir, Sys.isunix() ? "lib" : "bin")
1023-
mkpath(app_libdir)
1024-
cp(julia_libdir(), app_libdir; force=true)
1025-
# We do not want to bundle the sysimg
1026-
default_sysimg_name = "sys." * Libdl.dlext
1027-
rm(joinpath(app_libdir, "julia", default_sysimg_name); force=true)
1028-
# Remove debug symbol libraries
1029-
if Sys.isapple()
1030-
v = string(VERSION.major, ".", VERSION.minor)
1031-
rm(joinpath(app_libdir, "libjulia.$v.dylib.dSYM"); force=true, recursive=true)
1032-
rm(joinpath(app_libdir, "julia", "sys.dylib.dSYM"); force=true, recursive=true)
1028+
1029+
1030+
# Goes into `lib/julia`
1031+
const libjulia_list =
1032+
if Sys.islinux()
1033+
[
1034+
"libLLVM-*jl.so*"
1035+
"libatomic.so*"
1036+
"libgcc_s.so*"
1037+
"libgmp.so*" # I guess the xx version is not needed?
1038+
"libjulia-codegen.so*"
1039+
"libjulia-internal.so*"
1040+
"libmpfr.so*"
1041+
"libopenlibm.so*"
1042+
"libpcre2-8.so*"
1043+
"libssp.so*"
1044+
"libstdc++.so*"
1045+
"libunwind.so*"
1046+
"libuv.so*"
1047+
"libz.so*"
1048+
]
1049+
elseif Sys.isapple()
1050+
[
1051+
"libLLVM*.dylib" # why no 13jl prefix here like for the others?
1052+
"libatomic*.dylib"
1053+
"libgcc_s*.dylib"
1054+
"libgmp*.dylib"
1055+
"libjulia-codegen*.dylib"
1056+
"libjulia-internal*.dylib"
1057+
"libmpfr*.dylib"
1058+
"libopenlibm*.dylib"
1059+
"libpcre2-8*.dylib"
1060+
"libssp*.dylib"
1061+
"libstdc++*.dylib"
1062+
"libunwind*.dylib"
1063+
"libuv*.dylib"
1064+
"libz*.dylib"
1065+
]
1066+
elseif Sys.iswindows()
1067+
[
1068+
"libLLVM-*jl.dll"
1069+
"libLTO.dll"
1070+
"libatomic*.dll"
1071+
"libgcc_s_seh*.dll"
1072+
"libgmp*.dll"
1073+
"libjulia-codegen.dll"
1074+
"libjulia-internal.dll"
1075+
"libjulia.dll"
1076+
1077+
# Why are these needed?
1078+
"libRemarks.dll"
1079+
"libmlir_async_runtime.dll"
1080+
"libmlir_c_runner_utils.dll"
1081+
"libmlir_runner_utils.dll"
1082+
1083+
"libmpfr*.dll"
1084+
"libopenlibm.dll"
1085+
"libpcre2*.dll"
1086+
"libssp*.dll"
1087+
"libuv-2.dll"
1088+
"libwinpthread*.dll"
1089+
"libz.dll"
1090+
]
1091+
else
1092+
error("unknown os")
1093+
end
1094+
1095+
1096+
# Goes into `lib`
1097+
const lib_list = String[
1098+
if Sys.islinux()
1099+
"libjulia.so*"
1100+
elseif Sys.isapple()
1101+
"libjulia*.dylib"
1102+
elseif Sys.iswindows()
1103+
end
1104+
]
1105+
1106+
if Base.USE_BLAS64
1107+
const libsuffix = "64_"
1108+
else
1109+
const libsuffix = ""
1110+
end
1111+
1112+
1113+
const jll_libs = Dict{String, Vector{String}}(
1114+
"CompilerSupportLibraries_jll" =>
1115+
[
1116+
"libgomp"
1117+
"libquadmath"
1118+
"libgfortran"
1119+
],
1120+
"dSFMT_jll" =>
1121+
[
1122+
"libdSFMT"
1123+
],
1124+
"GMP_jll" =>
1125+
[
1126+
"libgmp"
1127+
"libgmpxx"
1128+
],
1129+
"libblastrampoline_jll" =>
1130+
[
1131+
"libblastrampoline"
1132+
],
1133+
"LibCURL_jll" =>
1134+
[
1135+
"libcurl"
1136+
],
1137+
"LibGit2_jll" =>
1138+
[
1139+
"libgit2"
1140+
],
1141+
"libLLVM_jll" =>
1142+
[
1143+
"libLLVM"
1144+
],
1145+
"LibSSH2_jll" =>
1146+
[
1147+
"libssh2"
1148+
],
1149+
# Only on Linux?
1150+
"LibUnwind_jll" =>
1151+
[
1152+
"libunwind"
1153+
],
1154+
"LibUV_jll" =>
1155+
[
1156+
"libuv"
1157+
],
1158+
# Only on Mac?
1159+
"LLVMLibUnwind_jll" =>
1160+
[
1161+
"libunwind"
1162+
],
1163+
"MbedTLS_jll" =>
1164+
[
1165+
"libmbedcrypto"
1166+
"libmbedtls"
1167+
"libmbedx509"
1168+
],
1169+
"MPFR_jll:" =>
1170+
[
1171+
"libmpfr"
1172+
],
1173+
"nghttp2_jll:" =>
1174+
[
1175+
"libnghttp2"
1176+
],
1177+
"OpenBLAS_jll:" =>
1178+
[
1179+
"libopenblas$(libsuffix)"
1180+
],
1181+
"OpenLibm_jll:" =>
1182+
[
1183+
"libopenlibm"
1184+
],
1185+
"PCRE2_jll" =>
1186+
[
1187+
"libpcre2-8"
1188+
],
1189+
"SuiteSparse_jll" =>
1190+
["libamd"
1191+
"libbtf"
1192+
"libcamd"
1193+
"libccolamd"
1194+
"libcholmod"
1195+
"libcolamd"
1196+
"libklu"
1197+
"libldl"
1198+
"librbio"
1199+
"libspqr"
1200+
"libsuitesparseconfig"
1201+
"libumfpack"
1202+
],
1203+
"Zlib_jll" =>
1204+
[
1205+
"libz"
1206+
],
1207+
)
1208+
1209+
function glob_pattern_lib(lib)
1210+
Sys.iswindows() ? lib * ".dll" :
1211+
Sys.isapple() ? lib * "*.dylib" :
1212+
Sys.islinux() ? lib* ".so*" :
1213+
error("unknown os")
1214+
end
1215+
1216+
1217+
1218+
# TODO: Detangle printing from business logic
1219+
function bundle_julia_libraries(dest_dir, stdlibs)
1220+
app_lib_dir = joinpath(dest_dir, Sys.isunix() ? "lib" : "bin")
1221+
app_libjulia_dir = Sys.isunix() ? joinpath(app_lib_dir, "julia") : app_lib_dir
1222+
lib_dir = julia_libdir()
1223+
libjulia_dir = Sys.isunix() ? joinpath(lib_dir, "julia") : lib_dir
1224+
1225+
mkpath(app_lib_dir)
1226+
Sys.isunix() && mkpath(app_libjulia_dir)
1227+
1228+
libs = Pair{String, String}
1229+
1230+
tot_libsize = 0
1231+
printstyled("PackageCompiler: bundled libraries:\n")
1232+
1233+
println(" ├── Base:")
1234+
first = true
1235+
for lib in libjulia_list
1236+
matches = glob(lib, libjulia_dir)
1237+
for match in matches
1238+
mark = "├──"
1239+
1240+
cp(match, joinpath(app_libjulia_dir, basename(match)))
1241+
libsize = lstat(match).size
1242+
tot_libsize += libsize
1243+
if libsize > 1024
1244+
println("$mark ", basename(match), " - ", pretty_byte_str(libsize))
1245+
first = false
1246+
end
1247+
end
1248+
end
1249+
1250+
for lib in lib_list
1251+
mark = "├──"
1252+
matches = glob(lib, lib_dir)
1253+
for match in matches
1254+
libsize = lstat(match).size
1255+
tot_libsize += libsize
1256+
if libsize > 1024
1257+
println("$mark ", basename(match), " - ", pretty_byte_str(libsize))
1258+
end
1259+
cp(match, joinpath(app_lib_dir, basename(match)))
1260+
end
10331261
end
1262+
1263+
println(" ├── Stdlibs:")
1264+
for stdlib in stdlibs
1265+
printed_stdlib = false
1266+
libs = get(Vector{String}, jll_libs, stdlib)
1267+
first_lib = true
1268+
for lib in libs
1269+
lib = glob_pattern_lib(lib)
1270+
matches = glob(lib, libjulia_dir)
1271+
for match in matches
1272+
destpath = joinpath(app_libjulia_dir, basename(match))
1273+
if !isfile(destpath)
1274+
if !printed_stdlib && !isempty(match)
1275+
mark = "├──"
1276+
printed_stdlib = true
1277+
println("$mark ", stdlib)
1278+
end
1279+
1280+
libsize = lstat(match).size
1281+
mark = "├──"
1282+
if libsize > 1024
1283+
println(" │ │ $mark ", basename(match), " - ", pretty_byte_str(libsize))
1284+
first_lib = false
1285+
end
1286+
cp(match, destpath)
1287+
tot_libsize += libsize
1288+
end
1289+
end
1290+
end
1291+
end
1292+
1293+
println(" Total library file size: ", pretty_byte_str(tot_libsize))
1294+
10341295
return
1296+
10351297
end
10361298

10371299
function recursive_dir_size(path)
@@ -1200,4 +1462,8 @@ function bundle_cert(dest_dir)
12001462
cp(cert_path, joinpath(share_path, "cert.pem"))
12011463
end
12021464

1465+
function bundle_libraries(src_dir, dest_dir)
1466+
1467+
end
1468+
12031469
end # module

0 commit comments

Comments
 (0)