summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-08-09 22:46:26 +0800
committerMatthew Pickering <matthewtpickering@gmail.com>2021-08-16 10:01:58 +0000
commit2e80f25b361c0a290e3dc741c374d97f8aa643e6 (patch)
tree4e36fd2742434028fd6f8887987b4c707e871799
parent7f217429a44747e418af6549606fcbcce005ba2e (diff)
downloadhaskell-2e80f25b361c0a290e3dc741c374d97f8aa643e6.tar.gz
Fix parsing of rpaths which include spaces in runInjectRPathswip/fix-inject-rpath
The logic didn't account for the fact that the paths could contain spaces before which led to errors such as the following from install_name_tool. Stderr ( T14304 ): Warning: -rtsopts and -with-rtsopts have no effect with -shared. Call hs_init_ghc() from your main() function to set these options. error: /nix/store/a6j5761iy238pbckxq2xrhqr2d5kra4m-cctools-binutils-darwin-949.0.1/bin/install_name_tool: for: dist/build/libHSp-0.1-ghc8.10.6.dylib (for architecture arm64) option "-add_rpath /Users/matt/ghc/bindisttest/install dir/lib/ghc-8.10.6/ghc-prim-0.6.1" would duplicate path, file already has LC_RPATH for: /Users/matt/ghc/bindisttest/install dir/lib/ghc-8.10.6/ghc-prim-0.6.1 `install_name_tool' failed in phase `Install Name Tool'. (Exit code: 1) Fixes #20212 This apparently also fixes #20026, which is a nice surprise.
-rw-r--r--compiler/GHC/Linker/MacOS.hs31
-rw-r--r--testsuite/tests/driver/T3007/all.T3
2 files changed, 27 insertions, 7 deletions
diff --git a/compiler/GHC/Linker/MacOS.hs b/compiler/GHC/Linker/MacOS.hs
index 765ea7a7b3..576b9e7feb 100644
--- a/compiler/GHC/Linker/MacOS.hs
+++ b/compiler/GHC/Linker/MacOS.hs
@@ -23,9 +23,12 @@ import GHC.Utils.Exception
import GHC.Utils.Logger
import Data.List (isPrefixOf, nub, sort, intersperse, intercalate)
-import Control.Monad (join, forM, filterM)
+import Data.Char
+import Data.Maybe
+import Control.Monad (join, forM, filterM, void)
import System.Directory (doesFileExist, getHomeDirectory)
import System.FilePath ((</>), (<.>))
+import Text.ParserCombinators.ReadP as Parser
-- | On macOS we rely on the linkers @-dead_strip_dylibs@ flag to remove unused
-- libraries from the dynamic library. We do this to reduce the number of load
@@ -51,10 +54,8 @@ runInjectRPaths logger dflags lib_paths dylib = do
-- filter the output for only the libraries. And then drop the @rpath prefix.
let libs = fmap (drop 7) $ filter (isPrefixOf "@rpath") $ fmap (head.words) $ info
-- find any pre-existing LC_PATH items
- info <- fmap words.lines <$> askOtool logger dflags Nothing [Option "-l", Option dylib]
- let paths = concatMap f info
- where f ("path":p:_) = [p]
- f _ = []
+ info <- lines <$> askOtool logger dflags Nothing [Option "-l", Option dylib]
+ let paths = mapMaybe get_rpath info
lib_paths' = [ p | p <- lib_paths, not (p `elem` paths) ]
-- only find those rpaths, that aren't already in the library.
rpaths <- nub . sort . join <$> forM libs (\f -> filterM (\l -> doesFileExist (l </> f)) lib_paths')
@@ -63,6 +64,26 @@ runInjectRPaths logger dflags lib_paths dylib = do
[] -> return ()
_ -> runInstallNameTool logger dflags $ map Option $ "-add_rpath":(intersperse "-add_rpath" rpaths) ++ [dylib]
+get_rpath :: String -> Maybe FilePath
+get_rpath l = case readP_to_S rpath_parser l of
+ [(rpath, "")] -> Just rpath
+ _ -> Nothing
+
+
+rpath_parser :: ReadP FilePath
+rpath_parser = do
+ skipSpaces
+ void $ string "path"
+ void $ many1 (satisfy isSpace)
+ rpath <- many get
+ void $ many1 (satisfy isSpace)
+ void $ string "(offset "
+ void $ munch1 isDigit
+ void $ Parser.char ')'
+ skipSpaces
+ return rpath
+
+
getUnitFrameworkOpts :: UnitEnv -> [UnitId] -> IO [String]
getUnitFrameworkOpts unit_env dep_packages
| platformUsesFrameworks (ue_platform unit_env) = do
diff --git a/testsuite/tests/driver/T3007/all.T b/testsuite/tests/driver/T3007/all.T
index be57f45807..d0442712e9 100644
--- a/testsuite/tests/driver/T3007/all.T
+++ b/testsuite/tests/driver/T3007/all.T
@@ -1,4 +1,3 @@
test('T3007',
- [when(opsys('darwin'), expect_broken(20026)),
- extra_files(['A/', 'B/'])],
+ [extra_files(['A/', 'B/'])],
makefile_test, [])