Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for object caching through pkgimages #47184

Merged
merged 29 commits into from
Dec 27, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0a8e063
Cache objectcode in pkgimages
vchuravy Oct 13, 2022
0f135a3
Improve wording, fix whitespace
timholy Dec 12, 2022
90db48c
Can't reference devdocs from manual
timholy Dec 12, 2022
5043270
Capitalize Xcode correctly
timholy Dec 12, 2022
4e97943
Clarify documentation
timholy Dec 13, 2022
22233f6
Docs: command-line options
timholy Dec 13, 2022
b8872d1
Expand "link" to devdocs
timholy Dec 13, 2022
8b308f1
Update doc/src/manual/command-line-interface.md
timholy Dec 13, 2022
03fe8d7
Merge branch 'master' into vc/external_functions
timholy Dec 13, 2022
58b4ac1
Mixin cpu_target
vchuravy Dec 14, 2022
1785d51
Don't overcount
vchuravy Dec 14, 2022
5c114ba
Update the documentation a bit
vchuravy Dec 14, 2022
71622a1
Reject .ji on pkgimage
vchuravy Dec 14, 2022
6ff3284
fixup! Don't overcount
vchuravy Dec 14, 2022
cb2cd68
Merge branch 'master' into vc/external_functions
timholy Dec 15, 2022
c405552
Fix & test PkgCacheInspector
timholy Dec 15, 2022
6373b89
Split post-load work into separate function
timholy Dec 15, 2022
23ce9aa
Merge branch 'master' into vc/external_functions
IanButterworth Dec 17, 2022
9b6bc2b
fix 32bit test failure
IanButterworth Dec 17, 2022
bb10c8c
Rename command line flag
vchuravy Dec 18, 2022
313bb9a
Apply suggestions from code review
vchuravy Dec 18, 2022
0d469bd
[CompilerSupportLibraries_jll] Upgrade to v1.0.2 and install `libsspd…
giordano Dec 18, 2022
692aa52
Merge branch 'master' into vc/external_functions
timholy Dec 21, 2022
17ff877
Find native code in non-worklist modules
timholy Dec 22, 2022
6e9a670
bump Pkg to a version that does not precompile on add
KristofferC Dec 24, 2022
9f2f0d1
Revert "bump Pkg to a version that does not precompile on add"
KristofferC Dec 25, 2022
0365526
Add MWE for DynamicExpressions failure
timholy Dec 26, 2022
f33c2a6
Simplify test
KristofferC Dec 26, 2022
5fe7c05
Change interposers from weak to internal
vchuravy Dec 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -260,13 +260,21 @@ ifeq ($(OS),WINNT)
-$(INSTALL_M) $(wildcard $(build_bindir)/*.dll) $(DESTDIR)$(bindir)/
ifeq ($(JULIA_BUILD_MODE),release)
-$(INSTALL_M) $(build_libdir)/libjulia.dll.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libjulia-internal.dll.a $(DESTDIR)$(libdir)/
else ifeq ($(JULIA_BUILD_MODE),debug)
-$(INSTALL_M) $(build_libdir)/libjulia-debug.dll.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libjulia-internal-debug.dll.a $(DESTDIR)$(libdir)/
endif

# We have a single exception; we want 7z.dll to live in libexec, not bin, so that 7z.exe can find it.
-mv $(DESTDIR)$(bindir)/7z.dll $(DESTDIR)$(libexecdir)/
-$(INSTALL_M) $(build_bindir)/libopenlibm.dll.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libssp.a $(DESTDIR)$(libdir)/ # TODO use implib
# The rest are compiler dependencies, as an example memcpy is exported by msvcrt
# These are files from mingw32 and required for creating shared libraries like our caches.
-$(INSTALL_M) $(build_libdir)/libgcc_s.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libgcc.a $(DESTDIR)$(libdir)/
-$(INSTALL_M) $(build_libdir)/libmsvcrt.a $(DESTDIR)$(libdir)/
else

# Copy over .dSYM directories directly for Darwin
Expand Down Expand Up @@ -331,6 +339,11 @@ else ifeq ($(JULIA_BUILD_MODE),debug)
$(INSTALL_M) $(build_private_libdir)/sys-debug.$(SHLIB_EXT) $(DESTDIR)$(private_libdir)
endif

# Cache stdlibs
@$(call PRINT_JULIA, $(call spawn,$(JULIA_EXECUTABLE)) --startup-file=no $(JULIAHOME)/contrib/cache_stdlibs.jl)
# CI uses `--check-bounds=yes` which impacts the cache flags
@$(call PRINT_JULIA, $(call spawn,$(JULIA_EXECUTABLE)) --startup-file=no --check-bounds=yes $(JULIAHOME)/contrib/cache_stdlibs.jl)

Comment on lines +342 to +346
Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the caching here, I think the first cache should definitely be done.

I'm okay with the second cache, although I think there's an argument for not including them in the default download, as they're mostly only useful for CI/running Base.runtests(). The main downside is that they do generate some amount of extra data that must be transferred over the internet many times, but it's pretty small, like ~1MB.

# Linux
$ find julia-0d469bd0f8/ -name \*.so | grep CgUe1.so | xargs stat -c '%s' | colsum
814272
# macOS
$ find julia-0d469bd0f8/ -name \*.dylib | grep cGsVO | xargs stat -f '%z' | colsum
1356080

I think 1MB is probably okay for us to just ship unconditionally.

Copy link
Sponsor Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another reason to eagerly precompile is to avoid having testing processes suddenly try to precompile these files multiple times. However, we will still run into multiple processes trying to smash these out if someone does a Base.runtests() from within the development directory (before running make install), right? Perhaps it's better to add these into a function that gets invoked from within Julia itself upon the running of Base.runtests()? Pkg.test() will already precompile everything it needs to, so I don't think we need to worry about user package tests running into this problem.

# Copy in all .jl sources as well
mkdir -p $(DESTDIR)$(datarootdir)/julia/base $(DESTDIR)$(datarootdir)/julia/test
cp -R -L $(JULIAHOME)/base/* $(DESTDIR)$(datarootdir)/julia/base
Expand Down
1 change: 1 addition & 0 deletions base/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ include("threadcall.jl")
include("uuid.jl")
include("pkgid.jl")
include("toml_parser.jl")
include("linking.jl")
include("loading.jl")

# misc useful functions & macros
Expand Down
4 changes: 4 additions & 0 deletions base/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ ifeq ($(DARWIN_FRAMEWORK), 1)
@echo "const DARWIN_FRAMEWORK_NAME = \"$(FRAMEWORK_NAME)\"" >> $@
else
@echo "const DARWIN_FRAMEWORK = false" >> $@
endif
ifeq ($(OS), Darwin)
@echo "const MACOS_PRODUCT_VERSION = \"$(shell sw_vers -productVersion)\"" >> $@
@echo "const MACOS_PLATFORM_VERSION = \"$(shell xcrun --show-sdk-version)\"" >> $@
endif
@echo "const BUILD_TRIPLET = \"$(BB_TRIPLET_LIBGFORTRAN_CXXABI)\"" >> $@

Expand Down
147 changes: 147 additions & 0 deletions base/linking.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license
module Linking

import Base.Libc: Libdl

# inlined LLD_jll
# These get calculated in __init__()
const PATH = Ref("")
const LIBPATH = Ref("")
const PATH_list = String[]
const LIBPATH_list = String[]
const lld_path = Ref{String}()
const lld_exe = Sys.iswindows() ? "lld.exe" : "lld"

if Sys.iswindows()
const LIBPATH_env = "PATH"
const LIBPATH_default = ""
const pathsep = ';'
elseif Sys.isapple()
const LIBPATH_env = "DYLD_FALLBACK_LIBRARY_PATH"
const LIBPATH_default = "~/lib:/usr/local/lib:/lib:/usr/lib"
const pathsep = ':'
else
const LIBPATH_env = "LD_LIBRARY_PATH"
const LIBPATH_default = ""
const pathsep = ':'
end

function adjust_ENV!(env::Dict, PATH::String, LIBPATH::String, adjust_PATH::Bool, adjust_LIBPATH::Bool)
vchuravy marked this conversation as resolved.
Show resolved Hide resolved
if adjust_LIBPATH
LIBPATH_base = get(env, LIBPATH_env, expanduser(LIBPATH_default))
if !isempty(LIBPATH_base)
env[LIBPATH_env] = string(LIBPATH, pathsep, LIBPATH_base)
else
env[LIBPATH_env] = LIBPATH
end
end
if adjust_PATH && (LIBPATH_env != "PATH" || !adjust_LIBPATH)
if !isempty(get(env, "PATH", ""))
env["PATH"] = string(PATH, pathsep, env["PATH"])
else
env["PATH"] = PATH
end
end
return env
end

function __init_lld_path()
# Prefer our own bundled lld, but if we don't have one, pick it up off of the PATH
# If this is an in-tree build, `lld` will live in `tools`. Otherwise, it'll be in `libexec`
for bundled_lld_path in (joinpath(Sys.BINDIR, Base.LIBEXECDIR, lld_exe),
joinpath(Sys.BINDIR, "..", "tools", lld_exe),
joinpath(Sys.BINDIR, lld_exe))
if isfile(bundled_lld_path)
lld_path[] = abspath(bundled_lld_path)
return
end
end
lld_path[] = something(Sys.which(lld_exe), lld_exe)
return
end

const VERBOSE = Ref{Bool}(false)

function __init__()
VERBOSE[] = parse(Bool, get(ENV, "JULIA_VERBOSE_LINKING", "false"))
timholy marked this conversation as resolved.
Show resolved Hide resolved

__init_lld_path()
PATH[] = dirname(lld_path[])
if Sys.iswindows()
# On windows, the dynamic libraries (.dll) are in Sys.BINDIR ("usr\\bin")
append!(LIBPATH_list, [abspath(Sys.BINDIR, Base.LIBDIR, "julia"), Sys.BINDIR])
else
append!(LIBPATH_list, [abspath(Sys.BINDIR, Base.LIBDIR, "julia"), abspath(Sys.BINDIR, Base.LIBDIR)])
end
LIBPATH[] = join(LIBPATH_list, pathsep)
return
end

function lld(; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH)
return Cmd(Cmd([lld_path[]]); env)
end

function ld()
default_args = ``
@static if Sys.iswindows()
# LLD supports mingw style linking
flavor = "gnu"
m = Sys.ARCH == :x86_64 ? "i386pep" : "i386pe"
default_args = `-m $m -Bdynamic --enable-auto-image-base --allow-multiple-definition`
elseif Sys.isapple()
flavor = "darwin"
arch = Sys.ARCH == :aarch64 ? :arm64 : Sys.ARCH
default_args = `-arch $arch -undefined dynamic_lookup -platform_version macos $(Base.MACOS_PRODUCT_VERSION) $(Base.MACOS_PLATFORM_VERSION)`
vchuravy marked this conversation as resolved.
Show resolved Hide resolved
else
flavor = "gnu"
end

`$(lld()) -flavor $flavor $default_args`
end

const WHOLE_ARCHIVE = if Sys.isapple()
"-all_load"
else
"--whole-archive"
end

const NO_WHOLE_ARCHIVE = if Sys.isapple()
""
else
"--no-whole-archive"
end

const SHARED = if Sys.isapple()
"-dylib"
else
"-shared"
end

is_debug() = ccall(:jl_is_debugbuild, Cint, ()) == 1
libdir() = abspath(Sys.BINDIR, Base.LIBDIR)
private_libdir() = abspath(Sys.BINDIR, Base.PRIVATE_LIBDIR)
if Sys.iswindows()
shlibdir() = Sys.BINDIR
else
shlibdir() = libdir()
end

function link_image_cmd(path, out)
LIBDIR = "-L$(libdir())"
PRIVATE_LIBDIR = "-L$(private_libdir())"
SHLIBDIR = "-L$(shlibdir())"
LIBS = is_debug() ? ("-ljulia-debug", "-ljulia-internal-debug") : ("-ljulia", "-ljulia-internal")
@static if Sys.iswindows()
LIBS = (LIBS..., "-lopenlibm", "-lssp", "-lgcc_s", "-lgcc", "-lmsvcrt")
end

V = VERBOSE[] ? "--verbose" : ""
`$(ld()) $V $SHARED -o $out $WHOLE_ARCHIVE $path $NO_WHOLE_ARCHIVE $LIBDIR $PRIVATE_LIBDIR $SHLIBDIR $LIBS`
end

function link_image(path, out, internal_stderr::IO = stderr, internal_stdout::IO = stdout)
run(link_image_cmd(path, out), Base.DevNull(), stderr, stdout)
end

end # module Linking
Loading