Commit b592bd98 authored by Moritz Angermann's avatar Moritz Angermann Committed by Ben Gamari

dead strip dylibs on macOS

When linking dynamic libraries or executables, we compute the full
transitive closure over the dependencies, and instruct the linker
to link all dependencies.  With deep dependency trees the number
of transitive dependencies can grow quickly.

macOS since the Sierra release has an upper limit on the load
command sizes the linker parses when loading dynamic lirbaries.
As such it is mandatory to keep the number of load commands (and
their size) small on recent macOS releases.

An approach that would just link direct dependencies as specified
by the -package-id flag is insufficient, because GHC can inline
across packages and the library or executable being linked could
refer to symbols deep in the dependency tree.

If we just recursively linked librarys and re-exported their
symbols, this increases the number of symbols in libraries with
many dependencies and ultimately puts excessive strain on the
linker to the point where linking takes a lot longer than even
the compilation of the modules.

We can however build a list of symbols from the obejcts we want
to link, and try to compute the libraries we need to link that
contain those symbols from the transitive dependency closure.
Luckily, we don't need to write this ourselves, but can use
the ld64 `-dead_strip_dylibs` linker flag on macOS to achive
the same result.  This will link only the libraries that are
actually referenced, which is usually a small subset of the
full transitive dependency closure.  As such we should stay
within the load command size limit for almost all but pathological

Reviewers: bgamari

Reviewed By: bgamari

Subscribers: lelf, rwbarton, thomie, carter

GHC Trac Issues: #14444

Differential Revision:
parent 21a9fb5f
......@@ -1884,6 +1884,9 @@ linkBinary' staticLink dflags o_files dep_packages = do
++ pkg_framework_opts
++ debug_opts
++ thread_opts
++ (if platformOS platform == OSDarwin
then [ "-Wl,-dead_strip_dylibs" ]
else [])
exeFileName :: Bool -> DynFlags -> FilePath
......@@ -540,6 +540,7 @@ linkDynLib dflags0 o_files dep_packages
++ map Option pkg_lib_path_opts
++ map Option pkg_link_opts
++ map Option pkg_framework_opts
++ [ Option "-Wl,-dead_strip_dylibs" ]
_ -> do
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment