Skip to content

Commit 2fc5d86

Browse files
authored
Merge pull request #19 from JuliaLang/sd/nativeimage
add back option to build native image
2 parents 7837ade + e2a3108 commit 2fc5d86

File tree

5 files changed

+85
-12
lines changed

5 files changed

+85
-12
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ compile_package("Matcha", "relative/path/for_snooping.jl")
2727
revert()
2828

2929
# Or if you simply want to get a native system image e.g. when you have downloaded the generic Julia install:
30-
build_clean_image()
30+
build_native_image()
3131
```
3232

3333

src/PackageCompiler.jl

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ iswindows() && using WinRPM
2121
include("static_julia.jl")
2222
include("api.jl")
2323
include("snooping.jl")
24+
include("system_image.jl")
2425

2526
const sysimage_binaries = (
2627
"sys.o", "sys.$(Libdl.dlext)", "sys.ji", "inference.o", "inference.ji"
@@ -36,6 +37,12 @@ function copy_system_image(src, dest, ignore_missing = false)
3637
ignore_missing && continue
3738
error("No file: $srcfile")
3839
end
40+
if isfile(destfile)
41+
if isfile(destfile * ".backup")
42+
rm(destfile * ".backup", force = true)
43+
end
44+
mv(destfile, destfile * ".backup", remove_destination = true)
45+
end
3946
info("Copying system image: $srcfile to $destfile")
4047
cp(srcfile, destfile, remove_destination = true)
4148
end
@@ -55,15 +62,7 @@ function replace_jl_sysimg(image_path, debug = false)
5562
end
5663

5764

58-
"""
59-
Builds a clean system image, similar to a fresh Julia install.
60-
Can also be used to build a native system image for a downloaded cross compiled julia binary.
61-
"""
62-
function build_clean_image(debug = false)
63-
backup = sysimgbackup_folder()
64-
build_sysimg(backup, joinpath(@__DIR__, "empty_userimg.jl"))
65-
copy_system_image(backup, default_sysimg_path(debug))
66-
end
65+
6766

6867
"""
6968
Reverts a forced compilation of the system image.
@@ -77,7 +76,7 @@ function revert(debug = false)
7776
copy_system_image(sysimg_backup, syspath)
7877
else
7978
warn("No backup found but restoring. Need to build a new system image from scratch")
80-
build_clean_image(debug)
79+
build_native_image(debug)
8180
end
8281
end
8382

@@ -177,7 +176,7 @@ function compile_package(packages::Tuple{String, String}...; force = false, reus
177176
end
178177

179178

180-
export compile_package, revert, build_clean_image
179+
export compile_package, revert, build_native_image
181180

182181

183182
end # module

src/api.jl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,14 @@ function build_shared_lib(
5252
object = true, shared = true, executable = false, julialibs = true,
5353
)
5454
end
55+
56+
57+
"""
58+
Builds a clean system image, similar to a fresh Julia install.
59+
Can also be used to build a native system image for a downloaded cross compiled julia binary.
60+
"""
61+
function build_native_image(debug = false)
62+
backup = sysimgbackup_folder()
63+
compile_system_image(joinpath(backup, "sys"), "native")
64+
copy_system_image(backup, default_sysimg_path(debug))
65+
end

src/system_image.jl

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
function default_sysimg_path(debug = false)
2+
ext = debug ? "sys-debug" : "sys"
3+
if is_unix()
4+
dirname(splitext(Libdl.dlpath(ext))[1])
5+
else
6+
joinpath(dirname(JULIA_HOME), "lib", "julia")
7+
end
8+
end
9+
10+
function compile_system_image(sysimg_path, cpu_target; debug = false)
11+
# Enter base and setup some useful paths
12+
base_dir = dirname(Base.find_source_file("sysimg.jl"))
13+
cd(base_dir) do
14+
julia = "julia"
15+
cc = system_compiler()
16+
# Ensure we have write-permissions to wherever we're trying to write to
17+
try
18+
touch("$sysimg_path.ji")
19+
catch
20+
err_msg = "Unable to modify $sysimg_path.ji, ensure parent directory exists "
21+
err_msg *= "and is writable; absolute paths work best.)"
22+
error(err_msg)
23+
end
24+
# Start by building inference.{ji,o}
25+
inference_path = joinpath(dirname(sysimg_path), "inference")
26+
info("Building inference.o")
27+
info("$julia -C $cpu_target --output-ji $inference_path.ji --output-o $inference_path.o coreimg.jl")
28+
run(`$julia -C $cpu_target --output-ji $inference_path.ji --output-o $inference_path.o coreimg.jl`)
29+
30+
# Bootstrap off of that to create sys.{ji,o}
31+
info("Building sys.o")
32+
info("$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl")
33+
run(`$julia -C $cpu_target --output-ji $sysimg_path.ji --output-o $sysimg_path.o -J $inference_path.ji --startup-file=no sysimg.jl`)
34+
35+
link_sysimg(sysimg_path, cc, debug)
36+
end
37+
end
38+
39+
# Link sys.o into sys.$(dlext)
40+
function link_sysimg(sysimg_path, cc = system_compiler(), debug = false)
41+
42+
julia_libdir = dirname(Libdl.dlpath(debug ? "libjulia-debug" : "libjulia"))
43+
44+
FLAGS = ["-L$julia_libdir"]
45+
46+
push!(FLAGS, "-shared")
47+
push!(FLAGS, debug ? "-ljulia-debug" : "-ljulia")
48+
if is_windows()
49+
push!(FLAGS, "-lssp")
50+
end
51+
52+
sysimg_file = "$sysimg_path.$(Libdl.dlext)"
53+
info("Linking sys.$(Libdl.dlext)")
54+
info("$cc $(join(FLAGS, ' ')) -o $sysimg_file $sysimg_path.o")
55+
# Windows has difficulties overwriting a file in use so we first link to a temp file
56+
run(`$cc $FLAGS -o $sysimg_file $sysimg_path.o`)
57+
end

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,10 @@ img_file = PackageCompiler.compile_package("Matcha", "UnicodeFun", force = false
1515
# Make sure we actually snooped stuff
1616
@test length(readlines(userimg)) > 700
1717
@test success(`julia -J $(img_file)`)
18+
mktempdir() do dir
19+
sysfile = joinpath(dir, "sys")
20+
PackageCompiler.compile_system_image(sysfile, "native")
21+
@test isfile(sysfile * ".o")
22+
@test isfile(sysfile * ".$(Libdl.dlext)")
23+
end
1824
end

0 commit comments

Comments
 (0)