diff --git a/Cabal/src/Distribution/Simple/ConfigureScript.hs b/Cabal/src/Distribution/Simple/ConfigureScript.hs index 102bacf6234..f5b0599c35a 100644 --- a/Cabal/src/Distribution/Simple/ConfigureScript.hs +++ b/Cabal/src/Distribution/Simple/ConfigureScript.hs @@ -18,6 +18,7 @@ import Distribution.Compat.Prelude import Prelude () -- local +import Distribution.Compiler (CompilerFlavor (..)) import Distribution.PackageDescription import Distribution.Pretty import Distribution.Simple.Configure (findDistPrefOrDefault) @@ -86,6 +87,34 @@ runConfigureScript verbHandles cfg flags programDb hp = do return (Just cxxProgShort, Just cxxFlags) Nothing -> return (Nothing, Nothing) + -- The compiler this package is configured with. A configure script that + -- asks for it (autoconf's @AC_ARG_WITH([compiler])@ or @AC_ARG_VAR([GHC])@, + -- as GHC's own libraries do to run @ghc --print-prim-module@) must get the + -- compiler Cabal uses, not whatever @ghc@ happens to be on PATH. The + -- ConfigFlags alone do not say: cabal-install passes the compiler as a + -- program path override and leaves 'configHcPath' unset, in which case + -- 'configureArgs' would only pass the flavour name. + let hcPrograms = case flagToMaybe (configHcFlavor cfg) of + Just GHC -> Just (ghcProgram, ghcPkgProgram) + Just GHCJS -> Just (ghcjsProgram, ghcjsPkgProgram) + _ -> Nothing + configuredPath prog = programPath <$> lookupProgram prog programDb + mHcPath <- traverse getShortPathName (hcPrograms >>= configuredPath . fst) + mHcPkgPath <- traverse getShortPathName (hcPrograms >>= configuredPath . snd) + let orConfigured flag mpath = case flag of + Flag p -> Flag p + NoFlag -> maybe NoFlag Flag mpath + cfg' = + cfg + { configHcPath = configHcPath cfg `orConfigured` mHcPath + , configHcPkg = configHcPkg cfg `orConfigured` mHcPkgPath + } + hcEnv = + [ (var, Just path) + | Just GHC <- [flagToMaybe (configHcFlavor cfg)] + , (var, Just path) <- [("GHC", mHcPath), ("GHC_PKG", mHcPkgPath)] + ] + let configureFile' = toUnix configureFile -- autoconf is fussy about filenames, and has a set of forbidden -- characters that can't appear in the build directory, etc: @@ -178,13 +207,19 @@ runConfigureScript verbHandles cfg flags programDb hp = do ("CFLAGS", Just (mkFlagsEnv ccFlags "CFLAGS")) : [("CXXFLAGS", Just (mkFlagsEnv cxxFlags "CXXFLAGS")) | Just cxxFlags <- [mcxxFlags]] ++ [("PATH", Just pathEnv) | not (null extraPath)] + ++ hcEnv ++ cabalFlagEnv maybeHostFlag = ["--host=" ++ show (pretty hp) | hp /= buildPlatform] + backwardsCompatHack = False + args = configureArgs backwardsCompatHack cfg' args' = configureFile' : args ++ ["CC=" ++ ccProgShort] ++ ["CXX=" ++ cxxProgShort | Just cxxProgShort <- [mcxxProgShort]] + -- The standard autoconf spelling for the Haskell compiler (#2947); + -- '--with-compiler' above is kept for the scripts that use it. + ++ ["HC=" ++ hcPath | Just hcPath <- [mHcPath]] ++ maybeHostFlag shProg = simpleProgram "sh" progDb <- prependProgramSearchPath verbosity extraPath [] emptyProgramDb @@ -200,9 +235,6 @@ runConfigureScript verbHandles cfg flags programDb hp = do { progInvokeCwd = Just build_in } Nothing -> dieWithException verbosity NotFoundMsg - where - args = configureArgs backwardsCompatHack cfg - backwardsCompatHack = False -- | Convert Windows path to Unix ones toUnix :: String -> String diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/A.hs b/cabal-testsuite/PackageTests/ConfigureCompiler/A.hs new file mode 100644 index 00000000000..fe651a3605e --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/A.hs @@ -0,0 +1,4 @@ +module A where + +a :: Int +a = 1 diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.out b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.out new file mode 100644 index 00000000000..5e3f7e5dd26 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.out @@ -0,0 +1,8 @@ +# cabal v2-build +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - configure-compiler-1.0 (lib) (first run) +Configuring library for configure-compiler-1.0... +Preprocessing library for configure-compiler-1.0... +Building library for configure-compiler-1.0... diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.project b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.test.hs b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.test.hs new file mode 100644 index 00000000000..2bc0ee81cb0 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/cabal.test.hs @@ -0,0 +1,11 @@ +import Test.Cabal.Prelude + +-- A 'build-type: Configure' script must be told which compiler Cabal is +-- configuring the package with (GHC's own libraries run it to generate +-- sources). cabal-install passes the compiler as a program path override, +-- so the runner has to recover it from the program db: the script checks +-- that --with-compiler / --with-hc-pkg are executable paths and that GHC +-- and GHC_PKG are exported. +main = do + skipIfWindows "relies on a POSIX shell script" + cabalTest $ cabal "v2-build" [] diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/configure b/cabal-testsuite/PackageTests/ConfigureCompiler/configure new file mode 100644 index 00000000000..1ea10c91b28 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/configure @@ -0,0 +1,21 @@ +#!/bin/sh +# A hand-written configure script: check that Cabal tells us which compiler +# it is configuring the package with, by path rather than by name. +hc=; hcpkg=; hcvar= +for arg in "$@"; do + case $arg in + --with-compiler=*) hc=${arg#--with-compiler=} ;; + --with-hc-pkg=*) hcpkg=${arg#--with-hc-pkg=} ;; + HC=*) hcvar=${arg#HC=} ;; + esac +done +fail() { echo "configure: $1" >&2; exit 1; } +[ -n "$hc" ] || fail "no --with-compiler argument" +[ -x "$hc" ] || fail "--with-compiler is not an executable path: $hc" +[ -n "$hcpkg" ] || fail "no --with-hc-pkg argument" +[ -x "$hcpkg" ] || fail "--with-hc-pkg is not an executable path: $hcpkg" +[ "$hcvar" = "$hc" ] || fail "HC= argument ($hcvar) differs from --with-compiler ($hc)" +[ -n "$GHC" ] || fail "GHC is not set in the environment" +[ "$GHC" = "$hc" ] || fail "GHC ($GHC) differs from --with-compiler ($hc)" +[ -n "$GHC_PKG" ] || fail "GHC_PKG is not set in the environment" +"$hc" --numeric-version > /dev/null || fail "cannot run $hc" diff --git a/cabal-testsuite/PackageTests/ConfigureCompiler/configure-compiler.cabal b/cabal-testsuite/PackageTests/ConfigureCompiler/configure-compiler.cabal new file mode 100644 index 00000000000..04e20b78971 --- /dev/null +++ b/cabal-testsuite/PackageTests/ConfigureCompiler/configure-compiler.cabal @@ -0,0 +1,11 @@ +cabal-version: 2.4 +name: configure-compiler +version: 1.0 +synopsis: A Configure package whose script needs the compiler +build-type: Configure +license: BSD-3-Clause + +library + exposed-modules: A + build-depends: base + default-language: Haskell2010 diff --git a/changelog.d/configure-script-compiler.md b/changelog.d/configure-script-compiler.md new file mode 100644 index 00000000000..60822a0b64c --- /dev/null +++ b/changelog.d/configure-script-compiler.md @@ -0,0 +1,14 @@ +--- +synopsis: Tell `configure` scripts which compiler Cabal is using +packages: [Cabal] +issues: [7452, 2947] +prs: 12340 +--- + +A `build-type: Configure` package's `configure` script now receives the path +of the compiler Cabal is configuring the package with: as the standard +`HC=/path/to/ghc` argument, in `--with-compiler` and `--with-hc-pkg`, and, for +GHC, in the `GHC` and `GHC_PKG` environment variables. Previously, when the +compiler was given as a program path (as cabal-install always does), the +script only got the flavour name `ghc` and had to find the compiler on `PATH`, +which may be a different one.