Commit 28380790 authored by Eric Conlon's avatar Eric Conlon
Browse files

Pass -optcxx for GHC >= 8.10

Fixes https://github.com/haskell/cabal/issues/6421

To summarize, Cabal passes all C and C++ flags through GHC to the underlying C or C++ compiler using -optc. This works for GHC < 8.10, but now GHC expects C++ flags to come through -optcxx. This means that anything through -optc is ignored, so we cannot pass any flags to the C++ compiler. This change simply detects the GHC version and uses the correct arguments.

This PR has been tested manually and two PackageTests have been added to cabal-testsuite. They pass under GHC 8.8.4 and GHC 8.10.2.
parent 90c46956
......@@ -686,7 +686,11 @@ renderGhcOptions comp _platform@(Platform _arch os) opts
, concat [ [ "-optP-include", "-optP" ++ inc]
| inc <- flags ghcOptCppIncludes ]
, [ "-optc" ++ opt | opt <- ghcOptCcOptions opts]
, [ "-optc" ++ opt | opt <- ghcOptCxxOptions opts]
, -- C++ compiler options: GHC >= 8.10 requires -optcxx, older requires -optc
let cxxflag = case compilerCompatVersion GHC comp of
Just v | v >= mkVersion [8, 10] -> "-optcxx"
_ -> "-optc"
in [ cxxflag ++ opt | opt <- ghcOptCxxOptions opts]
, [ "-opta" ++ opt | opt <- ghcOptAsmOptions opts]
-----------------
......
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign.C (CInt (..))
foreign import ccall "clib.h meaning_of_life_c"
meaning_of_life_c :: IO CInt
main :: IO ()
main = do
secret <- meaning_of_life_c
-- The value 11 comes from __TESTOPT_C__ - see the cabal file.
if (secret == 11)
then putStrLn ("The secret is " ++ show secret)
else error ("Expected value 11, got " ++ show secret)
# ForeignOptsC
This test case asserts that cabal passes `cc-options` to the C compiler (and NOT `cxx-options`).
See the additional case `ForeignOptsCxx`.
# cabal v2-build
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
- foreign-opts-c-0.1 (exe:foreign-opts-c-exe) (first run)
Configuring executable 'foreign-opts-c-exe' for foreign-opts-c-0.1..
Preprocessing executable 'foreign-opts-c-exe' for foreign-opts-c-0.1..
Building executable 'foreign-opts-c-exe' for foreign-opts-c-0.1..
# foreign-opts-c foreign-opts-c-exe
The secret is 11
import Test.Cabal.Prelude
main = cabalTest $ do
cabal "v2-build" ["foreign-opts-c-exe"]
withPlan $ runPlanExe "foreign-opts-c" "foreign-opts-c-exe" []
#include "clib.h"
#ifndef __TESTOPT_C__
#error "Did not get required __TESTOPT_C__ from cc-options"
#endif
#ifdef __TESTOPT_CXX__
#error "Got unexpected __TESTOPT_CXX__ from cxx-options"
#endif
int meaning_of_life_c() {
return __TESTOPT_C__;
}
#ifndef CLIB_H
#define CLIB_H
int meaning_of_life_c();
#endif
cabal-version: 2.2
name: foreign-opts-c
version: 0.1
build-type: Simple
executable foreign-opts-c-exe
main-is: Main.hs
build-depends: base
default-language: Haskell2010
include-dirs: cbits
c-sources: cbits/clib.c
-- The following options are shared in all ForeignOpts cases:
cc-options: -D__TESTOPT_C__=11
cxx-options: -D__TESTOPT_CXX__=22
{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Foreign.C (CInt (..))
foreign import ccall "cxxlib.h meaning_of_life_cxx"
meaning_of_life_cxx :: IO CInt
main :: IO ()
main = do
secret <- meaning_of_life_cxx
-- The value 22 comes from __TESTOPT_CXX__ - see the cabal file.
if (secret == 22)
then putStrLn ("The secret is " ++ show secret)
else error ("Expected value 22, got " ++ show secret)
# ForeignOptsCxx
This asserts that cabal passes `cxx-options` to the C++ compiler (and NOT `cc-options`).
Since GHC 8.10, they are passed through GHC with `-optcxx`. Before that, they were passed with `-optc`.
See the additional case `ForeignOptsC`.
# cabal v2-build
Resolving dependencies...
Build profile: -w ghc-<GHCVER> -O1
In order, the following will be built:
- foreign-opts-cxx-0.1 (exe:foreign-opts-cxx-exe) (first run)
Configuring executable 'foreign-opts-cxx-exe' for foreign-opts-cxx-0.1..
Preprocessing executable 'foreign-opts-cxx-exe' for foreign-opts-cxx-0.1..
Building executable 'foreign-opts-cxx-exe' for foreign-opts-cxx-0.1..
# foreign-opts-cxx foreign-opts-cxx-exe
The secret is 22
import Test.Cabal.Prelude
main = cabalTest $ do
cabal "v2-build" ["foreign-opts-cxx-exe"]
withPlan $ runPlanExe "foreign-opts-cxx" "foreign-opts-cxx-exe" []
#include "cxxlib.h"
#ifdef __TESTOPT_C__
#error "Got unexpected __TESTOPT_C__ from cc-options"
#endif
#ifndef __TESTOPT_CXX__
#error "Did not get required __TESTOPT_CXX__ from cxx-options"
#endif
int meaning_of_life_cxx() {
return __TESTOPT_CXX__;
}
#ifndef CXXLIB_H
#define CXXLIB_H
#ifdef __cplusplus
extern "C" {
#endif
int meaning_of_life_cxx();
#ifdef __cplusplus
}
#endif
#endif
cabal-version: 2.2
name: foreign-opts-cxx
version: 0.1
build-type: Simple
executable foreign-opts-cxx-exe
main-is: Main.hs
build-depends: base
default-language: Haskell2010
include-dirs: cxxbits
extra-libraries: stdc++
cxx-sources: cxxbits/cxxlib.cpp
-- The following options are shared in all ForeignOpts cases:
cc-options: -D__TESTOPT_C__=11
cxx-options: -D__TESTOPT_CXX__=22
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment