Skip to content

Commit

Permalink
Implement {cmm.asm}-{options,sources} for real
Browse files Browse the repository at this point in the history
While those buildinfo fields were added to the parser some time
ago via 57d7f28 and
4a28765 that work was never completed
by implementing the necessary build/sdist logic in Cabal.

This commit remedies this oversight by implementing and wiring up the
missing build logic.

NOTE: This is a backport of (at time of writing) unfinished
      #6033 to the 3.0 branch
      Specifically preprocessor-generated asm/cmm-sources need more
      work.

Co-authored-by: Sylvain Henry <sylvain@haskus.fr>
  • Loading branch information
hvr and hsyl20 committed Jul 1, 2019
1 parent 55ba720 commit c5395b8
Show file tree
Hide file tree
Showing 9 changed files with 201 additions and 15 deletions.
2 changes: 2 additions & 0 deletions Cabal/ChangeLog.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
add default implementation in terms of `coerce` / `unsafeCoerce`.
* Implement support for response file arguments to defaultMain* and cabal-install.
* Uniformly provide 'Semigroup' instances for `base < 4.9` via `semigroups` package
* Implement `{cmm,asm}-{sources,options} buildinfo fields for
separate compilation of C-- and ASM source files (#6033).

----

Expand Down
4 changes: 4 additions & 0 deletions Cabal/Distribution/PackageDescription/FieldGrammar.hs
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,9 @@ buildInfoFieldGrammar = BuildInfo
-- I.e. we don't want trigger unknown field warning
<*> monoidalFieldAla "cpp-options" (alaList' NoCommaFSep Token') L.cppOptions
<*> monoidalFieldAla "asm-options" (alaList' NoCommaFSep Token') L.asmOptions
^^^ availableSince CabalSpecV3_0 []
<*> monoidalFieldAla "cmm-options" (alaList' NoCommaFSep Token') L.cmmOptions
^^^ availableSince CabalSpecV3_0 []
<*> monoidalFieldAla "cc-options" (alaList' NoCommaFSep Token') L.ccOptions
<*> monoidalFieldAla "cxx-options" (alaList' NoCommaFSep Token') L.cxxOptions
^^^ availableSince CabalSpecV2_2 []
Expand All @@ -399,7 +401,9 @@ buildInfoFieldGrammar = BuildInfo
<*> monoidalFieldAla "frameworks" (alaList' FSep Token) L.frameworks
<*> monoidalFieldAla "extra-framework-dirs" (alaList' FSep FilePathNT) L.extraFrameworkDirs
<*> monoidalFieldAla "asm-sources" (alaList' VCat FilePathNT) L.asmSources
^^^ availableSince CabalSpecV3_0 []
<*> monoidalFieldAla "cmm-sources" (alaList' VCat FilePathNT) L.cmmSources
^^^ availableSince CabalSpecV3_0 []
<*> monoidalFieldAla "c-sources" (alaList' VCat FilePathNT) L.cSources
<*> monoidalFieldAla "cxx-sources" (alaList' VCat FilePathNT) L.cxxSources
^^^ availableSince CabalSpecV2_2 []
Expand Down
26 changes: 25 additions & 1 deletion Cabal/Distribution/Simple/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,13 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes
setupMessage' verbosity "Building" (packageId pkg_descr)
(componentLocalName clbi) (maybeComponentInstantiatedWith clbi)
let libbi = libBuildInfo lib
lib' = lib { libBuildInfo = addExtraCxxSources (addExtraCSources libbi extras) extras }
lib' = lib { libBuildInfo = flip addExtraAsmSources extras
$ flip addExtraCmmSources extras
$ flip addExtraCxxSources extras
$ flip addExtraCSources extras
$ libbi
}

buildLib verbosity numJobs pkg_descr lbi lib' clbi

let oneComponentRequested (OneComponentRequestedSpec _) = True
Expand Down Expand Up @@ -356,6 +362,24 @@ addExtraCxxSources bi extras = bi { cxxSources = new }
exs = Set.fromList extras


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


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


replComponent :: [String]
-> Verbosity
-> PackageDescription
Expand Down
73 changes: 70 additions & 3 deletions Cabal/Distribution/Simple/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -545,8 +545,12 @@ buildOrReplLib mReplFlags 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 cLikeFiles = fromNubListR $
toNubListR (cSources libBi) <> toNubListR (cxxSources libBi)
let cLikeFiles = fromNubListR $ mconcat
[ toNubListR (cSources libBi)
, toNubListR (cxxSources libBi)
, toNubListR (cmmSources libBi)
, toNubListR (asmSources libBi)
]
cObjs = map (`replaceExtension` objExtension) cLikeFiles
baseOpts = componentGhcOptions verbosity lbi libBi clbi libTargetDir
vanillaOpts = baseOpts `mappend` mempty {
Expand Down Expand Up @@ -667,7 +671,6 @@ buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do
ifReplLib (runGhcProg replOpts)

-- build any C sources
-- TODO: Add support for S and CMM files.
unless (not has_code || null (cSources libBi)) $ do
info verbosity "Building C Sources..."
sequence_
Expand Down Expand Up @@ -698,6 +701,68 @@ buildOrReplLib mReplFlags verbosity numJobs pkg_descr lbi lib clbi = do
unless forRepl $ whenProfLib (runGhcProgIfNeeded profCcOpts)
| filename <- cSources libBi]

-- build any ASM sources
unless (not has_code || null (asmSources libBi)) $ do
info verbosity "Building Assembler Sources..."
sequence_
[ do let baseAsmOpts = Internal.componentAsmGhcOptions verbosity implInfo
lbi libBi clbi libTargetDir filename
vanillaAsmOpts = if isGhcDynamic
-- Dynamic GHC requires objects to be built
-- with -fPIC for REPL to work. See #2207.
then baseAsmOpts { ghcOptFPic = toFlag True }
else baseAsmOpts
profAsmOpts = vanillaAsmOpts `mappend` mempty {
ghcOptProfilingMode = toFlag True,
ghcOptObjSuffix = toFlag "p_o"
}
sharedAsmOpts = vanillaAsmOpts `mappend` mempty {
ghcOptFPic = toFlag True,
ghcOptDynLinkMode = toFlag GhcDynamicOnly,
ghcOptObjSuffix = toFlag "dyn_o"
}
odir = fromFlag (ghcOptObjDir vanillaAsmOpts)
createDirectoryIfMissingVerbose verbosity True odir
let runGhcProgIfNeeded asmOpts = do
needsRecomp <- checkNeedsRecompilation filename asmOpts
when needsRecomp $ runGhcProg asmOpts
runGhcProgIfNeeded vanillaAsmOpts
unless forRepl $
whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedAsmOpts)
unless forRepl $ whenProfLib (runGhcProgIfNeeded profAsmOpts)
| filename <- asmSources libBi]

-- build any Cmm sources
unless (not has_code || null (cmmSources libBi)) $ do
info verbosity "Building C-- Sources..."
sequence_
[ do let baseCmmOpts = Internal.componentCmmGhcOptions verbosity implInfo
lbi libBi clbi libTargetDir filename
vanillaCmmOpts = if isGhcDynamic
-- Dynamic GHC requires C sources to be built
-- with -fPIC for REPL to work. See #2207.
then baseCmmOpts { ghcOptFPic = toFlag True }
else baseCmmOpts
profCmmOpts = vanillaCmmOpts `mappend` mempty {
ghcOptProfilingMode = toFlag True,
ghcOptObjSuffix = toFlag "p_o"
}
sharedCmmOpts = vanillaCmmOpts `mappend` mempty {
ghcOptFPic = toFlag True,
ghcOptDynLinkMode = toFlag GhcDynamicOnly,
ghcOptObjSuffix = toFlag "dyn_o"
}
odir = fromFlag (ghcOptObjDir vanillaCmmOpts)
createDirectoryIfMissingVerbose verbosity True odir
let runGhcProgIfNeeded cmmOpts = do
needsRecomp <- checkNeedsRecompilation filename cmmOpts
when needsRecomp $ runGhcProg cmmOpts
runGhcProgIfNeeded vanillaCmmOpts
unless forRepl $
whenSharedLib forceSharedLib (runGhcProgIfNeeded sharedCmmOpts)
unless forRepl $ whenProfLib (runGhcProgIfNeeded profCmmOpts)
| filename <- cmmSources libBi]

-- TODO: problem here is we need the .c files built first, so we can load them
-- with ghci, but .c files can depend on .h files generated by ghc by ffi
-- exports.
Expand Down Expand Up @@ -1932,6 +1997,8 @@ installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do
hasLib = not $ null (allLibModules lib clbi)
&& null (cSources (libBuildInfo lib))
&& null (cxxSources (libBuildInfo lib))
&& null (cmmSources (libBuildInfo lib))
&& null (asmSources (libBuildInfo lib))
has_code = not (componentIsIndefinite clbi)
whenHasCode = when has_code
whenVanilla = when (hasLib && withVanillaLib lbi)
Expand Down
81 changes: 77 additions & 4 deletions Cabal/Distribution/Simple/GHC/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ module Distribution.Simple.GHC.Internal (
targetPlatform,
getGhcInfo,
componentCcGhcOptions,
componentCmmGhcOptions,
componentCxxGhcOptions,
componentAsmGhcOptions,
componentGhcOptions,
mkGHCiLibName,
mkGHCiProfLibName,
Expand Down Expand Up @@ -335,6 +337,42 @@ componentCxxGhcOptions verbosity _implInfo lbi bi clbi odir filename =
}


componentAsmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo
-> BuildInfo -> ComponentLocalBuildInfo
-> FilePath -> FilePath
-> GhcOptions
componentAsmGhcOptions verbosity _implInfo lbi bi clbi 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 clbi
,autogenPackageModulesDir lbi
,odir]
-- includes relative to the package
++ PD.includeDirs bi
-- potential includes generated by `configure'
-- in the build directory
++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],
ghcOptHideAllPackages= toFlag True,
ghcOptPackageDBs = withPackageDB lbi,
ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,
ghcOptAsmOptions = (case withOptimization lbi of
NoOptimisation -> []
_ -> ["-O2"]) ++
(case withDebugInfo lbi of
NoDebugInfo -> []
MinimalDebugInfo -> ["-g1"]
NormalDebugInfo -> ["-g"]
MaximalDebugInfo -> ["-g3"]) ++
PD.asmOptions bi,
ghcOptObjDir = toFlag odir
}


componentGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo
-> BuildInfo -> ComponentLocalBuildInfo -> FilePath
-> GhcOptions
Expand Down Expand Up @@ -396,15 +434,50 @@ componentGhcOptions verbosity implInfo lbi bi clbi odir =
ghcOptExtensionMap = Map.fromList . compilerExtensions $ (compiler lbi)
}
where
toGhcOptimisation NoOptimisation = mempty --TODO perhaps override?
toGhcOptimisation NormalOptimisation = toFlag GhcNormalOptimisation
toGhcOptimisation MaximumOptimisation = toFlag GhcMaximumOptimisation

exe_paths = [ componentBuildDir lbi (targetCLBI exe_tgt)
| uid <- componentExeDeps clbi
-- TODO: Ugh, localPkgDescr
, Just exe_tgt <- [unitIdTarget' (localPkgDescr lbi) lbi uid] ]

toGhcOptimisation :: OptimisationLevel -> Flag GhcOptimisation
toGhcOptimisation NoOptimisation = mempty --TODO perhaps override?
toGhcOptimisation NormalOptimisation = toFlag GhcNormalOptimisation
toGhcOptimisation MaximumOptimisation = toFlag GhcMaximumOptimisation


componentCmmGhcOptions :: Verbosity -> GhcImplInfo -> LocalBuildInfo
-> BuildInfo -> ComponentLocalBuildInfo
-> FilePath -> FilePath
-> GhcOptions
componentCmmGhcOptions verbosity _implInfo lbi bi clbi 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 clbi
,autogenPackageModulesDir lbi
,odir]
-- includes relative to the package
++ PD.includeDirs bi
-- potential includes generated by `configure'
-- in the build directory
++ [buildDir lbi </> dir | dir <- PD.includeDirs bi],
ghcOptCppOptions = cppOptions bi,
ghcOptCppIncludes = toNubListR $
[autogenComponentModulesDir lbi clbi </> cppHeaderName],
ghcOptHideAllPackages= toFlag True,
ghcOptPackageDBs = withPackageDB lbi,
ghcOptPackages = toNubListR $ mkGhcOptPackages clbi,
ghcOptOptimisation = toGhcOptimisation (withOptimization lbi),
ghcOptDebugInfo = toFlag (withDebugInfo lbi),
ghcOptExtra = cmmOptions bi,
ghcOptObjDir = toFlag odir
}


-- | Strip out flags that are not supported in ghci
filterGhciFlags :: [String] -> [String]
filterGhciFlags = filter supported
Expand Down
4 changes: 4 additions & 0 deletions Cabal/Distribution/Simple/Program/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,9 @@ data GhcOptions = GhcOptions {
-- | Options to pass through to the C++ compiler.
ghcOptCxxOptions :: [String],

-- | Options to pass through to the Assembler.
ghcOptAsmOptions :: [String],

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

Expand Down Expand Up @@ -665,6 +668,7 @@ renderGhcOptions comp _platform@(Platform _arch os) opts
| inc <- flags ghcOptCppIncludes ]
, [ "-optc" ++ opt | opt <- ghcOptCcOptions opts]
, [ "-optc" ++ opt | opt <- ghcOptCxxOptions opts]
, [ "-opta" ++ opt | opt <- ghcOptAsmOptions opts]

-----------------
-- Linker stuff
Expand Down
3 changes: 2 additions & 1 deletion Cabal/Distribution/Simple/SrcDist.hs
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,8 @@ allSourcesBuildInfo verbosity bi pps modules = do
in findFileWithExtension fileExts (hsSourceDirs bi) file
| module_ <- modules ++ otherModules bi ]

return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi ++ jsSources bi
return $ sources ++ catMaybes bootFiles ++ cSources bi ++ cxxSources bi ++
cmmSources bi ++ asmSources bi ++ jsSources bi

where
nonEmpty x _ [] = x
Expand Down
11 changes: 9 additions & 2 deletions Cabal/doc/developing-packages.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2478,12 +2478,13 @@ system-dependent values for these fields.
appropriately.

.. pkg-field:: asm-sources: filename list
:since: 2.2
:since: 3.0

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

.. pkg-field:: cmm-sources: filename list
:since: 3.0

A list of C-- source files to be compiled and linked with the Haskell
files.
Expand Down Expand Up @@ -2550,8 +2551,14 @@ system-dependent values for these fields.
command-line arguments with the :pkg-field:`cc-options` and the
:pkg-field:`cxx-options` fields.

.. pkg-field:: cmm-options: token list
:since: 3.0

Command-line arguments to be passed to the compiler when compiling
C-- code. See also :pkg-field:`cmm-sources`.

.. pkg-field:: asm-options: token list
:since: 2.2
:since: 3.0

Command-line arguments to be passed to the assembler when compiling
assembler code. See also :pkg-field:`asm-sources`.
Expand Down
12 changes: 8 additions & 4 deletions Cabal/doc/file-format-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ relative to the respective preceding *published* version.
* New :pkg-field:`autogen-includes` for specifying :pkg-field:`install-includes`
which are autogenerated (e.g. by a ``configure`` script).

* New :pkg-field:`asm-sources` and :pkg-field:`asm-options` fields
added for suppporting bundled foreign routines implemented in
assembler.

* New :pkg-field:`cmm-sources` and :pkg-field:`cmm-options` fields
added for suppporting bundled foreign primops implemented in
C--.

``cabal-version: 2.4``
----------------------

Expand Down Expand Up @@ -104,10 +112,6 @@ relative to the respective preceding *published* version.
* New :pkg-field:`cxx-sources` and :pkg-field:`cxx-options` fields
added for suppporting bundled foreign routines implemented in C++.

* New :pkg-field:`asm-sources` and :pkg-field:`asm-options` fields
added for suppporting bundled foreign routines implemented in
assembler.

* New :pkg-field:`extra-bundled-libraries` field for specifying
additional custom library objects to be installed.

Expand Down

0 comments on commit c5395b8

Please sign in to comment.