Skip to content

Commit 38e4d7d

Browse files
committed
ability to precompile multiple packages
1 parent f9ca262 commit 38e4d7d

File tree

2 files changed

+90
-41
lines changed

2 files changed

+90
-41
lines changed

src/PackageCompiler.jl

Lines changed: 79 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,14 @@ const sysimage_binaries = (
99
"sys.o", "sys.$(Libdl.dlext)", "sys.ji", "inference.o", "inference.ji"
1010
)
1111

12-
function snoop(path, compilationfile, csv, reuse)
12+
function snoop(path, compilationfile, csv)
1313
cd(@__DIR__)
1414
# Snoop compiler can't handle the path as a variable, so we just create a file
15-
if !reuse
16-
open(joinpath("snoopy.jl"), "w") do io
17-
println(io, "include(\"$(escape_string(path))\")")
18-
end
19-
SnoopCompile.@snoop csv begin
20-
include("snoopy.jl")
21-
end
15+
open(joinpath("snoopy.jl"), "w") do io
16+
println(io, "include(\"$(escape_string(path))\")")
17+
end
18+
SnoopCompile.@snoop csv begin
19+
include("snoopy.jl")
2220
end
2321
data = SnoopCompile.read(csv)
2422
pc = SnoopCompile.parcel(reverse!(data[2]))
@@ -98,44 +96,68 @@ function get_root_dir(path)
9896
end
9997
end
10098

101-
function snoop_package(package::String, sysimg_tmp, reuse)
99+
function snoop_package(package::String, rel_snoop_file, sysimg_tmp, reuse)
102100
precompile_file = joinpath(sysimg_tmp, "precompile.jl")
103-
snoop(
104-
joinpath(testroot, "runtests.jl"),
105-
precompile_file,
106-
joinpath(sysimg_tmp, "snooped.csv"),
107-
reuse
108-
)
101+
109102
end
110103

111-
function compile_package(package::String...; force = false, reuse = false, debug = false)
112-
113-
realpath = if ispath(package)
114-
normpath(abspath(package))
115-
else
116-
Pkg.dir(package)
104+
sysimg_folder(files...) = normpath(abspath(joinpath(@__DIR__, "..", "sysimg", files...)))
105+
sysimgbackup_folder(files...) = sysimg_folder("backup", files...)
106+
package_folder(package...) = normpath(abspath(joinpath(@__DIR__, "..", "packages", package...)))
107+
108+
109+
function compile_package(packages...; kw_args...)
110+
args = map(packages) do package
111+
# If no explicit path to a seperate precompile file, use runtests
112+
isa(package, String) && return (package, "test/runtests.jl")
113+
isa(package, Tuple{String, String}) && return package
114+
error("Unrecognized package. Use `packagename::String`, or (packagename::String, rel_path_to_testfile::String). Found: $package")
117115
end
118-
testroot = joinpath(realpath, "test")
119-
sysimg_tmp = normpath(joinpath(@__DIR__, "..", "sysimg_tmp", get_root_dir(realpath)))
120-
sysimg_backup = joinpath(@__DIR__, "..", "sysimg_backup")
121-
isdir(sysimg_backup) || mkpath(sysimg_tmp)
122-
isdir(sysimg_tmp) || mkpath(sysimg_tmp)
116+
compile_package(args...; kw_args...)
117+
end
118+
119+
function snoop_userimg(userimg, packages::Tuple{String, String}...)
120+
snooped_precompiles = map(packages) do package_snoopfile
121+
package, snoopfile = package_snoopfile
122+
abs_package_path = if ispath(package)
123+
normpath(abspath(package))
124+
else
125+
Pkg.dir(package)
126+
end
127+
file2snoop = normpath(abspath(joinpath(abs_package_path, snoopfile)))
128+
package = package_folder(get_root_dir(abs_package_path))
129+
isdir(package) || mkpath(package)
130+
precompile_file = joinpath(package, "precompile.jl")
131+
snoop(
132+
file2snoop,
133+
precompile_file,
134+
joinpath(package, "snooped.csv")
135+
)
136+
precompile_file
137+
end
138+
open(userimg, "w") do io
139+
for path in snooped_precompiles
140+
write(io, open(read, path))
141+
println(io)
142+
end
143+
end
144+
userimg
145+
end
123146

124-
build_sysimg(joinpath(sysimg_tmp, "sys"), "native", precompile_file)
147+
function compile_package(packages::Tuple{String, String}...; force = false, reuse = false, debug = false)
148+
userimg = sysimg_folder("precompile.jl")
149+
if !reuse
150+
snoop_userimg(userimg, packages...)
151+
end
152+
image_path = sysimg_folder("sys")
153+
build_sysimg(image_path, "native", userimg)
125154
if force
126155
try
127-
syspath = default_sysimg_path(debug)
128-
for file in sysimage_binaries
129-
# backup
130-
bfile = joinpath(sysimg_backup, file)
131-
sfile = joinpath(dirname(syspath), file)
132-
if !isfile(bfile) # use the one that is already there
133-
mv(sfile, bfile, remove_destination = true)
134-
else
135-
mv(sfile, sfile*".old", remove_destination = true) # remove so we don't overwrite (seems to be problematic on windows)
136-
end
137-
mv(joinpath(sysimg_tmp, file), sfile, remove_destination = false)
138-
end
156+
replace_jl_sysimg(debug)
157+
info(
158+
"Replaced system image successfully. Next start of julia will load the newly compiled system image.
159+
If you encounter any errors with the new julia image, try `PackageCompiler.revert([debug = false])`"
160+
)
139161
catch e
140162
warn("An error has occured while replacing sysimg files:")
141163
warn(e)
@@ -145,9 +167,26 @@ function compile_package(package::String...; force = false, reuse = false, debug
145167
else
146168
info("""
147169
Not replacing system image.
148-
You can start julia with julia -J $(joinpath(sysimg_tmp, "sys")) to load the compiled files.
170+
You can start julia with julia -J $(image_path) to load the compiled files.
149171
""")
150172
end
151173
end
152174

175+
176+
function replace_jl_sysimg(debug = false)
177+
syspath = default_sysimg_path(debug)
178+
for file in sysimage_binaries
179+
# backup
180+
bfile = sysimgbackup_folder(file)
181+
sfile = joinpath(dirname(syspath), file)
182+
if !isfile(bfile) # use the one that is already there
183+
mv(sfile, bfile, remove_destination = true)
184+
else
185+
mv(sfile, sfile*".old", remove_destination = true) # remove so we don't overwrite (seems to be problematic on windows)
186+
end
187+
mv(joinpath(sysimg_tmp, file), sfile, remove_destination = false)
188+
end
189+
end
190+
191+
153192
end # module

test/runtests.jl

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,15 @@ using Base.Test
33

44
# If this works without error we should be in pretty good shape!
55
# This command will use the runtest.jl of Matcha to find out what functions to precompile!
6-
PackageCompiler.compile_package("Matcha", false) # false to not force overwriting julia's current system image
6+
PackageCompiler.compile_package("Matcha", "UnicodeFun", force = false, reuse = false) # false to not force overwriting julia's current system image
7+
# build again, with resuing the snoop file
8+
PackageCompiler.compile_package("Matcha", "UnicodeFun", force = false, reuse = true)
79
# TODO test revert - I suppose i wouldn't have enough rights on travis to move around dll's?
10+
11+
@testset "basic tests" begin
12+
@test isfile(PackageCompiler.sysimg_folder("sys.$(Libdl.dlext)"))
13+
userimg = PackageCompiler.sysimg_folder("precompile.jl")
14+
@test isfile(userimg)
15+
# Make sure we actually snooped stuff
16+
@test length(readlines(userimg)) > 700
17+
end

0 commit comments

Comments
 (0)