diff options
author | Moritz Angermann <moritz.angermann@iohk.io> | 2020-08-13 12:26:41 +0800 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2020-09-07 21:18:39 -0400 |
commit | 4ff93292243888545da452ea4d4c1987f2343591 (patch) | |
tree | 82ec9a402238ea3b360c72a4e806b0f37bffe3e7 /hadrian | |
parent | d4bc9f0de7992f60bce403731019829f6248cc2c (diff) | |
download | haskell-4ff93292243888545da452ea4d4c1987f2343591.tar.gz |
[macOS] improved runpath handling
In b592bd98ff25730bbe3c13d6f62a427df8c78e28 we started using
-dead_strip_dylib on macOS when lining dynamic libraries and binaries.
The underlying reason being the Load Command Size Limit in macOS
Sierra (10.14) and later.
GHC will produce @rpath/libHS... dependency entries together with a
corresponding RPATH entry pointing to the location of the libHS...
library. Thus for every library we produce two Load Commands. One to
specify the dependent library, and one with the path where to find it.
This makes relocating libraries and binaries easier, as we just need to
update the RPATH entry with the install_name_tool. The dynamic linker
will then subsitute each @rpath with the RPATH entries it finds in the
libraries load commands or the environement, when looking up @rpath
relative libraries.
-dead_strip_dylibs intructs the linker to drop unused libraries. This in
turn help us reduce the number of referenced libraries, and subsequently
the size of the load commands. This however does not remove the RPATH
entries. Subsequently we can end up (in extreme cases) with only a
single @rpath/libHS... entry, but 100s or more RPATH entries in the Load
Commands.
This patch rectifies this (slighly unorthodox) by passing *no* -rpath
arguments to the linker at link time, but -headerpad 8000. The
headerpad argument is in hexadecimal and the maxium 32k of the load
command size. This tells the linker to pad the load command section
enough for us to inject the RPATHs later. We then proceed to link the
library or binary with -dead_strip_dylibs, and *after* the linking
inspect the library to find the left over (non-dead-stripped)
dependencies (using otool). We find the corresponding RPATHs for each
@rpath relative dependency, and inject them into the library or binary
using the install_name_tool. Thus achieving a deadstripped dylib (and
rpaths) build product.
We can not do this in GHC, without starting to reimplement a dynamic
linker as we do not know which symbols and subsequently libraries are
necessary.
Commissioned-by: Mercury Technologies, Inc. (mercury.com)
Diffstat (limited to 'hadrian')
-rw-r--r-- | hadrian/cfg/system.config.in | 2 | ||||
-rw-r--r-- | hadrian/src/Oracles/Setting.hs | 4 | ||||
-rw-r--r-- | hadrian/src/Rules/Generate.hs | 2 |
3 files changed, 8 insertions, 0 deletions
diff --git a/hadrian/cfg/system.config.in b/hadrian/cfg/system.config.in index adc244fa7d..1297a2c1cc 100644 --- a/hadrian/cfg/system.config.in +++ b/hadrian/cfg/system.config.in @@ -152,6 +152,8 @@ settings-merge-objects-command = @SettingsMergeObjectsCommand@ settings-merge-objects-flags = @SettingsMergeObjectsFlags@ settings-ar-command = @SettingsArCommand@ settings-ranlib-command = @SettingsRanlibCommand@ +settings-otool-command = @SettingsOtoolCommand@ +settings-install_name_tool-command = @SettingsInstallNameToolCommand@ settings-dll-wrap-command = @SettingsDllWrapCommand@ settings-windres-command = @SettingsWindresCommand@ settings-libtool-command = @SettingsLibtoolCommand@ diff --git a/hadrian/src/Oracles/Setting.hs b/hadrian/src/Oracles/Setting.hs index 06ea13d3f8..4331317b68 100644 --- a/hadrian/src/Oracles/Setting.hs +++ b/hadrian/src/Oracles/Setting.hs @@ -114,6 +114,8 @@ data SettingsFileSetting | SettingsFileSetting_MergeObjectsFlags | SettingsFileSetting_ArCommand | SettingsFileSetting_RanlibCommand + | SettingsFileSetting_OtoolCommand + | SettingsFileSetting_InstallNameToolCommand | SettingsFileSetting_DllWrapCommand | SettingsFileSetting_WindresCommand | SettingsFileSetting_LibtoolCommand @@ -200,6 +202,8 @@ settingsFileSetting key = lookupValueOrError configFile $ case key of SettingsFileSetting_MergeObjectsFlags -> "settings-merge-objects-flags" SettingsFileSetting_ArCommand -> "settings-ar-command" SettingsFileSetting_RanlibCommand -> "settings-ranlib-command" + SettingsFileSetting_OtoolCommand -> "settings-otool-command" + SettingsFileSetting_InstallNameToolCommand -> "settings-install_name_tool-command" SettingsFileSetting_DllWrapCommand -> "settings-dll-wrap-command" SettingsFileSetting_WindresCommand -> "settings-windres-command" SettingsFileSetting_LibtoolCommand -> "settings-libtool-command" diff --git a/hadrian/src/Rules/Generate.hs b/hadrian/src/Rules/Generate.hs index 430946020c..f429a8a9d2 100644 --- a/hadrian/src/Rules/Generate.hs +++ b/hadrian/src/Rules/Generate.hs @@ -308,6 +308,8 @@ generateSettings = do , ("ar flags", expr $ lookupValueOrError configFile "ar-args") , ("ar supports at file", expr $ yesNo <$> flag ArSupportsAtFile) , ("ranlib command", expr $ settingsFileSetting SettingsFileSetting_RanlibCommand) + , ("otool command", expr $ settingsFileSetting SettingsFileSetting_OtoolCommand) + , ("install_name_tool command", expr $ settingsFileSetting SettingsFileSetting_InstallNameToolCommand) , ("touch command", expr $ settingsFileSetting SettingsFileSetting_TouchCommand) , ("dllwrap command", expr $ settingsFileSetting SettingsFileSetting_DllWrapCommand) , ("windres command", expr $ settingsFileSetting SettingsFileSetting_WindresCommand) |