Skip to content

Commit 96871ea

Browse files
authored
Automatically relink libgfortran to @rpath/libgfortran on OSX. (JuliaPackaging#147)
1 parent 35f4e9f commit 96871ea

File tree

1 file changed

+57
-23
lines changed

1 file changed

+57
-23
lines changed

src/Auditor.jl

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -108,9 +108,25 @@ function audit(prefix::Prefix; io=STDERR,
108108
info(io, msg)
109109
end
110110

111-
# Look at every non-default dynamic link
112-
libs = filter_default_linkages(find_libraries(oh), oh)
111+
# Look at every dynamic link, and see if we should do anything about that link...
112+
libs = find_libraries(oh)
113113
for libname in keys(libs)
114+
if should_ignore_lib(libname, oh)
115+
if verbose
116+
info(io, "Ignoring system library $(libname)")
117+
end
118+
continue
119+
end
120+
121+
# If this is a default dynamic link, then just rewrite to use rpath and call it good.
122+
if is_default_lib(libname, oh)
123+
relink_to_rpath(prefix, platform, path(oh), libs[libname])
124+
if verbose
125+
info(io, "Rpathify'ing default library $(libname)")
126+
end
127+
continue
128+
end
129+
114130
if !isfile(libs[libname])
115131
# If we couldn't resolve this library, let's try autofixing,
116132
# if we're allowed to by the user
@@ -250,18 +266,9 @@ function collapse_symlinks(files::Vector{String})
250266
return filter(predicate, files)
251267
end
252268

253-
"""
254-
filter_default_linkages(libs::Dict, oh::ObjectHandle)
255-
256-
Given libraries obtained through `ObjectFile.find_libraries()`, filter out
257-
libraries that are "default" libraries and should be available on any system.
258-
"""
259-
function filter_default_linkages(libs::Dict, oh::ObjectHandle)
260-
return Dict(k => libs[k] for k in keys(libs) if !should_ignore_lib(k, oh))
261-
end
262-
269+
# These are libraries we should straight-up ignore, like libsystem on OSX
263270
function should_ignore_lib(lib, ::ELFHandle)
264-
default_libs = [
271+
ignore_libs = [
265272
"libc.so.6",
266273
# libgcc Linux and FreeBSD style
267274
"libgcc_s.1.so",
@@ -270,32 +277,59 @@ function should_ignore_lib(lib, ::ELFHandle)
270277
"libgfortran.so.3",
271278
"libgfortran.so.4",
272279
]
273-
return lowercase(basename(lib)) in default_libs
280+
return lowercase(basename(lib)) in ignore_libs
274281
end
275-
276282
function should_ignore_lib(lib, ::MachOHandle)
277-
default_libs = [
283+
ignore_libs = [
278284
"libsystem.b.dylib",
279-
"libgcc_s.1.dylib",
280-
"libgfortran.3.dylib",
281-
"libgfortran.4.dylib",
282-
"libquadmath.0.dylib",
283285
]
284-
return lowercase(basename(lib)) in default_libs
286+
return lowercase(basename(lib)) in ignore_libs
285287
end
286-
287288
function should_ignore_lib(lib, ::COFFHandle)
288-
default_libs = [
289+
ignore_libs = [
289290
"msvcrt.dll",
290291
"kernel32.dll",
291292
"user32.dll",
292293
"libgcc_s_sjlj-1.dll",
293294
"libgfortran-3.dll",
294295
"libgfortran-4.dll",
295296
]
297+
return lowercase(basename(lib)) in ignore_libs
298+
end
299+
300+
# Determine whether a library is a "default" library or not, if it is we need
301+
# to map it to `@rpath/$libname` on OSX.
302+
is_default_lib(lib, oh) = false
303+
function is_default_lib(lib, ::MachOHandle)
304+
default_libs = [
305+
"libgcc_s.1.dylib",
306+
"libgfortran.3.dylib",
307+
"libgfortran.4.dylib",
308+
"libquadmath.0.dylib",
309+
]
296310
return lowercase(basename(lib)) in default_libs
297311
end
298312

313+
function relink_to_rpath(prefix::Prefix, platform::Platform, path::AbstractString,
314+
old_libpath::AbstractString; verbose::Bool = false)
315+
ur = UserNSRunner(prefix.path; cwd="/workspace/", platform=platform, verbose=true)
316+
rel_path = relpath(path, prefix.path)
317+
libname = basename(old_libpath)
318+
relink_cmd = ``
319+
320+
if Compat.Sys.isapple(platform)
321+
install_name_tool = "/opt/x86_64-apple-darwin14/bin/install_name_tool"
322+
relink_cmd = `$install_name_tool -change $(old_libpath) @rpath/$(libname) $(rel_path)`
323+
elseif Compat.Sys.islinux(platform)
324+
patchelf = "/usr/local/bin/patchelf"
325+
relink_cmd = `$patchelf --replace-needed $(old_libpath) \$ORIGIN/$(libname) $(rel_path)`
326+
end
327+
328+
# Create a new linkage that looks like $ORIGIN/../lib, or similar
329+
logpath = joinpath(logdir(prefix), "relink_to_rpath_$(libname).log")
330+
run(ur, relink_cmd, logpath; verbose=verbose)
331+
end
332+
299333
"""
300334
update_linkage(prefix::Prefix, platform::Platform, path::AbstractString,
301335
old_libpath, new_libpath; verbose::Bool = false)

0 commit comments

Comments
 (0)