-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9376 from JuliaLang/sf/build_sysimg3.0
Support building of system image in binary builds
- Loading branch information
Showing
11 changed files
with
263 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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(Sys.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 = dlopen_e("sys") | ||
if sysimg != C_NULL | ||
if !force && Base.samefile(Sys.dlpath(sysimg), "$(sysimg_path).$(Sys.dlext)") | ||
info("System image already loaded at $(Sys.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(Sys.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.$(Sys.dlext)") | ||
run(`$ld $FLAGS -o $sysimg_path.$(Sys.dlext) $sysimg_path.o`) | ||
|
||
info("System image successfully built at $sysimg_path.$(Sys.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.lj> 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 true") | ||
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,3 +8,4 @@ | |
:maxdepth: 1 | ||
|
||
cartesian | ||
sysimg |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
********************* | ||
System Image Building | ||
********************* | ||
|
||
Building the Julia system image | ||
------------------------------- | ||
|
||
Julia ships with a preparsed system image containing the contents of the ``Base`` module, named ``sys.ji``. This file is also precompiled into a shared library called ``sys.{so,dll,dylib}`` on as many platforms as possible, so as to give vastly improved startup times. On systems that do not ship with a precompiled system image file, one can be generated from the source files shipped in Julia's ``DATAROOTDIR/julia/base`` folder. | ||
|
||
This operation is useful for multiple reasons. A user may: | ||
|
||
* Build a precompiled shared library system image on a platform that did not ship with one, thereby improving startup times. | ||
|
||
* Modify ``Base``, rebuild the system image and use the new ``Base`` next time Julia is started. | ||
|
||
* Include a ``userimg.jl`` file that includes packages into the system image, thereby creating a system image that has packages embedded into the startup environment. | ||
|
||
Julia now ships with a script that automates the tasks of building the system image, wittingly named ``build_sysimg.jl`` that lives in ``DATAROOTDIR/julia/``. That is, to include it into a current Julia session, type: | ||
:: | ||
|
||
include(joinpath(JULIA_HOME, Base.DATAROOTDIR, "julia", "build_sysimg.jl")) | ||
|
||
This will include a ``build_sysimg()`` function: | ||
|
||
.. function:: build_sysimg(sysimg_path=default_sysimg_path, cpu_target="native", userimg_path=nothing; force=false) | ||
|
||
Rebuild the system image. Store it in ``sysimg_path``, which defaults to a file named ``sys.ji`` that sits in the same folder as ``libjulia.{so,dylib}``, except on Windows where it defaults to ``JULIA_HOME/../lib/julia/sys.ji``. | ||
Use the cpu instruction set given by ``cpu_target``. Valid CPU targets are the same as for the ``-C`` option to ``julia``, or the ``-march`` option to ``gcc``. Defaults to ``native``, which means to use all CPU instructions available on the current processor. | ||
Include the user image file given by ``userimg_path``, which should contain directives such as ``using MyPackage`` to include that package in the new system image. | ||
New system image will not replace an older image unless ``force`` is set to true. | ||
|
||
Note that this file can also be run as a script itself, with command line arguments taking the place of arguments passed to the ``build_sysimg`` function. For example, to build a system image in ``/tmp/sys.{so,dll,dylib}``, with the ``core2`` CPU instruction set, a user image of ``~/userimg.jl`` and ``force`` set to ``true``, one would execute: | ||
:: | ||
|
||
julia build_sysimg.jl /tmp/sys core2 ~/userimg.jl --force |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.