-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
/
Copy pathlinking.jl
169 lines (148 loc) · 5.38 KB
/
linking.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
169
# 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"
const dsymutil_path = Ref{String}()
const dsymutil_exe = Sys.iswindows() ? "dsymutil.exe" : "dsymutil"
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)
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 `private_libexecdir`
for bundled_lld_path in (joinpath(Sys.BINDIR, Base.PRIVATE_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
function __init_dsymutil_path()
#Same as with lld but for dsymutil
for bundled_dsymutil_path in (joinpath(Sys.BINDIR, Base.PRIVATE_LIBEXECDIR, dsymutil_exe),
joinpath(Sys.BINDIR, "..", "tools", dsymutil_exe),
joinpath(Sys.BINDIR, dsymutil_exe))
if isfile(bundled_dsymutil_path)
dsymutil_path[] = abspath(bundled_dsymutil_path)
return
end
end
dsymutil_path[] = something(Sys.which(dsymutil_exe), dsymutil_exe)
return
end
const VERBOSE = Ref{Bool}(false)
function __init__()
VERBOSE[] = something(Base.get_bool_env("JULIA_VERBOSE_LINKING", false), false)
__init_lld_path()
__init_dsymutil_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 dsymutil(; adjust_PATH::Bool = true, adjust_LIBPATH::Bool = true)
env = adjust_ENV!(copy(ENV), PATH[], LIBPATH[], adjust_PATH, adjust_LIBPATH)
return Cmd(Cmd([dsymutil_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 --disable-auto-import --disable-runtime-pseudo-reloc`
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)`
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)
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 $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(), internal_stderr, internal_stdout)
end
end # module Linking