diff --git a/Cabal/src/Distribution/Simple.hs b/Cabal/src/Distribution/Simple.hs index 114c60a1add..6a0ebc77fef 100644 --- a/Cabal/src/Distribution/Simple.hs +++ b/Cabal/src/Distribution/Simple.hs @@ -135,6 +135,7 @@ import Language.Haskell.Extension -- Base import Data.List (unionBy, (\\)) +import qualified Data.Map as Map import System.Directory (removePathForcibly) import System.Environment (getArgs, getProgName) import System.IO (hPutStr, hPutStrLn) @@ -981,12 +982,14 @@ autoconfUserHooks = let common = configCommonFlags flags verbosity = mkVerbosity defaultVerbosityHandles (fromFlag $ setupVerbosity common) mbWorkDir = flagToMaybe $ setupWorkingDir common + compilerTargetTriple = Map.lookup "Target platform" (compilerProperties (compiler lbi)) runConfigureScript defaultVerbosityHandles flags (flagAssignment lbi) (withPrograms lbi) (hostPlatform lbi) + compilerTargetTriple pbi <- getHookedBuildInfo verbosity mbWorkDir (buildDir lbi) sanityCheckHookedBuildInfo verbosity pkg_descr pbi let pkg_descr' = updatePackageDescription pbi pkg_descr @@ -1055,9 +1058,12 @@ autoconfSetupHooks = { LBC.configFlags = cfg , LBC.flagAssignment = flags , LBC.hostPlatform = plat + , LBC.compiler = compiler' } } - ) = runConfigureScript defaultVerbosityHandles cfg flags progs plat + ) = + let compilerTargetTriple = Map.lookup "Target platform" (compilerProperties compiler') + in runConfigureScript defaultVerbosityHandles cfg flags progs plat compilerTargetTriple pre_conf_comp :: SetupHooks.PreConfComponentInputs diff --git a/Cabal/src/Distribution/Simple/ConfigureScript.hs b/Cabal/src/Distribution/Simple/ConfigureScript.hs index 454503eb679..5fb844f98d0 100644 --- a/Cabal/src/Distribution/Simple/ConfigureScript.hs +++ b/Cabal/src/Distribution/Simple/ConfigureScript.hs @@ -23,7 +23,6 @@ import Prelude () -- local import Distribution.PackageDescription -import Distribution.Pretty import Distribution.Simple.Configure (findDistPrefOrDefault) import Distribution.Simple.Errors import Distribution.Simple.LocalBuildInfo @@ -56,8 +55,18 @@ runConfigureScript -> ProgramDb -> Platform -- ^ host platform + -> Maybe String + -- ^ The GHC target platform triple (e.g. @"x86_64-w64-mingw32"@), + -- passed as the autoconf @--host=@ flag. + -- + -- Note: GHC's \"target\" is the platform that compiled Haskell code + -- runs on, which corresponds to autoconf's \"host\" (the platform + -- where the compiled artifact runs). Autoconf reserves \"target\" + -- for compiler toolchains only. See the + -- [GHC wiki on cross-compilation](https://gitlab.haskell.org/ghc/ghc/-/wikis/cross-compilation) + -- for details on GHC's platform terminology. -> IO () -runConfigureScript verbHandles cfg flags programDb hp = do +runConfigureScript verbHandles cfg flags programDb hp targetTriple = do let commonCfg = configCommonFlags cfg verbosity = mkVerbosity verbHandles (fromFlag $ setupVerbosity commonCfg) dist_dir <- findDistPrefOrDefault $ setupDistPref commonCfg @@ -183,7 +192,15 @@ runConfigureScript verbHandles cfg flags programDb hp = do : [("CXXFLAGS", Just (mkFlagsEnv cxxFlags "CXXFLAGS")) | Just cxxFlags <- [mcxxFlags]] ++ [("PATH", Just pathEnv) | not (null extraPath)] ++ cabalFlagEnv - maybeHostFlag = ["--host=" ++ show (pretty hp) | hp /= buildPlatform] + maybeHostFlag = + case targetTriple of + Just host -> + [ "--host=" ++ host + | -- the hp =/ buildPlatform guard is too restrictive, + -- e.g. for glibc -> musl cross-compilation we don't want to omit x86_64-unknown-linux-musl. + hp /= buildPlatform + ] + Nothing -> [] args' = configureFile' : args diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/A.hs b/cabal-testsuite/PackageTests/ConfigureHostTriple/A.hs new file mode 100644 index 00000000000..d843c00b782 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/A.hs @@ -0,0 +1 @@ +module A where diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/Setup.hs b/cabal-testsuite/PackageTests/ConfigureHostTriple/Setup.hs new file mode 100644 index 00000000000..54f57d6f118 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/Setup.hs @@ -0,0 +1,6 @@ +module Main (main) where + +import Distribution.Simple + +main :: IO () +main = defaultMainWithHooks autoconfUserHooks diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/configure b/cabal-testsuite/PackageTests/ConfigureHostTriple/configure new file mode 100755 index 00000000000..8dc248ac2d9 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/configure @@ -0,0 +1,4 @@ +#!/bin/sh +# Minimal configure script that records its arguments. +# We write all args to configure-args.txt so the test can inspect them. +echo "$@" > configure-args.txt diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/scripts/fake-ghc.sh b/cabal-testsuite/PackageTests/ConfigureHostTriple/scripts/fake-ghc.sh new file mode 100755 index 00000000000..ba2d9c15a2c --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/scripts/fake-ghc.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +# A fake GHC that proxies the real GHC but overrides +# "Target platform" to simulate cross-compilation +# to x86_64-w64-mingw32. + +case "$*" in + *--info*) + ghc "$@" | sed 's/("Target platform","[^"]*")/("Target platform","x86_64-w64-mingw32")/' + ;; + *) + exec ghc "$@" + ;; +esac diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/setup.test.hs b/cabal-testsuite/PackageTests/ConfigureHostTriple/setup.test.hs new file mode 100644 index 00000000000..730f43db1ce --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/setup.test.hs @@ -0,0 +1,42 @@ +import Test.Cabal.Prelude +import Test.Cabal.Script (runghc) +import Control.Monad.IO.Class +import Data.List (isInfixOf) + +-- When cross-compiling, Cabal passes a --host= flag to configure scripts. +-- The value should be the original GNU triple (e.g. x86_64-w64-mingw32), +-- not Cabal's canonical platform string (e.g. x86_64-windows). +-- +-- This test uses a fake GHC wrapper that reports "x86_64-w64-mingw32" +-- as its Target platform (simulating a cross-compiler), then checks +-- that the configure script receives --host=x86_64-w64-mingw32 +-- rather than the mangled --host=x86_64-windows. +main = do + skipIfWindows "uses sh script as fake ghc" + setupTest $ recordMode DoNotRecord $ do + env <- getTestEnv + let cwd = testCurrentDir env + fakeGhc = cwd "scripts" "fake-ghc.sh" + -- Run Setup.hs configure with our fake cross-compiler. + -- We call runghc ourselves to bypass the test framework's + -- --with-ghc which would override ours. + _ <- liftIO $ runghc + (testScriptEnv env) + (Just $ testTmpDir env) + (testEnvironment env) + ("." "Setup.hs") + [ "configure" + , "--distdir", testDistDir env + , "--with-compiler", fakeGhc + ] + -- The configure script writes its arguments to configure-args.txt + -- in its working directory (dist/build/). + let argsFile = testDistDir env "build" "configure-args.txt" + args <- liftIO $ readFile argsFile + -- The configure script should receive --host=x86_64-w64-mingw32 + -- (the original GNU triple), not --host=x86_64-windows. + unless ("--host=x86_64-w64-mingw32" `isInfixOf` args) $ + error $ unlines + [ "Expected --host=x86_64-w64-mingw32 in configure arguments" + , "but got: " ++ args + ] diff --git a/cabal-testsuite/PackageTests/ConfigureHostTriple/test.cabal b/cabal-testsuite/PackageTests/ConfigureHostTriple/test.cabal new file mode 100644 index 00000000000..f5a2a84fb01 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureHostTriple/test.cabal @@ -0,0 +1,9 @@ +cabal-version: 2.2 +name: test +version: 0 +build-type: Configure + +library + exposed-modules: A + build-depends: base + default-language: Haskell2010 diff --git a/changelog.d/pr-11718.md b/changelog.d/pr-11718.md new file mode 100644 index 00000000000..ba959073c0d --- /dev/null +++ b/changelog.d/pr-11718.md @@ -0,0 +1,15 @@ +--- +synopsis: Fix --host= triple mangling during cross-compilation +packages: [cabal-install] +prs: 11718 +issues: 5887 +--- + +repairs (hopefully): https://github.com/haskell/cabal/issues/5887 + +Cabal now passes the unchanged GHC target platform triple as the autoconf --host, instead of a simplified version. + +For example, Cabal now passes the full `--host=x86_64-w64-mingw32` instead of the incorrect `--host=x86_64-windows`. + +Adds an integration test which fails on master +and now succeeds.