Skip to content

Commit a090a49

Browse files
committed
One-component configure, fixes #2802.
Described in: ghc-proposals/ghc-proposals#4 ./Setup configure now takes an argument to specify a specific component name that should solely be configured. Most of the gyrations in Configure are all about making it so that we can feed in internal dependencies via --dependency. I dropped the package name match sanity check to handle convenience library package name munging. Consider an internal library named 'q' in package 'p'. When we install it to the package database, we munged the package name into 'z-p-z-q', so that it doesn't conflict with the actual package named 'q'. Now consider when we feed it in with --dependency q=p-0.1-hash-q. Previously, Cabal checked that the 'q' in --dependency matched the package name in the database... which it doesn't. So I dropped the check. I also had to make register/copy unconditionally install internal libraries; otherwise you can't refer to them from later builds. Also a miscellaneous refactor: convenience libraries are printed with a "header" stanza now (not really a stanza header). Signed-off-by: Edward Z. Yang <[email protected]>
1 parent a06460c commit a090a49

File tree

29 files changed

+417
-144
lines changed

29 files changed

+417
-144
lines changed

Cabal/Cabal.cabal

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,17 @@ extra-source-files:
108108
tests/PackageTests/Configure/include/HsZlibConfig.h.in
109109
tests/PackageTests/Configure/zlib.buildinfo.in
110110
tests/PackageTests/Configure/zlib.cabal
111+
tests/PackageTests/ConfigureComponent/Exe/Bad.hs
112+
tests/PackageTests/ConfigureComponent/Exe/Exe.cabal
113+
tests/PackageTests/ConfigureComponent/Exe/Good.hs
114+
tests/PackageTests/ConfigureComponent/SubLib/Lib.cabal
115+
tests/PackageTests/ConfigureComponent/SubLib/Lib.hs
116+
tests/PackageTests/ConfigureComponent/SubLib/exe/Exe.hs
117+
tests/PackageTests/ConfigureComponent/Test/Lib.hs
118+
tests/PackageTests/ConfigureComponent/Test/Test.cabal
119+
tests/PackageTests/ConfigureComponent/Test/testlib/TestLib.hs
120+
tests/PackageTests/ConfigureComponent/Test/testlib/testlib.cabal
121+
tests/PackageTests/ConfigureComponent/Test/tests/Test.hs
111122
tests/PackageTests/CopyAssumeDepsUpToDate/CopyAssumeDepsUpToDate.cabal
112123
tests/PackageTests/CopyAssumeDepsUpToDate/Main.hs
113124
tests/PackageTests/CopyAssumeDepsUpToDate/P.hs

Cabal/Distribution/PackageDescription/Configuration.hs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,11 +421,14 @@ overallDependencies enabled (TargetSet targets) = mconcat depss
421421
where
422422
(depss, _) = unzip $ filter (removeDisabledSections . snd) targets
423423
removeDisabledSections :: PDTagged -> Bool
424-
removeDisabledSections (Lib l) = componentEnabled enabled (CLib l)
425-
removeDisabledSections (SubLib _ l) = componentEnabled enabled (CLib l)
426-
removeDisabledSections (Exe _ e) = componentEnabled enabled (CExe e)
427-
removeDisabledSections (Test _ t) = componentEnabled enabled (CTest t)
428-
removeDisabledSections (Bench _ b) = componentEnabled enabled (CBench b)
424+
-- UGH. The embedded componentName in the 'Component's here is
425+
-- BLANK. I don't know whose fault this is but I'll use the tag
426+
-- instead. -- ezyang
427+
removeDisabledSections (Lib _) = componentNameEnabled enabled CLibName
428+
removeDisabledSections (SubLib t _) = componentNameEnabled enabled (CSubLibName t)
429+
removeDisabledSections (Exe t _) = componentNameEnabled enabled (CExeName t)
430+
removeDisabledSections (Test t _) = componentNameEnabled enabled (CTestName t)
431+
removeDisabledSections (Bench t _) = componentNameEnabled enabled (CBenchName t)
429432
removeDisabledSections PDNull = True
430433

431434
-- Apply extra constraints to a dependency map.

Cabal/Distribution/Simple.hs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,6 @@ defaultUserHooks = autoconfUserHooks {
579579
-- https://github.com/haskell/cabal/issues/158
580580
where oldCompatPostConf args flags pkg_descr lbi
581581
= do let verbosity = fromFlag (configVerbosity flags)
582-
noExtraFlags args
583582
confExists <- doesFileExist "configure"
584583
when confExists $
585584
runConfigureScript verbosity
@@ -610,7 +609,6 @@ autoconfUserHooks
610609
where defaultPostConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
611610
defaultPostConf args flags pkg_descr lbi
612611
= do let verbosity = fromFlag (configVerbosity flags)
613-
noExtraFlags args
614612
confExists <- doesFileExist "configure"
615613
if confExists
616614
then runConfigureScript verbosity

Cabal/Distribution/Simple/BuildTarget.hs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
module Distribution.Simple.BuildTarget (
1313
-- * Main interface
1414
readTargetInfos,
15+
readBuildTargets, -- in case you don't have LocalBuildInfo
1516

1617
-- * Build targets
1718
BuildTarget(..),
@@ -998,3 +999,7 @@ checkBuildTargets verbosity pkg_descr lbi targets = do
998999
formatReason cn DisabledAllBenchmarks =
9991000
"Cannot process the " ++ cn ++ " because benchmarks are not "
10001001
++ "enabled. Re-run configure with the flag --enable-benchmarks"
1002+
formatReason cn (DisabledAllButOne cn') =
1003+
"Cannot process the " ++ cn ++ " because this package was "
1004+
++ "configured only to build " ++ cn' ++ ". Re-run configure "
1005+
++ "with the argument " ++ cn

Cabal/Distribution/Simple/Configure.hs

Lines changed: 169 additions & 96 deletions
Large diffs are not rendered by default.

Cabal/Distribution/Simple/GHC.hs

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,20 +1138,17 @@ installLib :: Verbosity
11381138
-> Library
11391139
-> ComponentLocalBuildInfo
11401140
-> IO ()
1141-
installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do
1141+
installLib verbosity lbi targetDir dynlibTargetDir _builtDir _pkg lib clbi = do
11421142
-- copy .hi files over:
1143-
whenRegistered $ do
1144-
whenVanilla $ copyModuleFiles "hi"
1145-
whenProf $ copyModuleFiles "p_hi"
1146-
whenShared $ copyModuleFiles "dyn_hi"
1143+
whenVanilla $ copyModuleFiles "hi"
1144+
whenProf $ copyModuleFiles "p_hi"
1145+
whenShared $ copyModuleFiles "dyn_hi"
11471146

11481147
-- copy the built library files over:
1149-
whenRegistered $ do
1150-
whenVanilla $ installOrdinary builtDir targetDir vanillaLibName
1151-
whenProf $ installOrdinary builtDir targetDir profileLibName
1152-
whenGHCi $ installOrdinary builtDir targetDir ghciLibName
1153-
whenRegisteredOrDynExecutable $ do
1154-
whenShared $ installShared builtDir dynlibTargetDir sharedLibName
1148+
whenVanilla $ installOrdinary builtDir targetDir vanillaLibName
1149+
whenProf $ installOrdinary builtDir targetDir profileLibName
1150+
whenGHCi $ installOrdinary builtDir targetDir ghciLibName
1151+
whenShared $ installShared builtDir dynlibTargetDir sharedLibName
11551152

11561153
where
11571154
builtDir = componentBuildDir lbi clbi
@@ -1189,17 +1186,6 @@ installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do
11891186
whenGHCi = when (hasLib && withGHCiLib lbi)
11901187
whenShared = when (hasLib && withSharedLib lbi)
11911188

1192-
-- Some files (e.g. interface files) are completely unnecessary when
1193-
-- we are not actually going to register the library. A library is
1194-
-- not registered if there is no "public library", e.g. in the case
1195-
-- that we have an internal library and executables, but no public
1196-
-- library.
1197-
whenRegistered = when (hasPublicLib pkg)
1198-
1199-
-- However, we must always install dynamic libraries when linking
1200-
-- dynamic executables, because we'll try to load them!
1201-
whenRegisteredOrDynExecutable = when (hasPublicLib pkg || (hasExes pkg && withDynExe lbi))
1202-
12031189
-- -----------------------------------------------------------------------------
12041190
-- Registering
12051191

Cabal/Distribution/Simple/InstallDirs.hs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module Distribution.Simple.InstallDirs (
2525
InstallDirs(..),
2626
InstallDirTemplates,
2727
defaultInstallDirs,
28+
defaultInstallDirs',
2829
combineInstallDirs,
2930
absoluteInstallDirs,
3031
CopyDest(..),
@@ -156,7 +157,17 @@ type InstallDirTemplates = InstallDirs PathTemplate
156157
-- Default installation directories
157158

158159
defaultInstallDirs :: CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates
159-
defaultInstallDirs comp userInstall _hasLibs = do
160+
defaultInstallDirs = defaultInstallDirs' False
161+
162+
defaultInstallDirs' :: Bool {- use external internal deps -}
163+
-> CompilerFlavor -> Bool -> Bool -> IO InstallDirTemplates
164+
defaultInstallDirs' True comp userInstall hasLibs = do
165+
dflt <- defaultInstallDirs' False comp userInstall hasLibs
166+
-- Be a bit more hermetic about per-component installs
167+
return dflt { datasubdir = toPathTemplate $ "$abi" </> "$libname",
168+
docdir = toPathTemplate $ "$datadir" </> "doc" </> "$abi" </> "$libname"
169+
}
170+
defaultInstallDirs' False comp userInstall _hasLibs = do
160171
installPrefix <-
161172
if userInstall
162173
then getAppUserDataDirectory "cabal"

Cabal/Distribution/Simple/Register.hs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,13 @@ import qualified Data.ByteString.Lazy.Char8 as BS.Char8
8888
register :: PackageDescription -> LocalBuildInfo
8989
-> RegisterFlags -- ^Install in the user's database?; verbose
9090
-> IO ()
91-
register pkg_descr lbi flags = when (hasPublicLib pkg_descr) doRegister
91+
register pkg_descr lbi flags =
92+
-- Duncan originally asked for us to not register/install files
93+
-- when there was no public library. But with per-component
94+
-- configure, we legitimately need to install internal libraries
95+
-- so that we can get them. So just unconditionally install.
96+
doRegister
9297
where
93-
-- We do NOT register libraries outside of the inplace database
94-
-- if there is no public library, since no one else can use it
95-
-- usefully (they're not public.) If we start supporting scoped
96-
-- packages, we'll have to relax this.
9798
doRegister = do
9899
targets <- readTargetInfos verbosity pkg_descr lbi (regArgs flags)
99100

Cabal/Distribution/Simple/Setup.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ data ConfigFlags = ConfigFlags {
391391
-- frameworks (OS X only)
392392
configExtraIncludeDirs :: [FilePath], -- ^ path to search for header files
393393
configIPID :: Flag String, -- ^ explicit IPID to be used
394+
configCID :: Flag ComponentId, -- ^ explicit CID to be used
394395

395396
configDistPref :: Flag FilePath, -- ^"dist" prefix
396397
configCabalFilePath :: Flag FilePath, -- ^ Cabal file to use
@@ -677,6 +678,11 @@ configureOptions showOrParseArgs =
677678
configIPID (\v flags -> flags {configIPID = v})
678679
(reqArgFlag "IPID")
679680

681+
,option "" ["cid"]
682+
"Installed component ID to compile this component as"
683+
(fmap display . configCID) (\v flags -> flags {configCID = fmap ComponentId v})
684+
(reqArgFlag "CID")
685+
680686
,option "" ["extra-lib-dirs"]
681687
"A list of directories to search for external libraries"
682688
configExtraLibDirs (\v flags -> flags {configExtraLibDirs = v})

Cabal/Distribution/Simple/UserHooks.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ emptyUserHooks
164164
readDesc = return Nothing,
165165
hookedPreProcessors = [],
166166
hookedPrograms = [],
167-
preConf = rn,
167+
preConf = rn',
168168
confHook = (\_ _ -> return (error "No local build info generated during configure. Over-ride empty configure hook.")),
169169
postConf = ru,
170170
preBuild = rn',

Cabal/Distribution/Types/ComponentEnabledSpec.hs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ module Distribution.Types.ComponentEnabledSpec (
1515

1616
import Prelude ()
1717
import Distribution.Compat.Prelude
18+
import Distribution.Text
1819

1920
import Distribution.Types.Component -- TODO: maybe remove me?
2021
import Distribution.Types.ComponentName
@@ -50,10 +51,9 @@ import Distribution.Types.ComponentName
5051
--
5152
-- @since 2.0.0.0
5253
data ComponentEnabledSpec
53-
= ComponentEnabledSpec {
54-
testsEnabled :: Bool,
55-
benchmarksEnabled :: Bool
56-
}
54+
= ComponentEnabledSpec { testsEnabled :: Bool,
55+
benchmarksEnabled :: Bool }
56+
| OneComponentEnabledSpec ComponentName
5757
deriving (Generic, Read, Show)
5858
instance Binary ComponentEnabledSpec
5959

@@ -91,15 +91,21 @@ componentDisabledReason enabled comp
9191
-- @since 2.0.0.0
9292
componentNameDisabledReason :: ComponentEnabledSpec -> ComponentName
9393
-> Maybe ComponentDisabledReason
94-
componentNameDisabledReason enabled (CTestName _)
95-
| not (testsEnabled enabled) = Just DisabledAllTests
96-
componentNameDisabledReason enabled (CBenchName _)
97-
| not (benchmarksEnabled enabled) = Just DisabledAllBenchmarks
98-
componentNameDisabledReason _ _ = Nothing
94+
componentNameDisabledReason
95+
ComponentEnabledSpec{ testsEnabled = False } (CTestName _)
96+
= Just DisabledAllTests
97+
componentNameDisabledReason
98+
ComponentEnabledSpec{ benchmarksEnabled = False } (CBenchName _)
99+
= Just DisabledAllBenchmarks
100+
componentNameDisabledReason ComponentEnabledSpec{} _ = Nothing
101+
componentNameDisabledReason (OneComponentEnabledSpec cname) c
102+
| c == cname = Nothing
103+
| otherwise = Just (DisabledAllButOne (display cname))
99104

100105
-- | A reason explaining why a component is disabled.
101106
--
102107
-- @since 2.0.0.0
103108
data ComponentDisabledReason = DisabledComponent
104109
| DisabledAllTests
105110
| DisabledAllBenchmarks
111+
| DisabledAllButOne String

Cabal/changelog

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
internal use.
6767
* Macros in 'cabal_macros.h' are now ifndef'd, so that they
6868
don't cause an error if the macro is already defined. (#3041)
69+
* './Setup configure' now accepts a single argument specifying
70+
the component to be configured. The semantics of this mode
71+
of operation are described in
72+
<https://github.com/ghc-proposals/ghc-proposals/pull/4>
6973

7074
1.24.0.0 Ryan Thomas <[email protected]> March 2016
7175
* Support GHC 8.

Cabal/doc/installing-packages.markdown

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,35 @@ is passed the `--with-hc-pkg`, `--prefix`, `--bindir`, `--libdir`,
410410
value of the `--with-compiler` option is passed in a `--with-hc` option
411411
and all options specified with `--configure-option=` are passed on.
412412

413+
In Cabal 2.0, support for a single positional argument was added to `setup configure`
414+
This makes Cabal configure a the specific component to be
415+
configured. Specified names can be qualified with `lib:` or
416+
`exe:` in case just a name is ambiguous (as would be the case
417+
for a package named `p` which has a library and an executable
418+
named `p`.) This has the following effects:
419+
420+
* Subsequent invocations of `build`, `register`, etc. operate only
421+
on the configured component.
422+
423+
* Cabal requires all "internal" dependencies (e.g., an executable
424+
depending on a library defined in the same package) must be
425+
found in the set of databases via `--package-db` (and related flags):
426+
these dependencies are assumed to be up-to-date. A dependency can
427+
be explicitly specified using `--dependency` simply by giving
428+
the name of the internal library; e.g., the dependency for an
429+
internal library named `foo` is given as `--dependency=pkg-internal=pkg-1.0-internal-abcd`.
430+
431+
* Only the dependencies needed for the requested component are
432+
required. Similarly, when `--exact-configuration` is specified,
433+
it's only necessary to specify `--dependency` for the component.
434+
(As mentioned previously, you *must* specify internal dependencies
435+
as well.)
436+
437+
* Internal `build-tools` dependencies are expected to be in the `PATH`
438+
upon subsequent invocations of `setup`.
439+
440+
Full details can be found in the [Componentized Cabal proposal](https://github.com/ezyang/ghc-proposals/blob/master/proposals/0000-componentized-cabal.rst).
441+
413442
### Programs used for building ###
414443

415444
The following options govern the programs used to process the source
@@ -753,6 +782,19 @@ be controlled with the following command line options.
753782

754783
To reset the stack, use `--package-db=clear`.
755784

785+
`--ipid=`_ipid_
786+
: Specifies the _installed package identifier_ of the package to be
787+
built; this identifier is passed on to GHC and serves as the basis
788+
for linker symbols and the `id` field in a `ghc-pkg` registration.
789+
When a package has multiple components, the actual component
790+
identifiers are derived off of this identifier (e.g., an
791+
internal library `foo` from package `p-0.1-abcd` will get the
792+
identifier `p-0.1-abcd-foo`.
793+
794+
`--cid=`_cid_
795+
: Specifies the _component identifier_ of the component being built;
796+
this is only valid if you are configuring a single component.
797+
756798
`--default-user-config=` _file_
757799
: Allows a "default" `cabal.config` freeze file to be passed in
758800
manually. This file will only be used if one does not exist in the
@@ -954,6 +996,18 @@ be controlled with the following command line options.
954996
for libraries it is also saved in the package registration
955997
information and used when compiling modules that use the library.
956998

999+
`--dependency`[=_pkgname_=_ipid_]
1000+
: Specify that a particular dependency should used for a particular
1001+
package name. In particular, it declares that any reference to
1002+
_pkgname_ in a `build-depends` should be resolved to _ipid_.
1003+
1004+
`--exact-configuration`
1005+
: This changes Cabal to require every dependency be explicitly
1006+
specified using `--dependency`, rather than use Cabal's
1007+
(very simple) dependency solver. This is useful for programmatic
1008+
use of Cabal's API, where you want to error if you didn't
1009+
specify enough `--dependency` flags.
1010+
9571011
`--allow-newer`[=_pkgs_], `--allow-older`[=_pkgs_]
9581012
: Selectively relax upper or lower bounds in dependencies without
9591013
editing the package description respectively.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Main where
2+
3+
main :: IO ()
4+
main = putStrLn "Hello, Haskell!"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Exe
2+
version: 0.1.0.0
3+
license: BSD3
4+
author: Edward Z. Yang
5+
maintainer: [email protected]
6+
build-type: Simple
7+
cabal-version: >=1.10
8+
9+
executable goodexe
10+
main-is: Good.hs
11+
build-depends: base
12+
default-language: Haskell2010
13+
14+
-- We deliberately don't configure badexe, so that we can build ONLY goodexe
15+
executable badexe
16+
main-is: Bad.hs
17+
build-depends: totally-impossible-dependency-to-fill == 10000.25.6
18+
default-language: Haskell2010
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module Main where
2+
3+
main :: IO ()
4+
main = putStrLn "OK"
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Lib
2+
version: 0.1.0.0
3+
license: BSD3
4+
author: Edward Z. Yang
5+
maintainer: [email protected]
6+
build-type: Simple
7+
cabal-version: >=1.10
8+
9+
library sublib
10+
build-depends: base
11+
exposed-modules: Lib
12+
default-language: Haskell2010
13+
14+
executable exe
15+
main-is: Exe.hs
16+
build-depends: base, sublib
17+
hs-source-dirs: exe
18+
default-language: Haskell2010
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module Lib where
2+
lib = "OK"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import Lib
2+
main = putStrLn lib
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
module Lib where
2+
lib = "OK"

0 commit comments

Comments
 (0)