summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2021-08-09 22:46:26 +0800
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-08-18 05:43:57 -0400
commit0ba21dbe28882d506c3536c40224ebff337a9f49 (patch)
tree416e9390dbd1db7728ee0239e3432b0ba481cc35
parent5798357d9396c62a07413b1ee8ab3515526cf1e7 (diff)
downloadhaskell-0ba21dbe28882d506c3536c40224ebff337a9f49.tar.gz
Fix parsing of rpaths which include spaces in runInjectRPaths
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, [])