Skip to content

Commit c10af43

Browse files
committed
Adding an explicit pgmcxx flag for interaction with GHC
1 parent 7e0b5ad commit c10af43

12 files changed

Lines changed: 116 additions & 5 deletions

File tree

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,19 @@ componentCxxGhcOptions verbosity lbi bi clbi odir filename =
415415
MaximalDebugInfo -> ["-g3"]
416416
)
417417
++ cxxOptions bi
418-
, ghcOptCcProgram =
419-
maybeToFlag $
420-
programPath
421-
<$> lookupProgram gccProgram (withPrograms lbi)
418+
, -- Similarly, you need to add a split for cxx-sources in the configure script.
419+
-- The configure split can be found here: https://github.com/haskell/cabal/pull/10844
420+
ghcOptGppProgram =
421+
ghcOptionsSince
422+
(mkVersion [9, 4])
423+
(compiler lbi)
424+
(maybeToFlag $ programPath <$> lookupProgram gppProgram (withPrograms lbi))
425+
, -- The assumption that the C++ compiler is part of the toolchain is only since ghc-9.4.
426+
ghcOptCcProgram =
427+
ghcOptionsBefore
428+
(mkVersion [9, 4])
429+
(compiler lbi)
430+
(maybeToFlag $ programPath <$> lookupProgram gccProgram (withPrograms lbi))
422431
, ghcOptObjDir = toFlag odir
423432
, ghcOptExtra = hcOptions GHC bi
424433
}
@@ -492,6 +501,15 @@ ghcOptionsSince ver comp defOptions =
492501
| otherwise -> mempty
493502
Nothing -> mempty
494503

504+
-- Applies options only if the GHC version is less than the given one.
505+
ghcOptionsBefore :: Monoid a => Version -> Compiler -> a -> a
506+
ghcOptionsBefore ver comp defOptions =
507+
case compilerCompatVersion GHC comp of
508+
Just v
509+
| v < ver -> defOptions
510+
| otherwise -> mempty
511+
Nothing -> mempty
512+
495513
componentGhcOptions
496514
:: VerbosityLevel
497515
-> LocalBuildInfo
@@ -575,6 +593,12 @@ componentGhcOptions verbosity lbi bi clbi odir =
575593
(mkVersion [9, 4])
576594
(compiler lbi)
577595
(maybeToFlag $ programPath <$> lookupProgram gccProgram (withPrograms lbi))
596+
, -- The assumption that the C++ compiler is part of the toolchain is only since ghc-9.4.
597+
ghcOptGppProgram =
598+
ghcOptionsSince
599+
(mkVersion [9, 4])
600+
(compiler lbi)
601+
(maybeToFlag $ programPath <$> lookupProgram gppProgram (withPrograms lbi))
578602
}
579603
where
580604
exe_paths =

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,10 @@ data GhcOptions = GhcOptions
519519
, ghcOptFfiIncludes :: NubListR FilePath
520520
-- ^ Extra header files to include for old-style FFI; the @ghc -#include@ flag.
521521
, ghcOptCcProgram :: Flag FilePath
522-
-- ^ Program to use for the C and C++ compiler; the @ghc -pgmc@ flag.
522+
-- ^ Program to use for the C compiler; the @ghc -pgmc@ flag and also
523+
-- program to use for the C++ compiler before 9.4.
524+
, ghcOptGppProgram :: Flag FilePath
525+
-- ^ Program to use for the C++ compiler; the @ghc -pgmcxx@ flag.
523526
, ----------------------------
524527
-- Language and extensions
525528

@@ -874,6 +877,7 @@ renderGhcOptions comp _platform@(Platform _arch os) opts
874877
in [cxxflag ++ opt | opt <- ghcOptCxxOptions opts]
875878
, ["-opta" ++ opt | opt <- ghcOptAsmOptions opts]
876879
, concat [["-pgmc", cc] | cc <- flag ghcOptCcProgram]
880+
, concat [["-pgmcxx", cxx] | cxx <- flag ghcOptGppProgram]
877881
, -----------------
878882
-- Linker stuff
879883

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{-# LANGUAGE ForeignFunctionInterface #-}
2+
3+
module Main where
4+
5+
import Foreign.C (CInt (..))
6+
7+
foreign import ccall "pgmcxxlib.h meaning_of_life_pgmcxx"
8+
meaning_of_life_pgmcxx :: IO CInt
9+
10+
main :: IO ()
11+
main = do
12+
secret <- meaning_of_life_pgmcxx
13+
-- The value 67 comes from __TESTOPT_PGMCXX__ - see cxx-wrapper.sh.
14+
if (secret == 67)
15+
then putStrLn ("The secret is " ++ show secret)
16+
else error ("Expected value 67, got " ++ show secret)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# ForeignOptsPgmcxx
2+
3+
This test case asserts that cabal passes the `-pgmcxx` GHC option to override the C++ compiler program.
4+
5+
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`.
6+
7+
This test is skipped on Windows (no POSIX shell).

cabal-testsuite/PackageTests/FFI/ForeignOptsPgmcxx/cabal.out

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Test.Cabal.Prelude
2+
3+
main = do
4+
skipIfWindows "requires a POSIX shell script as the C++ compiler wrapper"
5+
-- The assumption that the C++ compiler is part of the toolchain is only since ghc-9.4.
6+
cabalTest $ recordMode DoNotRecord $ do
7+
skipUnlessGhcVersion ">= 9.4"
8+
cwd <- fmap testCurrentDir getTestEnv
9+
let wrapper = cwd </> "scripts/cxx-wrapper.sh"
10+
cabal "v2-build" ["foreign-opts-pgmcxx-exe"]
11+
withPlan $ runPlanExe "foreign-opts-pgmcxx" "foreign-opts-pgmcxx-exe" []
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "pgmcxxlib.h"
2+
3+
#ifndef __TESTOPT_PGMCXX__
4+
#error "Did not get required __TESTOPT_PGMCXX__ from the -pgmcxx wrapper"
5+
#endif
6+
7+
int meaning_of_life_pgmcxx() {
8+
return __TESTOPT_PGMCXX__;
9+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef PGMCXXLIB_H
2+
#define PGMCXXLIB_H
3+
extern "C" {
4+
5+
int meaning_of_life_pgmcxx();
6+
7+
}
8+
#endif
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
cabal-version: 2.2
2+
name: foreign-opts-pgmcxx
3+
version: 0.1
4+
build-type: Simple
5+
6+
executable foreign-opts-pgmcxx-exe
7+
main-is: Main.hs
8+
build-depends: base
9+
default-language: Haskell2010
10+
include-dirs: cxxbits
11+
-- The following options can be ignore with -pgmcxx by defult.
12+
-- Only gcc need stdc++ for C++ code, g++ doesn't need it.
13+
-- extra-libraries: stdc++
14+
cxx-sources: cxxbits/pgmcxxlib.cpp
15+
ghc-options: -pgmcxx scripts/cxx-wrapper.sh

0 commit comments

Comments
 (0)