Skip to content

Commit e929e22

Browse files
committed
Adding an explicit pgmc flag for interaction with GHC
1 parent 71b3c85 commit e929e22

17 files changed

Lines changed: 340 additions & 55 deletions

File tree

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ import Distribution.Types.GivenComponent
8181
import Distribution.Types.LocalBuildInfo
8282
import Distribution.Types.TargetInfo
8383
import Distribution.Types.UnitId
84+
import Distribution.Types.Version
8485
import Distribution.Utils.NubList (NubListR, toNubListR)
8586
import Distribution.Utils.Path
8687
import Distribution.Verbosity
87-
import Distribution.Version (Version)
8888
import Language.Haskell.Extension
8989
import System.Directory (listDirectory)
9090
import System.Environment (getEnv)
@@ -514,6 +514,16 @@ componentJsGhcOptions verbosity lbi bi clbi odir filename =
514514
, ghcOptExtra = hcOptions GHC bi
515515
}
516516

517+
-- Applies options only if the GHC version is greater than or
518+
-- equal to the given one.
519+
ghcOptionsSince :: Monoid a => Version -> Compiler -> a -> a
520+
ghcOptionsSince ver comp options =
521+
case compilerCompatVersion GHC comp of
522+
Just v
523+
| v >= ver -> options
524+
| otherwise -> mempty
525+
Nothing -> mempty
526+
517527
componentGhcOptions
518528
:: VerbosityLevel
519529
-> LocalBuildInfo
@@ -587,6 +597,15 @@ componentGhcOptions verbosity lbi bi clbi odir =
587597
, -- Unsupported extensions have already been checked by configure
588598
ghcOptExtensions = toNubListR $ usedExtensions bi
589599
, ghcOptExtensionMap = Map.fromList . compilerExtensions $ (compiler lbi)
600+
, -- https://gitlab.haskell.org/ghc/ghc/-/merge_requests/6949
601+
-- Only pass -pie, -no-pie when linking the value of -pgmc
602+
-- does not matter when checking for the workaround of
603+
-- https://gitlab.haskell.org/ghc/ghc/-/issues/15319
604+
ghcOptCcProgram =
605+
ghcOptionsSince
606+
(mkVersion [9, 4])
607+
(compiler lbi)
608+
(maybeToFlag $ programPath <$> lookupProgram gccProgram (withPrograms lbi))
590609
}
591610
where
592611
exe_paths =
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 "pgmclib.h meaning_of_life_pgmc"
8+
meaning_of_life_pgmc :: IO CInt
9+
10+
main :: IO ()
11+
main = do
12+
secret <- meaning_of_life_pgmc
13+
-- The value 66 comes from __TESTOPT_PGMC__ - see cc-wrapper.sh.
14+
if (secret == 66)
15+
then putStrLn ("The secret is " ++ show secret)
16+
else error ("Expected value 66, got " ++ show secret)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# ForeignOptsPgmc
2+
3+
This test case asserts that cabal passes the `-pgmc` GHC option to override the C compiler program.
4+
5+
The cabal file sets `ghc-options: -pgmc scripts/cc-wrapper.sh`, pointing GHC at a shell script wrapper (`scripts/cc-wrapper.sh`) instead of the system C compiler. The wrapper adds `-D__TESTOPT_PGMC__=66` to every compilation and then delegates to the real `cc`. The C source requires `__TESTOPT_PGMC__` 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).
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# cabal v2-build
2+
Resolving dependencies...
3+
Build profile: -w ghc-<GHCVER> -O1
4+
In order, the following will be built:
5+
- foreign-opts-pgmc-0.1 (exe:foreign-opts-pgmc-exe) (first run)
6+
Configuring executable 'foreign-opts-pgmc-exe' for foreign-opts-pgmc-0.1...
7+
Preprocessing executable 'foreign-opts-pgmc-exe' for foreign-opts-pgmc-0.1...
8+
Building executable 'foreign-opts-pgmc-exe' for foreign-opts-pgmc-0.1...
9+
# foreign-opts-pgmc foreign-opts-pgmc-exe
10+
The secret is 66
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
packages: .
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import Test.Cabal.Prelude
2+
3+
main = do
4+
skipIfWindows "requires a POSIX shell script as the C compiler wrapper"
5+
cabalTest $ do
6+
skipUnlessGhcVersion ">= 9.4"
7+
cwd <- fmap testCurrentDir getTestEnv
8+
let wrapper = cwd </> "scripts/cc-wrapper.sh"
9+
cabal "v2-build" ["foreign-opts-pgmc-exe"]
10+
withPlan $ runPlanExe "foreign-opts-pgmc" "foreign-opts-pgmc-exe" []
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include "pgmclib.h"
2+
3+
#ifndef __TESTOPT_PGMC__
4+
#error "Did not get required __TESTOPT_PGMC__ from the -pgmc wrapper"
5+
#endif
6+
7+
int meaning_of_life_pgmc() {
8+
return __TESTOPT_PGMC__;
9+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef PGMCLIB_H
2+
#define PGMCLIB_H
3+
4+
int meaning_of_life_pgmc();
5+
6+
#endif
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cabal-version: 2.2
2+
name: foreign-opts-pgmc
3+
version: 0.1
4+
build-type: Simple
5+
6+
executable foreign-opts-pgmc-exe
7+
main-is: Main.hs
8+
build-depends: base
9+
default-language: Haskell2010
10+
include-dirs: cbits
11+
c-sources: cbits/pgmclib.c
12+
ghc-options: -pgmc scripts/cc-wrapper.sh
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
# Wrapper around cc that adds -D__TESTOPT_PGMC__=66 to every compilation.
3+
# Used by the ForeignOptsPgmc test to verify that -pgmc selects this wrapper.
4+
exec cc -D__TESTOPT_PGMC__=66 "$@"

0 commit comments

Comments
 (0)