From fc0040268dd04f4da0c9dac60f68a1cbf63fdffc Mon Sep 17 00:00:00 2001 From: Moritz Angermann Date: Thu, 22 May 2025 11:07:51 +0000 Subject: [PATCH] lib:Cabal - do not use GHC to configure LD. Cabal uses a peculiar c program to check if LD supports and should use -x. To do this, it shells out to GHC to compiler the C file. This however requires that GHC will not bail out, yet cabal does not pass --package-db flags to this GHC invocation, and as such we can run into situations where GHC bails out, especially during GHC bootstrap phases where not all boot packages are available. We however do not need GHC to compiler a c program, and can rely on the C compiler. Fundamentally cabal does not allow modelling program dependencies in the program db, as such we must configure gcc first before using it. We make a small change to lib:Cabal (specifically the GHC module, and it's Internal companion) to allow it to configure gcc first, before trying to configure ld, and thus having gcc in scope while configuring ld. This removes the need for the awkward ghc invocation to compiler the test program. Co-authored-by: brandon s allbery kf8nh --- Cabal/src/Distribution/Simple/GHC.hs | 6 +- Cabal/src/Distribution/Simple/GHC/Internal.hs | 82 +++++++++++-------- 2 files changed, 50 insertions(+), 38 deletions(-) diff --git a/Cabal/src/Distribution/Simple/GHC.hs b/Cabal/src/Distribution/Simple/GHC.hs index 45fbee0fed1..5e01d0f42a5 100644 --- a/Cabal/src/Distribution/Simple/GHC.hs +++ b/Cabal/src/Distribution/Simple/GHC.hs @@ -261,8 +261,10 @@ configure verbosity hcPath hcPkgPath conf0 = do , compilerProperties = ghcInfoMap } compPlatform = Internal.targetPlatform ghcInfo - -- configure gcc and ld - progdb4 = Internal.configureToolchain implInfo ghcProg ghcInfoMap progdb3 + -- configure gcc and ld + -- similarly to how we need ghc above, we need to know the c compiler + -- generally named `gcc` in cabal, to configure other programs, e.g. ld. + progdb4 <- Internal.configureToolchain verbosity implInfo ghcProg ghcInfoMap progdb3 return (comp, compPlatform, progdb4) -- | Given something like /usr/local/bin/ghc-6.6.1(.exe) we try and find diff --git a/Cabal/src/Distribution/Simple/GHC/Internal.hs b/Cabal/src/Distribution/Simple/GHC/Internal.hs index 9e252d7c889..a4c121fc1bb 100644 --- a/Cabal/src/Distribution/Simple/GHC/Internal.hs +++ b/Cabal/src/Distribution/Simple/GHC/Internal.hs @@ -100,37 +100,48 @@ targetPlatform ghcInfo = platformFromTriple =<< lookup "Target platform" ghcInfo -- | Adjust the way we find and configure gcc and ld configureToolchain - :: GhcImplInfo + :: Verbosity + -> GhcImplInfo -> ConfiguredProgram -> Map String String -> ProgramDb - -> ProgramDb -configureToolchain _implInfo ghcProg ghcInfo = - addKnownProgram - gccProgram - { programFindLocation = findProg gccProgramName extraGccPath - , programPostConf = configureGcc - } - . addKnownProgram - gppProgram - { programFindLocation = findProg gppProgramName extraGppPath - , programPostConf = configureGpp - } - . addKnownProgram - ldProgram - { programFindLocation = findProg ldProgramName extraLdPath - , programPostConf = \v cp -> - -- Call any existing configuration first and then add any new configuration - configureLd v =<< programPostConf ldProgram v cp - } - . addKnownProgram - arProgram - { programFindLocation = findProg arProgramName extraArPath - } - . addKnownProgram - stripProgram - { programFindLocation = findProg stripProgramName extraStripPath - } + -> IO ProgramDb +configureToolchain verbosity0 _implInfo ghcProg ghcInfo db = do + -- this is a bit of a hack. We have a dependency of ld on gcc. + -- ld needs to compile a c program, to check an ld feature. + -- we _could_ use ghc as a c frontend, but we do not pass all + -- of the db stack appropriately, and thus we can run into situations + -- where GHC will fail if it's stricter in its wired-in-unit + -- selction and has the wrong db stack. However we don't need + -- ghc to compile a _test_ c program. So we configure `gcc` + -- first and then use `gcc` (the generic c compiler in cabal + -- terminology) to compile the test program. + let db' = + flip addKnownProgram db $ + gccProgram + { programFindLocation = findProg gccProgramName extraGccPath + , programPostConf = configureGcc + } + (gccProg, db'') <- requireProgram verbosity0 gccProgram db' + return $ + flip addKnownPrograms db'' $ + [ gppProgram + { programFindLocation = findProg gppProgramName extraGppPath + , programPostConf = configureGpp + } + , ldProgram + { programFindLocation = findProg ldProgramName extraLdPath + , programPostConf = \v cp -> + -- Call any existing configuration first and then add any new configuration + configureLd gccProg v =<< programPostConf ldProgram v cp + } + , arProgram + { programFindLocation = findProg arProgramName extraArPath + } + , stripProgram + { programFindLocation = findProg stripProgramName extraStripPath + } + ] where compilerDir, base_dir, mingwBinDir :: FilePath compilerDir = takeDirectory (programPath ghcProg) @@ -230,17 +241,17 @@ configureToolchain _implInfo ghcProg ghcInfo = ++ cxxFlags } - configureLd :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram - configureLd v ldProg = do - ldProg' <- configureLd' v ldProg + configureLd :: ConfiguredProgram -> Verbosity -> ConfiguredProgram -> IO ConfiguredProgram + configureLd gccProg v ldProg = do + ldProg' <- configureLd' gccProg v ldProg return ldProg' { programDefaultArgs = programDefaultArgs ldProg' ++ ldLinkerFlags } -- we need to find out if ld supports the -x flag - configureLd' :: Verbosity -> ConfiguredProgram -> IO ConfiguredProgram - configureLd' verbosity ldProg = do + configureLd' :: ConfiguredProgram -> Verbosity -> ConfiguredProgram -> IO ConfiguredProgram + configureLd' gccProg verbosity ldProg = do ldx <- withTempFile ".c" $ \testcfile testchnd -> withTempFile ".o" $ \testofile testohnd -> do hPutStrLn testchnd "int foo() { return 0; }" @@ -248,9 +259,8 @@ configureToolchain _implInfo ghcProg ghcInfo = hClose testohnd runProgram verbosity - ghcProg - [ "-hide-all-packages" - , "-c" + gccProg + [ "-c" , testcfile , "-o" , testofile