forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
build_sysimg.jl
168 lines (148 loc) · 6.69 KB
/
build_sysimg.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
#!/usr/bin/env julia
# Build a system image binary at sysimg_path.dlext. By default, put the system image
# next to libjulia (except on Windows, where it goes in $JULIA_HOME\..\lib\julia)
# Allow insertion of a userimg via userimg_path. If sysimg_path.dlext is currently loaded into memory,
# don't continue unless force is set to true. Allow targeting of a CPU architecture via cpu_target
@unix_only const default_sysimg_path = joinpath(dirname(Libdl.dlpath("libjulia")),"sys")
@windows_only const default_sysimg_path = joinpath(JULIA_HOME,"..","lib","julia","sys")
function build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", userimg_path=nothing; force=false)
# Quit out if a sysimg is already loaded and is in the same spot as sysimg_path, unless forcing
sysimg = Libdl.dlopen_e("sys")
if sysimg != C_NULL
if !force && Base.samefile(Libdl.dlpath(sysimg), "$(sysimg_path).$(Libdl.dlext)")
info("System image already loaded at $(Libdl.dlpath(sysimg)), set force to override")
return
end
end
# Canonicalize userimg_path before we enter the base_dir
if userimg_path != nothing
userimg_path = abspath(userimg_path)
end
# Enter base/ and setup some useful paths
base_dir = dirname(Base.find_source_file("sysimg.jl"))
cd(base_dir) do
try
julia = joinpath(JULIA_HOME, "julia")
ld = find_system_linker()
# Ensure we have write-permissions to wherever we're trying to write to
try
touch("$sysimg_path.ji")
catch
err_msg = "Unable to modify $sysimg_path.ji, ensure parent directory exists "
err_msg *= "and is writable. Absolute paths work best. Do you need to run this with sudo?)"
error( err_msg )
end
# Copy in userimg.jl if it exists...
if userimg_path != nothing
if !isreadable(userimg_path)
error("$userimg_path is not readable, ensure it is an absolute path!")
end
cp(userimg_path, "userimg.jl")
end
# Start by building sys0.{ji,o}
sys0_path = joinpath(dirname(sysimg_path), "sys0")
info("Building sys0.o...")
println("$julia -C $cpu_target --build $sys0_path sysimg.jl")
run(`$julia -C $cpu_target --build $sys0_path sysimg.jl`)
# Bootstrap off of that to create sys.{ji,o}
info("Building sys.o...")
println("$julia -C $cpu_target --build $sysimg_path -J $sys0_path.ji -f sysimg.jl")
run(`$julia -C $cpu_target --build $sysimg_path -J $sys0_path.ji -f sysimg.jl`)
if ld != nothing
link_sysimg(sysimg_path, ld)
else
info("System image successfully built at $sysimg_path.ji")
end
if !Base.samefile("$default_sysimg_path.ji", "$sysimg_path.ji")
info("To run Julia with this image loaded, run: julia -J $sysimg_path.ji")
else
info("Julia will automatically load this system image at next startup")
end
finally
# Cleanup userimg.jl
if isfile("userimg.jl")
rm("userimg.jl")
end
end
end
end
# Search for a linker to link sys.o into sys.dl_ext. Honor LD environment variable.
function find_system_linker()
if haskey( ENV, "LD" )
if !success(`$(ENV["LD"]) -v`)
warn("Using linker override $(ENV["LD"]), but unable to run `$(ENV["LD"]) -v`")
end
return ENV["LD"]
end
# On Windows, check to see if WinRPM is installed, and if so, see if gcc is installed
@windows_only try
require("WinRPM")
winrpmgcc = joinpath(WinRPM.installdir,"usr","$(Sys.ARCH)-w64-mingw32",
"sys-root","mingw","bin","gcc.exe")
if success(`$winrpmgcc --version`)
return winrpmgcc
else
throw()
end
catch
warn("Install GCC via `Pkg.add(\"WinRPM\"); WinRPM.install(\"gcc\")` to generate sys.dll for faster startup times")
end
# See if `ld` exists
try
if success(`ld -v`)
return "ld"
end
end
warn( "No supported linker found; startup times will be longer" )
end
# Link sys.o into sys.$(dlext)
function link_sysimg(sysimg_path=default_sysimg_path, ld=find_system_linker())
julia_libdir = dirname(Libdl.dlpath("libjulia"))
FLAGS = ["-L$julia_libdir"]
if OS_NAME == :Darwin
push!(FLAGS, "-dylib")
push!(FLAGS, "-undefined")
push!(FLAGS, "dynamic_lookup")
push!(FLAGS, "-macosx_version_min")
push!(FLAGS, "10.7")
else
push!(FLAGS, "-shared")
# on windows we link using gcc for now
wl = @windows? "-Wl," : ""
push!(FLAGS, wl * "--unresolved-symbols")
push!(FLAGS, wl * "ignore-all")
end
@windows_only append!(FLAGS, ["-ljulia", "-lssp-0"])
info("Linking sys.$(Libdl.dlext)")
run(`$ld $FLAGS -o $sysimg_path.$(Libdl.dlext) $sysimg_path.o`)
info("System image successfully built at $sysimg_path.$(Libdl.dlext)")
@windows_only begin
if convert(VersionNumber, Base.libllvm_version) < v"3.5.0"
LLVM_msg = "Building sys.dll on Windows against LLVM < 3.5.0 can cause incorrect backtraces!"
LLVM_msg *= " Delete generated sys.dll to avoid these problems"
warn( LLVM_msg )
end
end
end
# When running this file as a script, try to do so with default values. If arguments are passed
# in, use them as the arguments to build_sysimg above
if !isinteractive()
if length(ARGS) > 4 || ("--help" in ARGS || "-h" in ARGS)
println("Usage: build_sysimg.jl <sysimg_path> <cpu_target> <usrimg_path.jl> [--force] [--help]")
println(" <sysimg_path> is an absolute, extensionless path to store the system image at")
println(" <cpu_target> is an LLVM cpu target to build the system image against")
println(" <usrimg_path.jl> is the path to a user image to be baked into the system image")
println(" --force Set if you wish to overwrite the default system image")
println(" --help Print out this help text and exit")
println()
println(" Example:")
println(" build_sysimg.jl /usr/local/lib/julia/sys core2 ~/my_usrimg.jl --force")
println()
println(" Running this script with no arguments is equivalent to calling it via")
println(" build_sysimg.jl $(default_sysimg_path) native")
return 0
end
force_flag = "--force" in ARGS
filter!(x -> x != "--force", ARGS)
build_sysimg(ARGS..., force=force_flag)
end