Skip to content

Commit 256f85d

Browse files
authored
Backport of #9443 "Use linker capability detection to improve linker use" (#9797)
1 parent ce72f63 commit 256f85d

File tree

5 files changed

+83
-35
lines changed

5 files changed

+83
-35
lines changed

Cabal/src/Distribution/Simple/Configure.hs

+24-29
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ import Distribution.Simple.Program
7676
import Distribution.Simple.Setup as Setup
7777
import Distribution.Simple.BuildTarget
7878
import Distribution.Simple.LocalBuildInfo
79-
import Distribution.Simple.Program.Db (appendProgramSearchPath, modifyProgramSearchPath)
79+
import Distribution.Simple.Program.Db (appendProgramSearchPath, modifyProgramSearchPath, lookupProgramByName)
8080
import Distribution.Simple.Utils
8181
import Distribution.System
8282
import Distribution.Types.PackageVersionConstraint
@@ -102,7 +102,8 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite
102102
import Control.Exception
103103
( try )
104104
import Distribution.Utils.Structured ( structuredDecodeOrFailIO, structuredEncode )
105-
import Distribution.Compat.Directory ( listDirectory )
105+
import Distribution.Compat.Directory
106+
( listDirectory, doesPathExist )
106107
import Data.ByteString.Lazy ( ByteString )
107108
import qualified Data.ByteString as BS
108109
import qualified Data.ByteString.Lazy.Char8 as BLC8
@@ -115,8 +116,6 @@ import System.Directory
115116
, getTemporaryDirectory, removeFile)
116117
import System.FilePath
117118
( (</>), isAbsolute, takeDirectory )
118-
import Distribution.Compat.Directory
119-
( doesPathExist )
120119
import qualified System.Info
121120
( compilerName, compilerVersion )
122121
import System.IO
@@ -639,21 +638,16 @@ configure (pkg_descr0, pbi) cfg = do
639638
"--enable-split-objs; ignoring")
640639
return False
641640

642-
let compilerSupportsGhciLibs :: Bool
643-
compilerSupportsGhciLibs =
644-
case compilerId comp of
645-
CompilerId GHC version
646-
| version > mkVersion [9,3] && windows ->
647-
False
648-
CompilerId GHC _ ->
649-
True
650-
CompilerId GHCJS _ ->
651-
True
652-
_ -> False
653-
where
654-
windows = case compPlatform of
655-
Platform _ Windows -> True
656-
Platform _ _ -> False
641+
-- Basically yes/no/unknown.
642+
let linkerSupportsRelocations :: Maybe Bool
643+
linkerSupportsRelocations =
644+
case lookupProgramByName "ld" programDb'' of
645+
Nothing -> Nothing
646+
Just ld ->
647+
case Map.lookup "Supports relocatable output" $ programProperties ld of
648+
Just "YES" -> Just True
649+
Just "NO" -> Just False
650+
_other -> Nothing
657651

658652
let ghciLibByDefault =
659653
case compilerId comp of
@@ -673,10 +667,12 @@ configure (pkg_descr0, pbi) cfg = do
673667

674668
withGHCiLib_ <-
675669
case fromFlagOrDefault ghciLibByDefault (configGHCiLib cfg) of
676-
True | not compilerSupportsGhciLibs -> do
670+
-- NOTE: If linkerSupportsRelocations is Nothing this may still fail if the
671+
-- linker does not support -r.
672+
True | not (fromMaybe True linkerSupportsRelocations) -> do
677673
warn verbosity $
678-
"--enable-library-for-ghci is no longer supported on Windows with"
679-
++ " GHC 9.4 and later; ignoring..."
674+
"--enable-library-for-ghci is not supported with the current"
675+
++ " linker; ignoring..."
680676
return False
681677
v -> return v
682678

@@ -951,11 +947,11 @@ dependencySatisfiable
951947
then internalDepSatisfiable
952948
else
953949
-- Backward compatibility for the old sublibrary syntax
954-
(sublibs == mainLibSet
950+
sublibs == mainLibSet
955951
&& Map.member
956952
(pn, CLibName $ LSubLibName $
957953
packageNameToUnqualComponentName depName)
958-
requiredDepsMap)
954+
requiredDepsMap
959955

960956
|| all visible sublibs
961957

@@ -982,7 +978,7 @@ dependencySatisfiable
982978
internalDepSatisfiable =
983979
Set.isSubsetOf (NES.toSet sublibs) packageLibraries
984980
internalDepSatisfiableExternally =
985-
all (\ln -> not $ null $ PackageIndex.lookupInternalDependency installedPackageSet pn vr ln) sublibs
981+
all (not . null . PackageIndex.lookupInternalDependency installedPackageSet pn vr) sublibs
986982

987983
-- Check whether a library exists and is visible.
988984
-- We don't disambiguate between dependency on non-existent or private
@@ -1451,8 +1447,7 @@ getInstalledPackagesMonitorFiles verbosity comp packageDBs progdb platform =
14511447
-- flag into a single package db stack.
14521448
--
14531449
interpretPackageDbFlags :: Bool -> [Maybe PackageDB] -> PackageDBStack
1454-
interpretPackageDbFlags userInstall specificDBs =
1455-
extra initialStack specificDBs
1450+
interpretPackageDbFlags userInstall = extra initialStack
14561451
where
14571452
initialStack | userInstall = [GlobalPackageDB, UserPackageDB]
14581453
| otherwise = [GlobalPackageDB]
@@ -1698,8 +1693,8 @@ ccLdOptionsBuildInfo cflags ldflags ldflags_static =
16981693
let (includeDirs', cflags') = partition ("-I" `isPrefixOf`) cflags
16991694
(extraLibs', ldflags') = partition ("-l" `isPrefixOf`) ldflags
17001695
(extraLibDirs', ldflags'') = partition ("-L" `isPrefixOf`) ldflags'
1701-
(extraLibsStatic') = filter ("-l" `isPrefixOf`) ldflags_static
1702-
(extraLibDirsStatic') = filter ("-L" `isPrefixOf`) ldflags_static
1696+
extraLibsStatic' = filter ("-l" `isPrefixOf`) ldflags_static
1697+
extraLibDirsStatic' = filter ("-L" `isPrefixOf`) ldflags_static
17031698
in mempty {
17041699
includeDirs = map (drop 2) includeDirs',
17051700
extraLibs = map (drop 2) extraLibs',

Cabal/src/Distribution/Simple/GHC/Internal.hs

+3-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,9 @@ configureToolchain _implInfo ghcProg ghcInfo =
101101
}
102102
. addKnownProgram ldProgram {
103103
programFindLocation = findProg ldProgramName extraLdPath,
104-
programPostConf = configureLd
104+
programPostConf = \v cp ->
105+
-- Call any existing configuration first and then add any new configuration
106+
configureLd v =<< programPostConf ldProgram v cp
105107
}
106108
. addKnownProgram arProgram {
107109
programFindLocation = findProg arProgramName extraArPath

Cabal/src/Distribution/Simple/Program/Builtin.hs

+40-4
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,7 @@ arProgram = simpleProgram "ar"
256256

257257
stripProgram :: Program
258258
stripProgram = (simpleProgram "strip") {
259-
programFindVersion = \verbosity ->
260-
findProgramVersion "--version" stripExtractVersion (lessVerbose verbosity)
259+
programFindVersion = findProgramVersion "--version" stripExtractVersion . lessVerbose
261260
}
262261

263262
hsc2hsProgram :: Program
@@ -322,7 +321,44 @@ greencardProgram :: Program
322321
greencardProgram = simpleProgram "greencard"
323322

324323
ldProgram :: Program
325-
ldProgram = simpleProgram "ld"
324+
ldProgram = (simpleProgram "ld")
325+
{ programPostConf = \verbosity ldProg -> do
326+
-- The `lld` linker cannot create merge (relocatable) objects so we
327+
-- want to detect this.
328+
-- If the linker does support relocatable objects, we want to use that
329+
-- to create partially pre-linked objects for GHCi, so we get much
330+
-- faster loading as we do not have to do the separate loading and
331+
-- in-memory linking the static linker in GHC does, but can offload
332+
-- parts of this process to a pre-linking step.
333+
-- However this requires the linker to support this features. Not all
334+
-- linkers do, and notably as of this writing `lld` which is a popular
335+
-- choice for windows linking does not support this feature. However
336+
-- if using binutils ld or another linker that supports --relocatable,
337+
-- we should still be good to generate pre-linked objects.
338+
ldHelpOutput <-
339+
getProgramInvocationOutput
340+
verbosity
341+
(programInvocation ldProg ["--help"])
342+
-- In case the linker does not support '--help'. Eg the LLVM linker,
343+
-- `lld` only accepts `-help`.
344+
`catchIO` (\_ -> return "")
345+
let k = "Supports relocatable output"
346+
-- Standard GNU `ld` uses `--relocatable` while `ld.gold` uses
347+
-- `-relocatable` (single `-`).
348+
v
349+
| "-relocatable" `isInfixOf` ldHelpOutput = "YES"
350+
-- ld64 on macOS has this lovely response for "--help"
351+
--
352+
-- ld64: For information on command line options please use 'man ld'.
353+
--
354+
-- it does however support -r, if you read the manpage
355+
-- (e.g. https://www.manpagez.com/man/1/ld64/)
356+
| "ld64:" `isPrefixOf` ldHelpOutput = "YES"
357+
| otherwise = "NO"
358+
359+
m = Map.insert k v (programProperties ldProg)
360+
return $ ldProg{programProperties = m}
361+
}
326362

327363
tarProgram :: Program
328364
tarProgram = (simpleProgram "tar") {
@@ -334,7 +370,7 @@ tarProgram = (simpleProgram "tar") {
334370
-- Some versions of tar don't support '--help'.
335371
`catchIO` (\_ -> return "")
336372
let k = "Supports --format"
337-
v = if ("--format" `isInfixOf` tarHelpOutput) then "YES" else "NO"
373+
v = if "--format" `isInfixOf` tarHelpOutput then "YES" else "NO"
338374
m = Map.insert k v (programProperties tarProg)
339375
return $ tarProg { programProperties = m }
340376
}

Cabal/src/Distribution/Simple/Program/Db.hs

+5-1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ module Distribution.Simple.Program.Db (
4747
userSpecifyArgss,
4848
userSpecifiedArgs,
4949
lookupProgram,
50+
lookupProgramByName,
5051
updateProgram,
5152
configuredPrograms,
5253

@@ -309,8 +310,11 @@ userSpecifiedArgs prog =
309310

310311
-- | Try to find a configured program
311312
lookupProgram :: Program -> ProgramDb -> Maybe ConfiguredProgram
312-
lookupProgram prog = Map.lookup (programName prog) . configuredProgs
313+
lookupProgram = lookupProgramByName . programName
313314

315+
-- | Try to find a configured program
316+
lookupProgramByName :: String -> ProgramDb -> Maybe ConfiguredProgram
317+
lookupProgramByName name = Map.lookup name . configuredProgs
314318

315319
-- | Update a configured program in the database.
316320
updateProgram :: ConfiguredProgram -> ProgramDb

changelog.d/pr-9443

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
synopsis: Use linker capability detection to improve linker use
2+
packages: Cabal
3+
prs: #9443
4+
5+
description: {
6+
7+
- Previously the GHC version number and platform were used as a proxy for whether
8+
the linker can generate relocatable objects.
9+
- Now, the ability of the linker to create relocatable objects is detected.
10+
11+
}

0 commit comments

Comments
 (0)