Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added cxx-options and cxx-sources build info fields for separate compilation of C and C++ source files. #4810

Merged
merged 7 commits into from
Oct 5, 2017
1 change: 1 addition & 0 deletions Cabal/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,7 @@ checkPaths pkg =
++ [ (path, "license-file") | path <- licenseFiles pkg ]
++ concat
[ [ (path, "c-sources") | path <- cSources bi ]
++ [ (path, "cxx-sources") | path <- cxxSources bi ]
++ [ (path, "js-sources") | path <- jsSources bi ]
++ [ (path, "install-includes") | path <- installIncludes bi ]
++ [ (path, "hs-source-dirs") | path <- hsSourceDirs bi ]
Expand Down
2 changes: 2 additions & 0 deletions Cabal/Distribution/PackageDescription/FieldGrammar.hs
Original file line number Diff line number Diff line change
Expand Up @@ -361,11 +361,13 @@ buildInfoFieldGrammar = BuildInfo
^^^ availableSince [2,0]
<*> monoidalFieldAla "cpp-options" (alaList' NoCommaFSep Token') L.cppOptions
<*> monoidalFieldAla "cc-options" (alaList' NoCommaFSep Token') L.ccOptions
<*> monoidalFieldAla "cxx-options" (alaList' NoCommaFSep Token') L.cxxOptions
<*> monoidalFieldAla "ld-options" (alaList' NoCommaFSep Token') L.ldOptions
<*> monoidalFieldAla "pkgconfig-depends" (alaList CommaFSep) L.pkgconfigDepends
<*> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks
<*> monoidalFieldAla "extra-framework-dirs" (alaList' FSep FilePathNT) L.extraFrameworkDirs
<*> monoidalFieldAla "c-sources" (alaList' VCat FilePathNT) L.cSources
<*> monoidalFieldAla "cxx-sources" (alaList' VCat FilePathNT) L.cxxSources
<*> monoidalFieldAla "js-sources" (alaList' VCat FilePathNT) L.jsSources
<*> hsSourceDirsGrammar
<*> monoidalFieldAla "other-modules" (alaList' VCat MQuoted) L.otherModules
Expand Down
6 changes: 6 additions & 0 deletions Cabal/Distribution/PackageDescription/Parse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,9 @@ binfoFieldDescrs =
, spaceListField "cc-options"
showToken parseTokenQ'
ccOptions (\val binfo -> binfo{ccOptions=val})
, spaceListField "cxx-options"
showToken parseTokenQ'
cxxOptions (\val binfo -> binfo{cxxOptions=val})
, spaceListField "ld-options"
showToken parseTokenQ'
ldOptions (\val binfo -> binfo{ldOptions=val})
Expand All @@ -456,6 +459,9 @@ binfoFieldDescrs =
, listFieldWithSep vcat "c-sources"
showFilePath parseFilePathQ
cSources (\paths binfo -> binfo{cSources=paths})
, listFieldWithSep vcat "cxx-sources"
showFilePath parseFilePathQ
cxxSources (\paths binfo -> binfo{cxxSources=paths})
, listFieldWithSep vcat "js-sources"
showFilePath parseFilePathQ
jsSources (\paths binfo -> binfo{jsSources=paths})
Expand Down
11 changes: 10 additions & 1 deletion Cabal/Distribution/Simple/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes
setupMessage' verbosity "Building" (packageId pkg_descr)
(componentLocalName clbi) (maybeComponentInstantiatedWith clbi)
let libbi = libBuildInfo lib
lib' = lib { libBuildInfo = addExtraCSources libbi extras }
lib' = lib { libBuildInfo = addExtraCxxSources (addExtraCSources libbi extras) extras }
buildLib verbosity numJobs pkg_descr lbi lib' clbi

let oneComponentRequested (OneComponentRequestedSpec _) = True
Expand Down Expand Up @@ -329,6 +329,15 @@ addExtraCSources bi extras = bi { cSources = new }
exs = Set.fromList extras


-- | Add extra C++ sources generated by preprocessing to build
-- information.
addExtraCxxSources :: BuildInfo -> [FilePath] -> BuildInfo
addExtraCxxSources bi extras = bi { cxxSources = new }
where new = Set.toList $ old `Set.union` exs
old = Set.fromList $ cxxSources bi
exs = Set.fromList extras


replComponent :: Verbosity
-> PackageDescription
-> LocalBuildInfo
Expand Down
44 changes: 37 additions & 7 deletions Cabal/Distribution/Simple/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,8 @@ buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
createDirectoryIfMissingVerbose verbosity True libTargetDir
-- TODO: do we need to put hs-boot files into place for mutually recursive
-- modules?
let cObjs = map (`replaceExtension` objExtension) (cSources libBi)
let cLikeFiles = fromNubListR $ toNubListR (cSources libBi) <> toNubListR (cxxSources libBi)
cObjs = map (`replaceExtension` objExtension) cLikeFiles
baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir
vanillaOpts = baseOpts `mappend` mempty {
ghcOptMode = toFlag GhcModeMake,
Expand Down Expand Up @@ -644,6 +645,39 @@ buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
else do vanilla; shared
whenProfLib (runGhcProg profOpts)

-- build any C++ sources seperately
unless (not has_code || null (cxxSources libBi)) $ do
info verbosity "Building C++ Sources..."
sequence_
[ do let baseCxxOpts = Internal.componentCxxGhcOptions verbosity implInfo
lbi libBi clbi libTargetDir filename
vanillaCxxOpts = if isGhcDynamic
then baseCxxOpts { ghcOptFPic = toFlag True }
else baseCxxOpts
profCxxOpts = vanillaCxxOpts `mappend` mempty {
ghcOptProfilingMode = toFlag True,
ghcOptObjSuffix = toFlag "p_o"
}
sharedCxxOpts = vanillaCxxOpts `mappend` mempty {
ghcOptFPic = toFlag True,
ghcOptDynLinkMode = toFlag GhcDynamicOnly,
ghcOptObjSuffix = toFlag "dyn_o"
}
odir = fromFlag (ghcOptObjDir vanillaCxxOpts)
createDirectoryIfMissingVerbose verbosity True odir
let runGhcProgIfNeeded cxxOpts = do
needsRecomp <- checkNeedsRecompilation filename cxxOpts
when needsRecomp $ runGhcProg cxxOpts
runGhcProgIfNeeded vanillaCxxOpts
unless forRepl $
whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCxxOpts)
unless forRepl $ whenProfLib (runGhcProgIfNeeded profCxxOpts)
| filename <- cxxSources libBi]

when has_code . ifReplLib $ do
when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"
ifReplLib (runGhcProg replOpts)

-- build any C sources
unless (not has_code || null (cSources libBi)) $ do
info verbosity "Building C Sources..."
Expand Down Expand Up @@ -679,17 +713,13 @@ buildOrReplLib forRepl verbosity numJobs pkg_descr lbi lib clbi = do
-- with ghci, but .c files can depend on .h files generated by ghc by ffi
-- exports.

when has_code . ifReplLib $ do
when (null (allLibModules lib clbi)) $ warn verbosity "No exposed modules"
ifReplLib (runGhcProg replOpts)

-- link:
when has_code . unless forRepl $ do
info verbosity "Linking..."
let cProfObjs = map (`replaceExtension` ("p_" ++ objExtension))
(cSources libBi)
(cSources libBi ++ cxxSources libBi)
cSharedObjs = map (`replaceExtension` ("dyn_" ++ objExtension))
(cSources libBi)
(cSources libBi ++ cxxSources libBi)
compiler_id = compilerId (compiler lbi)
vanillaLibFilePath = libTargetDir </> mkLibName uid
profileLibFilePath = libTargetDir </> mkProfLibName uid
Expand Down
35 changes: 35 additions & 0 deletions Cabal/Distribution/Simple/GHC/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Distribution.Simple.GHC.Internal (
targetPlatform,
getGhcInfo,
componentCcGhcOptions,
componentCxxGhcOptions,
componentGhcOptions,
mkGHCiLibName,
filterGhciFlags,
Expand Down Expand Up @@ -290,6 +291,40 @@ componentCcGhcOptions verbosity _implInfo lbi bi clbi odir filename =
ghcOptObjDir = toFlag odir
}


componentCxxGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo
-> BuildInfo -> ComponentLocalBuildInfo
-> FilePath -> FilePath
-> GhcOptions
componentCxxGhcOptions verbosity _implInfo lbi bi cxxlbi odir filename =
mempty {
-- Respect -v0, but don't crank up verbosity on GHC if
-- Cabal verbosity is requested. For that, use --ghc-option=-v instead!
ghcOptVerbosity = toFlag (min verbosity normal),
ghcOptMode = toFlag GhcModeCompile,
ghcOptInputFiles = toNubListR [filename],

ghcOptCppIncludePath = toNubListR $ [autogenComponentModulesDir lbi cxxlbi
,autogenPackageModulesDir lbi
,odir]
++ PD.includeDirs bi,
ghcOptHideAllPackages= toFlag True,
ghcOptPackageDBs = withPackageDB lbi,
ghcOptPackages = toNubListR $ mkGhcOptPackages cxxlbi,
ghcOptCxxOptions = toNubListR $
(case withOptimization lbi of
NoOptimisation -> []
_ -> ["-O2"]) ++
(case withDebugInfo lbi of
NoDebugInfo -> []
MinimalDebugInfo -> ["-g1"]
NormalDebugInfo -> ["-g"]
MaximalDebugInfo -> ["-g3"]) ++
PD.cxxOptions bi,
ghcOptObjDir = toFlag odir
}


componentGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo
-> BuildInfo -> ComponentLocalBuildInfo -> FilePath
-> GhcOptions
Expand Down
8 changes: 7 additions & 1 deletion Cabal/Distribution/Simple/Program/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ data GhcOptions = GhcOptions {
-- | Options to pass through to the C compiler; the @ghc -optc@ flag.
ghcOptCcOptions :: NubListR String,

-- | Options to pass through to the C++ compiler.
ghcOptCxxOptions :: NubListR String,

-- | Options to pass through to CPP; the @ghc -optP@ flag.
ghcOptCppOptions :: NubListR String,

Expand Down Expand Up @@ -392,13 +395,16 @@ renderGhcOptions comp _platform@(Platform _arch os) opts
, [ "-i" ++ dir | dir <- flags ghcOptSourcePath ]

--------------------
-- C and CPP stuff

--------------------
-- CPP, C, and C++ stuff

, [ "-I" ++ dir | dir <- flags ghcOptCppIncludePath ]
, [ "-optP" ++ opt | opt <- flags ghcOptCppOptions ]
, concat [ [ "-optP-include", "-optP" ++ inc]
| inc <- flags ghcOptCppIncludes ]
, [ "-optc" ++ opt | opt <- flags ghcOptCcOptions ]
, [ "-optc" ++ opt | opt <- flags ghcOptCxxOptions ]

-----------------
-- Linker stuff
Expand Down
6 changes: 6 additions & 0 deletions Cabal/Distribution/Types/BuildInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,13 @@ data BuildInfo = BuildInfo {
buildToolDepends :: [ExeDependency],
cppOptions :: [String], -- ^ options for pre-processing Haskell code
ccOptions :: [String], -- ^ options for C compiler
cxxOptions :: [String], -- ^ options for C++ compiler
ldOptions :: [String], -- ^ options for linker
pkgconfigDepends :: [PkgconfigDependency], -- ^ pkg-config packages that are used
frameworks :: [String], -- ^support frameworks for Mac OS X
extraFrameworkDirs:: [String], -- ^ extra locations to find frameworks.
cSources :: [FilePath],
cxxSources :: [FilePath],
jsSources :: [FilePath],
hsSourceDirs :: [FilePath], -- ^ where to look for the Haskell module hierarchy
otherModules :: [ModuleName], -- ^ non-exposed or non-main modules
Expand Down Expand Up @@ -95,11 +97,13 @@ instance Monoid BuildInfo where
buildToolDepends = [],
cppOptions = [],
ccOptions = [],
cxxOptions = [],
ldOptions = [],
pkgconfigDepends = [],
frameworks = [],
extraFrameworkDirs = [],
cSources = [],
cxxSources = [],
jsSources = [],
hsSourceDirs = [],
otherModules = [],
Expand Down Expand Up @@ -132,11 +136,13 @@ instance Semigroup BuildInfo where
buildToolDepends = combine buildToolDepends,
cppOptions = combine cppOptions,
ccOptions = combine ccOptions,
cxxOptions = combine cxxOptions,
ldOptions = combine ldOptions,
pkgconfigDepends = combine pkgconfigDepends,
frameworks = combineNub frameworks,
extraFrameworkDirs = combineNub extraFrameworkDirs,
cSources = combineNub cSources,
cxxSources = combineNub cxxSources,
jsSources = combineNub jsSources,
hsSourceDirs = combineNub hsSourceDirs,
otherModules = combineNub otherModules,
Expand Down
14 changes: 14 additions & 0 deletions Cabal/Distribution/Types/BuildInfo/Lens.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class HasBuildInfo a where
ccOptions = buildInfo . ccOptions
{-# INLINE ccOptions #-}

cxxOptions :: Lens' a [String]
cxxOptions = buildInfo . cxxOptions
{-# INLINE cxxOptions #-}

ldOptions :: Lens' a [String]
ldOptions = buildInfo . ldOptions
{-# INLINE ldOptions #-}
Expand All @@ -63,6 +67,10 @@ class HasBuildInfo a where
cSources = buildInfo . cSources
{-# INLINE cSources #-}

cxxSources :: Lens' a [FilePath]
cxxSources = buildInfo . cxxSources
{-# INLINE cxxSources #-}

jsSources :: Lens' a [FilePath]
jsSources = buildInfo . jsSources
{-# INLINE jsSources #-}
Expand Down Expand Up @@ -171,6 +179,9 @@ instance HasBuildInfo BuildInfo where
ccOptions f s = fmap (\x -> s { T.ccOptions = x }) (f (T.ccOptions s))
{-# INLINE ccOptions #-}

cxxOptions f s = fmap (\x -> s { T.cxxOptions = x }) (f (T.cxxOptions s))
{-# INLINE cxxOptions #-}

ldOptions f s = fmap (\x -> s { T.ldOptions = x }) (f (T.ldOptions s))
{-# INLINE ldOptions #-}

Expand All @@ -186,6 +197,9 @@ instance HasBuildInfo BuildInfo where
cSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cSources s))
{-# INLINE cSources #-}

cxxSources f s = fmap (\x -> s { T.cSources = x }) (f (T.cxxSources s))
{-# INLINE cxxSources #-}

jsSources f s = fmap (\x -> s { T.jsSources = x }) (f (T.jsSources s))
{-# INLINE jsSources #-}

Expand Down
2 changes: 2 additions & 0 deletions Cabal/changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
-*-change-log-*-

2.2.0.0 (current development version)
* Added cxx-options and cxx-sources build info fields for seperate
compilation of C++ source files (#3700)
* Remove unused '--allow-newer'/'--allow-older' support (#4527)
* Change `rawSystemStdInOut` to use proper type to represent
binary and textual data; new 'Distribution.Utils.IOData' module;
Expand Down
24 changes: 23 additions & 1 deletion Cabal/doc/developing-packages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2024,12 +2024,22 @@ system-dependent values for these fields.
source tree. Cabal looks in these directories when attempting to
locate files listed in :pkg-field:`includes` and
:pkg-field:`install-includes`.

.. pkg-field:: c-sources: filename list

A list of C source files to be compiled and linked with the Haskell
files.

.. pkg-field:: cxx-sources: filename list

A list of C++ source files to be compiled and linked with the Haskell
files. Useful for segregating C and C++ sources when supplying different
command-line arguments to the compiler via the :pkg-field:`cc-options`
and the :pkg-field:`cxx-options` fields. The files listed in the
:pkg-field:`cxx-sources` can reference files listed in the
:pkg-field:`c-sources` field and vice-versa. The object files will be linked
appropriately.

.. pkg-field:: js-sources: filename list

A list of JavaScript source files to be linked with the Haskell
Expand Down Expand Up @@ -2060,6 +2070,18 @@ system-dependent values for these fields.
haskell source and other pre-processed Haskell source like .hsc
.chs. Does not apply to C code, that's what cc-options is for.

.. pkg-field:: cxx-options: token list

Command-line arguments to be passed to the compiler when compiling
C++ code. The C++ sources to which these command-line arguments
should be applied can be specified with the :pkg-field:`cxx-sources`
field. Command-line options for C and C++ can be passed separately to
the compiler when compiling both C and C++ sources by segregating the C
and C++ sources with the :pkg-field:`c-sources` and
:pkg-field:`cxx-sources` fields respectively, and providing different
command-line arguments with the :pkg-field:`cc-options` and the
:pkg-field:`cxx-options` fields.

.. pkg-field:: ld-options: token list

Command-line arguments to be passed to the linker. Since the
Expand Down
7 changes: 7 additions & 0 deletions cabal-install/changelog
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
-*-change-log-*-

2.2.0.0 (current development version)
* New config file field: 'cxx-options' to specify which options to be
passed to the compiler when compiling C++ sources specified by the
'cxx-sources' field. (#3700)
* New config file field: 'cxx-sources' to specify C++ files to be
compiled separately from C source files. Useful in conjunction with the
'cxx-options' flag to pass different compiler options to C and C++
source files. (#3700)
* 'cabal configure' now supports '--enable-static' which can be
used to build static libaries with GHC via GHC's `-staticlib` flag.
* Don't automatically/silently case-correct mispelled package-names
Expand Down