From c596c676bb883f0fd7e8c6467e9e94d78ceea464 Mon Sep 17 00:00:00 2001 From: Ilia Baryshnikov Date: Sat, 9 May 2026 13:40:40 +0300 Subject: [PATCH] Adding an explicit pgmcxx flag for interaction with GHC --- Cabal/src/Distribution/Simple/GHC/Internal.hs | 48 ++++++++++++++++++- Cabal/src/Distribution/Simple/Program/GHC.hs | 5 +- .../FFI/ForeignOptsPgmcxx/Main.hs | 16 +++++++ .../FFI/ForeignOptsPgmcxx/README.md | 7 +++ .../FFI/ForeignOptsPgmcxx/cabal.out | 0 .../FFI/ForeignOptsPgmcxx/cabal.project | 1 + .../FFI/ForeignOptsPgmcxx/cabal.test.hs | 9 ++++ .../ForeignOptsPgmcxx/cxxbits/pgmcxxlib.cpp | 9 ++++ .../FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.h | 8 ++++ .../foreign-opts-pgmcxx.cabal | 15 ++++++ .../ForeignOptsPgmcxx/scripts/cxx-wrapper.sh | 4 ++ .../ShowBuildInfo/Complex/single.out | 10 ++-- .../src/Test/Cabal/OutputNormalizer.hs | 4 ++ changelog.d/11763.md | 12 +++++ 14 files changed, 141 insertions(+), 7 deletions(-) create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/Main.hs create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/README.md create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.out create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.project create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.cpp create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.h create mode 100644 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/foreign-opts-pgmcxx.cabal create mode 100755 cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/scripts/cxx-wrapper.sh create mode 100644 changelog.d/11763.md diff --git a/Cabal/src/Distribution/Simple/GHC/Internal.hs b/Cabal/src/Distribution/Simple/GHC/Internal.hs index 2a7b0ef598a..e30e70410d7 100644 --- a/Cabal/src/Distribution/Simple/GHC/Internal.hs +++ b/Cabal/src/Distribution/Simple/GHC/Internal.hs @@ -361,8 +361,16 @@ splitCandCxxOptions -> GhcOptions splitCandCxxOptions source verbosity lbi bi clbi odir filename = case source of CxxProgram -> - setCcProgram $ setCcOptions $ sourcesGhcOptions verbosity lbi bi clbi odir filename + -- For C++ sources: reset ccOptions for GHC < 8.10, because on those + -- old GHCs there's no -optcxx flag — all options go through -optc. + -- Without this reset, C-specific flags (ccOptions) would leak into + -- C++ compilation via -optc, which is wrong. + setGppProgram $ setCcOptions $ sourcesGhcOptions verbosity lbi bi clbi odir filename CcProgram -> + -- For C sources: reset cxxOptions for GHC < 8.10, because on those + -- old GHCs there's no -optcxx flag — all options go through -optc. + -- Without this reset, C++-specific flags (cxxOptions) would leak into + -- C compilation via -optc, which is wrong. setCcProgram $ setCxxOptions $ sourcesGhcOptions verbosity lbi bi clbi odir filename where setCcOptions xxx = @@ -406,6 +414,29 @@ splitCandCxxOptions source verbosity lbi bi clbi odir filename = case source of -- see example in cabal-testsuite/PackageTests/FFI/ForeignOptsPgmc ghcOptCcProgram = maybeToFlag $ programPath <$> lookupProgram gccProgram (withPrograms lbi) } + setGppProgram xxx = + xxx + { -- We explicitly pass the C++ compiler via -pgmcxx because GHC >= 9.4 + -- does not automatically detect it from the toolchain. Without this GHC + -- falls back to a gcc as a C++ compiler. + -- Related: #11805 + ghcOptGppProgram = + ghcOptionsSince + (mkVersion [9, 4]) + (compiler lbi) + (maybeToFlag $ programPath <$> lookupProgram gppProgram (withPrograms lbi)) + , -- For GHC < 9.4, which does not support -pgmcxx, we fall back to + -- passing the C++ compiler via -pgmc. This ensures C++ sources are + -- compiled with the correct compiler even on older GHCs. + -- Note: we use gppProgram (C++ compiler), NOT gccProgram (C compiler), + -- because this path is specifically for C++ source files. + -- Related: #11805 + ghcOptCcProgram = + ghcOptionsBefore + (mkVersion [9, 4]) + (compiler lbi) + (maybeToFlag $ programPath <$> lookupProgram gppProgram (withPrograms lbi)) + } sourcesGhcOptions :: VerbosityLevel @@ -454,6 +485,15 @@ ghcOptionsSince ver comp defOptions = | otherwise -> mempty Nothing -> mempty +-- Applies options only if the GHC version is less than the given one. +ghcOptionsBefore :: Monoid a => Version -> Compiler -> a -> a +ghcOptionsBefore ver comp defOptions = + case compilerCompatVersion GHC comp of + Just v + | v < ver -> defOptions + | otherwise -> mempty + Nothing -> mempty + componentGhcOptions :: VerbosityLevel -> LocalBuildInfo @@ -552,6 +592,12 @@ linkGhcOptions verbosity lbi bi clbi = (mkVersion [9, 4]) (compiler lbi) (maybeToFlag $ programPath <$> lookupProgram gccProgram (withPrograms lbi)) + , -- The assumption that the C++ compiler is part of the toolchain is only since ghc-9.4. + ghcOptGppProgram = + ghcOptionsSince + (mkVersion [9, 4]) + (compiler lbi) + (maybeToFlag $ programPath <$> lookupProgram gppProgram (withPrograms lbi)) } where exe_paths = diff --git a/Cabal/src/Distribution/Simple/Program/GHC.hs b/Cabal/src/Distribution/Simple/Program/GHC.hs index e049749ee7e..b2d692d35a1 100644 --- a/Cabal/src/Distribution/Simple/Program/GHC.hs +++ b/Cabal/src/Distribution/Simple/Program/GHC.hs @@ -519,7 +519,9 @@ data GhcOptions = GhcOptions , ghcOptFfiIncludes :: NubListR FilePath -- ^ Extra header files to include for old-style FFI; the @ghc -#include@ flag. , ghcOptCcProgram :: Flag FilePath - -- ^ Program to use for the C and C++ compiler; the @ghc -pgmc@ flag. + -- ^ Program to use for the C compiler; the @ghc -pgmc@ flag. + , ghcOptGppProgram :: Flag FilePath + -- ^ Program to use for the C++ compiler; the @ghc -pgmcxx@ flag. , ---------------------------- -- Language and extensions @@ -875,6 +877,7 @@ renderGhcOptions comp _platform@(Platform _arch os) opts in [cxxflag ++ opt | opt <- ghcOptCxxOptions opts] , ["-opta" ++ opt | opt <- ghcOptAsmOptions opts] , concat [["-pgmc", cc] | cc <- flag ghcOptCcProgram] + , concat [["-pgmcxx", cxx] | cxx <- flag ghcOptGppProgram] , ----------------- -- Linker stuff diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/Main.hs b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/Main.hs new file mode 100644 index 00000000000..67fd49994cd --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/Main.hs @@ -0,0 +1,16 @@ +{-# LANGUAGE ForeignFunctionInterface #-} + +module Main where + +import Foreign.C (CInt (..)) + +foreign import ccall "pgmcxxlib.h meaning_of_life_pgmcxx" + meaning_of_life_pgmcxx :: IO CInt + +main :: IO () +main = do + secret <- meaning_of_life_pgmcxx + -- The value 67 comes from __TESTOPT_PGMCXX__ - see cxx-wrapper.sh. + if secret == 67 + then putStrLn ("The secret is " ++ show secret) + else error ("Expected value 67, got " ++ show secret) diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/README.md b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/README.md new file mode 100644 index 00000000000..80b2da68f1a --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/README.md @@ -0,0 +1,7 @@ +# ForeignOptsPgmcxx + +This test case asserts that cabal passes the `-pgmcxx` GHC option to override the C++ compiler program. + +The cabal file sets `ghc-options: -pgmcxx scripts/cxx-wrapper.sh`, pointing GHC at a shell script wrapper (`scripts/cxx-wrapper.sh`) instead of the system C++ compiler. The wrapper adds `-D__TESTOPT_PGMCXX__=67` to every compilation and then delegates to the real `g++`. The C++ source requires `__TESTOPT_PGMCXX__` to be defined; if the wrapper is not used as the C++ compiler, the build fails with a `#error`. + +This test is skipped on Windows (no POSIX shell). diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.out b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.out new file mode 100644 index 00000000000..e69de29bb2d diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.project b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.test.hs b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.test.hs new file mode 100644 index 00000000000..920cb26c90e --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.test.hs @@ -0,0 +1,9 @@ +import Test.Cabal.Prelude + +main = do + skipIfWindows "requires a POSIX shell script as the C++ compiler wrapper" + -- The assumption that the C++ compiler is part of the toolchain is only since ghc-9.4. + cabalTest $ recordMode DoNotRecord $ do + skipUnlessGhcVersion ">= 9.4" + cabal "v2-build" ["foreign-opts-pgmcxx-exe"] + withPlan $ runPlanExe "foreign-opts-pgmcxx" "foreign-opts-pgmcxx-exe" [] diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.cpp b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.cpp new file mode 100644 index 00000000000..f8f50dab32b --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.cpp @@ -0,0 +1,9 @@ +#include "pgmcxxlib.h" + +#ifndef __TESTOPT_PGMCXX__ +#error "Did not get required __TESTOPT_PGMCXX__ from the -pgmcxx wrapper" +#endif + +int meaning_of_life_pgmcxx() { + return __TESTOPT_PGMCXX__; +} diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.h b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.h new file mode 100644 index 00000000000..fea26a8dbbf --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cxxbits/pgmcxxlib.h @@ -0,0 +1,8 @@ +#ifndef PGMCXXLIB_H +#define PGMCXXLIB_H +extern "C" { + +int meaning_of_life_pgmcxx(); + +} +#endif diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/foreign-opts-pgmcxx.cabal b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/foreign-opts-pgmcxx.cabal new file mode 100644 index 00000000000..6f85a3d609f --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/foreign-opts-pgmcxx.cabal @@ -0,0 +1,15 @@ +cabal-version: 2.2 +name: foreign-opts-pgmcxx +version: 0.1 +build-type: Simple + +executable foreign-opts-pgmcxx-exe + main-is: Main.hs + build-depends: base + default-language: Haskell2010 + include-dirs: cxxbits + -- The stdc++ extra library option is not needed given that we now pass -pgmcxx by default. + -- Only gcc need stdc++ for C++ code, g++ doesn't need it. + -- extra-libraries: stdc++ + cxx-sources: cxxbits/pgmcxxlib.cpp + ghc-options: -pgmcxx scripts/cxx-wrapper.sh diff --git a/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/scripts/cxx-wrapper.sh b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/scripts/cxx-wrapper.sh new file mode 100755 index 00000000000..a68b2621205 --- /dev/null +++ b/cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/scripts/cxx-wrapper.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# Wrapper around g++ that adds -D__TESTOPT_PGMCXX__=67 to every compilation. +# Used by the ForeignOptsPgmcxx test to verify that -pgmcxx selects this wrapper. +exec g++ -D__TESTOPT_PGMCXX__=67 "$@" diff --git a/cabal-testsuite/PackageTests/ShowBuildInfo/Complex/single.out b/cabal-testsuite/PackageTests/ShowBuildInfo/Complex/single.out index fb8047cbd02..f95744c876b 100644 --- a/cabal-testsuite/PackageTests/ShowBuildInfo/Complex/single.out +++ b/cabal-testsuite/PackageTests/ShowBuildInfo/Complex/single.out @@ -15,11 +15,11 @@ Warning: [unknown-directory] 'hs-source-dirs: doesnt-exist' specifies a director Preprocessing executable 'Complex' for Complex-0.1.0.0... Building executable 'Complex' for Complex-0.1.0.0... # show-build-info Complex exe:Complex -{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"exe","name":"exe:Complex","unit-id":"Complex-0.1.0.0-inplace-Complex","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-i","-iapp","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen/cabal_macros.h","-pgmc","","-this-unit-id","Complex-0.1.0.0-inplace-Complex","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-XHaskell2010","-threaded","-rtsopts","-with-rtsopts=-N -T","-Wredundant-constraints"],"modules":["Other","Paths_Complex"],"src-files":["Main.lhs"],"hs-src-dirs":["app"],"src-dir":"/","cabal-file":"Complex.cabal"}]} +{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"exe","name":"exe:Complex","unit-id":"Complex-0.1.0.0-inplace-Complex","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-i","-iapp","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/x/Complex/build/Complex/autogen/cabal_macros.h","-pgmc","","-pgmcxx","","-this-unit-id","Complex-0.1.0.0-inplace-Complex","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-XHaskell2010","-threaded","-rtsopts","-with-rtsopts=-N -T","-Wredundant-constraints"],"modules":["Other","Paths_Complex"],"src-files":["Main.lhs"],"hs-src-dirs":["app"],"src-dir":"/","cabal-file":"Complex.cabal"}]} # cabal build Up to date # show-build-info Complex lib -{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"lib","name":"lib","unit-id":"Complex-0.1.0.0-inplace","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-i","-isrc","-idoesnt-exist","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen/cabal_macros.h","-pgmc","","-this-unit-id","Complex-0.1.0.0-inplace","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-XHaskell2010","-Wall"],"modules":["A","B","C","D","Paths_Complex"],"src-files":[],"hs-src-dirs":["src","doesnt-exist"],"src-dir":"/","cabal-file":"Complex.cabal"}]} +{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"lib","name":"lib","unit-id":"Complex-0.1.0.0-inplace","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-i","-isrc","-idoesnt-exist","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/build/autogen/cabal_macros.h","-pgmc","","-pgmcxx","","-this-unit-id","Complex-0.1.0.0-inplace","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-XHaskell2010","-Wall"],"modules":["A","B","C","D","Paths_Complex"],"src-files":[],"hs-src-dirs":["src","doesnt-exist"],"src-dir":"/","cabal-file":"Complex.cabal"}]} # cabal build Build profile: -w ghc- -O1 In order, the following will be built: @@ -34,7 +34,7 @@ Warning: [unknown-directory] 'hs-source-dirs: doesnt-exist' specifies a director Preprocessing benchmark 'complex-benchmarks' for Complex-0.1.0.0... Building benchmark 'complex-benchmarks' for Complex-0.1.0.0... # show-build-info Complex bench:complex-benchmarks -{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"bench","name":"bench:complex-benchmarks","unit-id":"Complex-0.1.0.0-inplace-complex-benchmarks","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-i","-ibenchmark","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen/cabal_macros.h","-pgmc","","-this-unit-id","Complex-0.1.0.0-inplace-complex-benchmarks","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-package-id","","-XHaskell2010","-Wall","-rtsopts","-threaded","-with-rtsopts=-N"],"modules":["Paths_Complex"],"src-files":["Main.hs"],"hs-src-dirs":["benchmark"],"src-dir":"/","cabal-file":"Complex.cabal"}]} +{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"bench","name":"bench:complex-benchmarks","unit-id":"Complex-0.1.0.0-inplace-complex-benchmarks","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-i","-ibenchmark","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/b/complex-benchmarks/build/complex-benchmarks/autogen/cabal_macros.h","-pgmc","","-pgmcxx","","-this-unit-id","Complex-0.1.0.0-inplace-complex-benchmarks","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-package-id","","-XHaskell2010","-Wall","-rtsopts","-threaded","-with-rtsopts=-N"],"modules":["Paths_Complex"],"src-files":["Main.hs"],"hs-src-dirs":["benchmark"],"src-dir":"/","cabal-file":"Complex.cabal"}]} # cabal build Build profile: -w ghc- -O1 In order, the following will be built: @@ -49,7 +49,7 @@ Warning: [unknown-directory] 'hs-source-dirs: doesnt-exist' specifies a director Preprocessing test suite 'func-test' for Complex-0.1.0.0... Building test suite 'func-test' for Complex-0.1.0.0... # show-build-info Complex test:func-test -{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"test","name":"test:func-test","unit-id":"Complex-0.1.0.0-inplace-func-test","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-i","-itest","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen/cabal_macros.h","-pgmc","","-this-unit-id","Complex-0.1.0.0-inplace-func-test","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-package-id","","-XHaskell2010"],"modules":[],"src-files":["FuncMain.hs"],"hs-src-dirs":["test"],"src-dir":"/","cabal-file":"Complex.cabal"}]} +{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"test","name":"test:func-test","unit-id":"Complex-0.1.0.0-inplace-func-test","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-i","-itest","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/func-test/build/func-test/autogen/cabal_macros.h","-pgmc","","-pgmcxx","","-this-unit-id","Complex-0.1.0.0-inplace-func-test","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-package-id","","-XHaskell2010"],"modules":[],"src-files":["FuncMain.hs"],"hs-src-dirs":["test"],"src-dir":"/","cabal-file":"Complex.cabal"}]} # cabal build Build profile: -w ghc- -O1 In order, the following will be built: @@ -64,4 +64,4 @@ Warning: [unknown-directory] 'hs-source-dirs: doesnt-exist' specifies a director Preprocessing test suite 'unit-test' for Complex-0.1.0.0... Building test suite 'unit-test' for Complex-0.1.0.0... # show-build-info Complex test:unit-test -{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"test","name":"test:unit-test","unit-id":"Complex-0.1.0.0-inplace-unit-test","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-i","-itest","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen/cabal_macros.h","-pgmc","","-this-unit-id","Complex-0.1.0.0-inplace-unit-test","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-XHaskell2010"],"modules":[],"src-files":["UnitMain.hs"],"hs-src-dirs":["test"],"src-dir":"/","cabal-file":"Complex.cabal"}]} \ No newline at end of file +{"cabal-lib-version":"","compiler":{"flavour":"ghc","compiler-id":"ghc-","path":""},"components":[{"type":"test","name":"test:unit-test","unit-id":"Complex-0.1.0.0-inplace-unit-test","compiler-args":["-fbuilding-cabal-package","-O","-outputdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-odir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-hidir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-hiedir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/extra-compilation-artifacts/hie","-stubdir","single.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-i","-itest","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen","-isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/global-autogen","-Isingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build","-optP-include","-optPsingle.dist/work/./dist/build//ghc-/Complex-0.1.0.0/t/unit-test/build/unit-test/autogen/cabal_macros.h","-pgmc","","-pgmcxx","","-this-unit-id","Complex-0.1.0.0-inplace-unit-test","-hide-all-packages","-Wmissing-home-modules","-no-user-package-db","-package-db","/single.dist/home/.cabal/store/ghc-/package.db","-package-db","/single.dist/work/dist/packagedb/ghc-","-package-id","","-package-id","","-XHaskell2010"],"modules":[],"src-files":["UnitMain.hs"],"hs-src-dirs":["test"],"src-dir":"/","cabal-file":"Complex.cabal"}]} \ No newline at end of file diff --git a/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs b/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs index e8f104baa2b..b0aac7562d9 100644 --- a/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs +++ b/cabal-testsuite/src/Test/Cabal/OutputNormalizer.hs @@ -129,6 +129,10 @@ normalizeOutput nenv = . resub "\"-pgmc\",\"[^\"]+\"" "\"-pgmc\",\"\"" + -- Normalize the C++ compiler path embedded in -pgmcxx. + . resub + "\"-pgmcxx\",\"[^\"]+\"" + "\"-pgmcxx\",\"\"" -- Remove cabal version output from show-build-info output . resub ("{\"cabal-lib-version\":\"" ++ posixRegexEscape (display (normalizerCabalVersion nenv)) ++ "\"") diff --git a/changelog.d/11763.md b/changelog.d/11763.md new file mode 100644 index 00000000000..d0025dcf0cb --- /dev/null +++ b/changelog.d/11763.md @@ -0,0 +1,12 @@ +--- +synopsis: Add explicit `pgmcxx` flag for GHC invocation +packages: [Cabal] +prs: 11763 +--- +Add an explicit `pgmcxx` flag to Cabal's GHC invocation logic. This aligns +with the existing `pgmc` behavior and accounts for the GHC 9.4+ toolchain +requirements, resolving inconsistencies in how C++ compiler options are handled. + +This change allows users to remove `extra-libraries: stdc++` from their +configuration files, as `g++` automatically handles C++ standard library +linking, unlike the legacy approach of invoking C++ via `gcc`.