From 2f65025eeb4a79458af26d759e932d70633a64db Mon Sep 17 00:00:00 2001 From: Alec Theriault Date: Mon, 7 Jan 2019 11:38:11 -0800 Subject: Hadrian: support extra libraries + OSX rpath Summary: This fixes some of the issues that surfaced when trying to build dynamic GHC on OSX. Unfortunately, due some other `libffi` issues, this doesn't completely fix dynamic builds on OSX. - Use 'extra-libraries' from .cabal files instead of hardcoding which packages need which extra libs. Also add support for 'extra-lib-dirs'. - Make sure Hadrian looks in the right places to support both plain '.buildinfo' and '.buildinfo.in' files. - Make the '-rpath' support more robust across OS's (it previously didn't work on OSX and possibly windows either). Reviewers: angerman, alpmestan, adamse, DavidEichmann, bgamari, Phyx Subscribers: rwbarton, carter GHC Trac Issues: #15990 Differential Revision: https://phabricator.haskell.org/D5409 --- hadrian/src/Context.hs | 9 ++++++--- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs | 14 +++++++------- hadrian/src/Oracles/Setting.hs | 10 +++++++++- hadrian/src/Rules/BinaryDist.hs | 4 +--- hadrian/src/Settings/Builders/Ghc.hs | 21 +++++++++++---------- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/hadrian/src/Context.hs b/hadrian/src/Context.hs index 8036eb00bc..7943e6dfce 100644 --- a/hadrian/src/Context.hs +++ b/hadrian/src/Context.hs @@ -51,12 +51,15 @@ libPath :: Context -> Action FilePath libPath context = buildRoot <&> (-/- libDir context) -- | Get the directory name for binary distribution files --- --ghc-. +-- @--ghc-@. +-- +-- We preform some renaming to accomodate Cabal's slightly different naming +-- conventions (see 'cabalOsString' and 'cabalArchString'). distDir :: Action FilePath distDir = do version <- setting ProjectVersion - hostOs <- setting BuildOs - hostArch <- setting BuildArch + hostOs <- cabalOsString <$> setting BuildOs + hostArch <- cabalArchString <$> setting BuildArch return $ hostArch ++ "-" ++ hostOs ++ "-ghc-" ++ version pkgFile :: Context -> String -> String -> Action FilePath diff --git a/hadrian/src/Hadrian/Haskell/Cabal/Parse.hs b/hadrian/src/Hadrian/Haskell/Cabal/Parse.hs index bb2f0be3da..995270184b 100644 --- a/hadrian/src/Hadrian/Haskell/Cabal/Parse.hs +++ b/hadrian/src/Hadrian/Haskell/Cabal/Parse.hs @@ -208,7 +208,7 @@ resolveContextData context@Context {..} = do -- Create the @cabal_macros.h@, ... -- Note: the @cPath@ is ignored. The path that's used is the 'buildDir' path -- from the local build info @lbi@. - pdi <- liftIO $ getHookedBuildInfo (pkgPath package) + pdi <- liftIO $ getHookedBuildInfo [pkgPath package, cPath -/- "build"] let pd' = C.updatePackageDescription pdi pd lbi' = lbi { C.localPkgDescr = pd' } liftIO $ C.initialBuildSteps cPath pd' lbi' C.silent @@ -282,12 +282,12 @@ resolveContextData context@Context {..} = do , depLdOpts = forDeps Installed.ldOptions , buildGhciLib = C.withGHCiLib lbi' } -getHookedBuildInfo :: FilePath -> IO C.HookedBuildInfo -getHookedBuildInfo baseDir = do - -- TODO: We should probably better generate this in the build directory, - -- rather than in the base directory? However, @configure@ is run in the - -- base directory. +-- | Look for a @.buildinfo@ in all of the specified directories, stopping on +-- the first one we find. +getHookedBuildInfo :: [FilePath] -> IO C.HookedBuildInfo +getHookedBuildInfo [] = return C.emptyHookedBuildInfo +getHookedBuildInfo (baseDir:baseDirs) = do maybeInfoFile <- C.findHookedPackageDesc baseDir case maybeInfoFile of - Nothing -> return C.emptyHookedBuildInfo + Nothing -> getHookedBuildInfo baseDirs Just infoFile -> C.readHookedBuildInfo C.silent infoFile diff --git a/hadrian/src/Oracles/Setting.hs b/hadrian/src/Oracles/Setting.hs index 5197b8ea54..02ac42e0c9 100644 --- a/hadrian/src/Oracles/Setting.hs +++ b/hadrian/src/Oracles/Setting.hs @@ -3,7 +3,7 @@ module Oracles.Setting ( getSettingList, anyTargetPlatform, anyTargetOs, anyTargetArch, anyHostOs, ghcWithInterpreter, ghcEnableTablesNextToCode, useLibFFIForAdjustors, ghcCanonVersion, cmdLineLengthLimit, iosHost, osxHost, windowsHost, - topDirectory, libsuf + hostSupportsRPaths, topDirectory, libsuf ) where import Hadrian.Expression @@ -166,6 +166,14 @@ iosHost = anyHostOs ["ios"] osxHost :: Action Bool osxHost = anyHostOs ["darwin"] +-- | Check whether the host OS supports the @-rpath@ linker option when +-- using dynamic linking. +-- +-- TODO: Windows supports lazy binding (but GHC doesn't currently support +-- dynamic way on Windows anyways). +hostSupportsRPaths :: Action Bool +hostSupportsRPaths = anyHostOs ["linux", "darwin", "freebsd"] + -- | Check whether the host OS setting is set to @"mingw32"@ or @"cygwin32"@. windowsHost :: Action Bool windowsHost = anyHostOs ["mingw32", "cygwin32"] diff --git a/hadrian/src/Rules/BinaryDist.hs b/hadrian/src/Rules/BinaryDist.hs index a589c7af98..f847af9166 100644 --- a/hadrian/src/Rules/BinaryDist.hs +++ b/hadrian/src/Rules/BinaryDist.hs @@ -98,14 +98,12 @@ bindistRules = do version <- setting ProjectVersion targetPlatform <- setting TargetPlatformFull - cabalHostOs <- cabalOsString <$> setting BuildOs - cabalHostArch <- cabalArchString <$> setting BuildArch + distDir <- Context.distDir rtsDir <- pkgIdentifier rts let ghcBuildDir = root -/- stageString Stage1 bindistFilesDir = root -/- "bindist" -/- ghcVersionPretty ghcVersionPretty = "ghc-" ++ version ++ "-" ++ targetPlatform - distDir = cabalHostArch ++ "-" ++ cabalHostOs ++ "-ghc-" ++ version rtsIncludeDir = ghcBuildDir -/- "lib" -/- distDir -/- rtsDir -/- "include" diff --git a/hadrian/src/Settings/Builders/Ghc.hs b/hadrian/src/Settings/Builders/Ghc.hs index a605873d77..4957de77fe 100644 --- a/hadrian/src/Settings/Builders/Ghc.hs +++ b/hadrian/src/Settings/Builders/Ghc.hs @@ -43,10 +43,10 @@ compileC = builder (Ghc CompileCWithGhc) ? do ghcLinkArgs :: Args ghcLinkArgs = builder (Ghc LinkHs) ? do pkg <- getPackage - libs <- pkg == hp2ps ? pure ["m"] - intLib <- getIntegerPackage - gmpLibs <- notStage0 ? intLib == integerGmp ? pure ["gmp"] + libs <- getContextData extraLibs + libDirs <- getContextData extraLibDirs dynamic <- requiresDynamic + darwin <- expr osxHost -- Relative path from the output (rpath $ORIGIN). originPath <- dropFileName <$> getOutput @@ -56,20 +56,21 @@ ghcLinkArgs = builder (Ghc LinkHs) ? do let distPath = libPath' -/- distDir originToLibsDir = makeRelativeNoSysLink originPath distPath + rpath | darwin = "@loader_path" -/- originToLibsDir + | otherwise = "$ORIGIN" -/- originToLibsDir mconcat [ dynamic ? mconcat [ arg "-dynamic" - -- TODO what about windows / OSX? - , notStage0 ? pure - [ "-optl-Wl,-rpath" - , "-optl-Wl," ++ ("$ORIGIN" -/- originToLibsDir) ] + -- TODO what about windows? + , isLibrary pkg ? pure [ "-shared", "-dynload", "deploy" ] + , notStage0 ? + hostSupportsRPaths ? arg ("-optl-Wl,-rpath," ++ rpath) ] - , (dynamic && isLibrary pkg) ? - pure [ "-shared", "-dynload", "deploy" ] , arg "-no-auto-link-packages" , nonHsMainPackage pkg ? arg "-no-hs-main" , not (nonHsMainPackage pkg) ? arg "-rtsopts" - , pure [ "-optl-l" ++ lib | lib <- libs ++ gmpLibs ] + , pure [ "-l" ++ lib | lib <- libs ] + , pure [ "-L" ++ libDir | libDir <- libDirs ] ] findHsDependencies :: Args -- cgit v1.2.1