Skip to content

Commit

Permalink
One-component configure, fixes haskell#2802.
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ezyang committed Aug 12, 2016
1 parent e641ce5 commit 99d0d2d
Show file tree
Hide file tree
Showing 26 changed files with 348 additions and 144 deletions.
11 changes: 11 additions & 0 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,17 @@ extra-source-files:
tests/PackageTests/Configure/include/HsZlibConfig.h.in
tests/PackageTests/Configure/zlib.buildinfo.in
tests/PackageTests/Configure/zlib.cabal
tests/PackageTests/ConfigureComponent/Exe/Bad.hs
tests/PackageTests/ConfigureComponent/Exe/Exe.cabal
tests/PackageTests/ConfigureComponent/Exe/Good.hs
tests/PackageTests/ConfigureComponent/SubLib/Lib.cabal
tests/PackageTests/ConfigureComponent/SubLib/Lib.hs
tests/PackageTests/ConfigureComponent/SubLib/exe/Exe.hs
tests/PackageTests/ConfigureComponent/Test/Lib.hs
tests/PackageTests/ConfigureComponent/Test/Test.cabal
tests/PackageTests/ConfigureComponent/Test/testlib/TestLib.hs
tests/PackageTests/ConfigureComponent/Test/testlib/testlib.cabal
tests/PackageTests/ConfigureComponent/Test/tests/Test.hs
tests/PackageTests/CopyAssumeDepsUpToDate/CopyAssumeDepsUpToDate.cabal
tests/PackageTests/CopyAssumeDepsUpToDate/Main.hs
tests/PackageTests/CopyAssumeDepsUpToDate/P.hs
Expand Down
13 changes: 8 additions & 5 deletions Cabal/Distribution/PackageDescription/Configuration.hs
Original file line number Diff line number Diff line change
Expand Up @@ -421,11 +421,14 @@ overallDependencies enabled (TargetSet targets) = mconcat depss
where
(depss, _) = unzip $ filter (removeDisabledSections . snd) targets
removeDisabledSections :: PDTagged -> Bool
removeDisabledSections (Lib l) = componentEnabled enabled (CLib l)
removeDisabledSections (SubLib _ l) = componentEnabled enabled (CLib l)
removeDisabledSections (Exe _ e) = componentEnabled enabled (CExe e)
removeDisabledSections (Test _ t) = componentEnabled enabled (CTest t)
removeDisabledSections (Bench _ b) = componentEnabled enabled (CBench b)
-- UGH. The embedded componentName in the 'Component's here is
-- BLANK. I don't know whose fault this is but I'll use the tag
-- instead. -- ezyang
removeDisabledSections (Lib _) = componentNameEnabled enabled CLibName
removeDisabledSections (SubLib t _) = componentNameEnabled enabled (CSubLibName t)
removeDisabledSections (Exe t _) = componentNameEnabled enabled (CExeName t)
removeDisabledSections (Test t _) = componentNameEnabled enabled (CTestName t)
removeDisabledSections (Bench t _) = componentNameEnabled enabled (CBenchName t)
removeDisabledSections PDNull = True

-- Apply extra constraints to a dependency map.
Expand Down
2 changes: 0 additions & 2 deletions Cabal/Distribution/Simple.hs
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,6 @@ defaultUserHooks = autoconfUserHooks {
-- https://github.com/haskell/cabal/issues/158
where oldCompatPostConf args flags pkg_descr lbi
= do let verbosity = fromFlag (configVerbosity flags)
noExtraFlags args
confExists <- doesFileExist "configure"
when confExists $
runConfigureScript verbosity
Expand Down Expand Up @@ -610,7 +609,6 @@ autoconfUserHooks
where defaultPostConf :: Args -> ConfigFlags -> PackageDescription -> LocalBuildInfo -> IO ()
defaultPostConf args flags pkg_descr lbi
= do let verbosity = fromFlag (configVerbosity flags)
noExtraFlags args
confExists <- doesFileExist "configure"
if confExists
then runConfigureScript verbosity
Expand Down
5 changes: 5 additions & 0 deletions Cabal/Distribution/Simple/BuildTarget.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
module Distribution.Simple.BuildTarget (
-- * Main interface
readTargetInfos,
readBuildTargets, -- in case you don't have LocalBuildInfo

-- * Build targets
BuildTarget(..),
Expand Down Expand Up @@ -998,3 +999,7 @@ checkBuildTargets verbosity pkg_descr lbi targets = do
formatReason cn DisabledAllBenchmarks =
"Cannot process the " ++ cn ++ " because benchmarks are not "
++ "enabled. Re-run configure with the flag --enable-benchmarks"
formatReason cn (DisabledAllButOne cn') =
"Cannot process the " ++ cn ++ " because this package was "
++ "configured only to build " ++ cn' ++ ". Re-run configure "
++ "with the argument " ++ cn
268 changes: 171 additions & 97 deletions Cabal/Distribution/Simple/Configure.hs

Large diffs are not rendered by default.

30 changes: 8 additions & 22 deletions Cabal/Distribution/Simple/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,20 +1138,17 @@ installLib :: Verbosity
-> Library
-> ComponentLocalBuildInfo
-> IO ()
installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do
installLib verbosity lbi targetDir dynlibTargetDir _builtDir _pkg lib clbi = do
-- copy .hi files over:
whenRegistered $ do
whenVanilla $ copyModuleFiles "hi"
whenProf $ copyModuleFiles "p_hi"
whenShared $ copyModuleFiles "dyn_hi"
whenVanilla $ copyModuleFiles "hi"
whenProf $ copyModuleFiles "p_hi"
whenShared $ copyModuleFiles "dyn_hi"

-- copy the built library files over:
whenRegistered $ do
whenVanilla $ installOrdinary builtDir targetDir vanillaLibName
whenProf $ installOrdinary builtDir targetDir profileLibName
whenGHCi $ installOrdinary builtDir targetDir ghciLibName
whenRegisteredOrDynExecutable $ do
whenShared $ installShared builtDir dynlibTargetDir sharedLibName
whenVanilla $ installOrdinary builtDir targetDir vanillaLibName
whenProf $ installOrdinary builtDir targetDir profileLibName
whenGHCi $ installOrdinary builtDir targetDir ghciLibName
whenShared $ installShared builtDir dynlibTargetDir sharedLibName

where
builtDir = componentBuildDir lbi clbi
Expand Down Expand Up @@ -1189,17 +1186,6 @@ installLib verbosity lbi targetDir dynlibTargetDir _builtDir pkg lib clbi = do
whenGHCi = when (hasLib && withGHCiLib lbi)
whenShared = when (hasLib && withSharedLib lbi)

-- Some files (e.g. interface files) are completely unnecessary when
-- we are not actually going to register the library. A library is
-- not registered if there is no "public library", e.g. in the case
-- that we have an internal library and executables, but no public
-- library.
whenRegistered = when (hasPublicLib pkg)

-- However, we must always install dynamic libraries when linking
-- dynamic executables, because we'll try to load them!
whenRegisteredOrDynExecutable = when (hasPublicLib pkg || (hasExes pkg && withDynExe lbi))

-- -----------------------------------------------------------------------------
-- Registering

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

Expand Down
6 changes: 6 additions & 0 deletions Cabal/Distribution/Simple/Setup.hs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ data ConfigFlags = ConfigFlags {
-- frameworks (OS X only)
configExtraIncludeDirs :: [FilePath], -- ^ path to search for header files
configIPID :: Flag String, -- ^ explicit IPID to be used
configCID :: Flag ComponentId, -- ^ explicit CID to be used

configDistPref :: Flag FilePath, -- ^"dist" prefix
configCabalFilePath :: Flag FilePath, -- ^ Cabal file to use
Expand Down Expand Up @@ -676,6 +677,11 @@ configureOptions showOrParseArgs =
configIPID (\v flags -> flags {configIPID = v})
(reqArgFlag "IPID")

,option "" ["cid"]
"Installed component ID to compile this component as"
(fmap display . configCID) (\v flags -> flags {configCID = fmap ComponentId v})
(reqArgFlag "CID")

,option "" ["extra-lib-dirs"]
"A list of directories to search for external libraries"
configExtraLibDirs (\v flags -> flags {configExtraLibDirs = v})
Expand Down
2 changes: 1 addition & 1 deletion Cabal/Distribution/Simple/UserHooks.hs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ emptyUserHooks
readDesc = return Nothing,
hookedPreProcessors = [],
hookedPrograms = [],
preConf = rn,
preConf = rn',
confHook = (\_ _ -> return (error "No local build info generated during configure. Over-ride empty configure hook.")),
postConf = ru,
preBuild = rn',
Expand Down
24 changes: 15 additions & 9 deletions Cabal/Distribution/Types/ComponentEnabledSpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module Distribution.Types.ComponentEnabledSpec (

import Prelude ()
import Distribution.Compat.Prelude
import Distribution.Text

import Distribution.Types.Component -- TODO: maybe remove me?
import Distribution.Types.ComponentName
Expand Down Expand Up @@ -50,10 +51,9 @@ import Distribution.Types.ComponentName
--
-- @since 2.0.0.0
data ComponentEnabledSpec
= ComponentEnabledSpec {
testsEnabled :: Bool,
benchmarksEnabled :: Bool
}
= ComponentEnabledSpec { testsEnabled :: Bool,
benchmarksEnabled :: Bool }
| OneComponentEnabledSpec ComponentName
deriving (Generic, Read, Show)
instance Binary ComponentEnabledSpec

Expand Down Expand Up @@ -91,15 +91,21 @@ componentDisabledReason enabled comp
-- @since 2.0.0.0
componentNameDisabledReason :: ComponentEnabledSpec -> ComponentName
-> Maybe ComponentDisabledReason
componentNameDisabledReason enabled (CTestName _)
| not (testsEnabled enabled) = Just DisabledAllTests
componentNameDisabledReason enabled (CBenchName _)
| not (benchmarksEnabled enabled) = Just DisabledAllBenchmarks
componentNameDisabledReason _ _ = Nothing
componentNameDisabledReason
ComponentEnabledSpec{ testsEnabled = False } (CTestName _)
= Just DisabledAllTests
componentNameDisabledReason
ComponentEnabledSpec{ benchmarksEnabled = False } (CBenchName _)
= Just DisabledAllBenchmarks
componentNameDisabledReason ComponentEnabledSpec{} _ = Nothing
componentNameDisabledReason (OneComponentEnabledSpec cname) c
| c == cname = Nothing
| otherwise = Just (DisabledAllButOne (display cname))

-- | A reason explaining why a component is disabled.
--
-- @since 2.0.0.0
data ComponentDisabledReason = DisabledComponent
| DisabledAllTests
| DisabledAllBenchmarks
| DisabledAllButOne String
4 changes: 4 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/Exe/Bad.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Main where

main :: IO ()
main = putStrLn "Hello, Haskell!"
17 changes: 17 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/Exe/Exe.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Exe
version: 0.1.0.0
license: BSD3
author: Edward Z. Yang
maintainer: [email protected]
build-type: Simple
cabal-version: >=1.10

executable goodexe
main-is: Good.hs
build-depends: base
default-language: Haskell2010

executable badexe
main-is: Bad.hs
build-depends: totally-impossible-dependency-to-fill == 10000.25.6
default-language: Haskell2010
4 changes: 4 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/Exe/Good.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Main where

main :: IO ()
main = putStrLn "OK"
18 changes: 18 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/SubLib/Lib.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Lib
version: 0.1.0.0
license: BSD3
author: Edward Z. Yang
maintainer: [email protected]
build-type: Simple
cabal-version: >=1.10

library sublib
build-depends: base
exposed-modules: Lib
default-language: Haskell2010

executable exe
main-is: Exe.hs
build-depends: base, sublib
hs-source-dirs: exe
default-language: Haskell2010
2 changes: 2 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/SubLib/Lib.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module Lib where
lib = "OK"
2 changes: 2 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/SubLib/exe/Exe.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import Lib
main = putStrLn lib
2 changes: 2 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/Test/Lib.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
module Lib where
lib = "OK"
18 changes: 18 additions & 0 deletions Cabal/tests/PackageTests/ConfigureComponent/Test/Test.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: test-for-cabal
version: 0.1.0.0
license: BSD3
author: Edward Z. Yang
maintainer: [email protected]
build-type: Simple
cabal-version: >=1.10

library
exposed-modules: Lib
build-depends: base
default-language: Haskell2010

test-suite testsuite
build-depends: test-for-cabal, testlib, base
type: exitcode-stdio-1.0
main-is: Test.hs
hs-source-dirs: tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module TestLib where
import Lib
testlib = lib
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: testlib
version: 0.1.0.0
license: BSD3
author: Edward Z. Yang
maintainer: [email protected]
build-type: Simple
cabal-version: >=1.10

library
exposed-modules: TestLib
build-depends: test-for-cabal, base
default-language: Haskell2010
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import TestLib
main = putStrLn testlib
31 changes: 28 additions & 3 deletions Cabal/tests/PackageTests/Tests.hs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,31 @@ tests config = do
_ <- shell "autoreconf" ["-i"]
cabal_build []

tc "ConfigureComponent/Exe" $ do
withPackageDb $ do
cabal_install ["goodexe"]
runExe' "goodexe" [] >>= assertOutputContains "OK"

tcs "ConfigureComponent/SubLib" "sublib-explicit" $ do
withPackageDb $ do
cabal_install ["sublib", "--cid", "sublib-0.1-abc"]
cabal_install ["exe", "--dependency", "sublib=sublib-0.1-abc"]
runExe' "exe" [] >>= assertOutputContains "OK"

tcs "ConfigureComponent/SubLib" "sublib" $ do
withPackageDb $ do
cabal_install ["sublib"]
cabal_install ["exe"]
runExe' "exe" [] >>= assertOutputContains "OK"

tcs "ConfigureComponent/Test" "test" $ do
withPackageDb $ do
cabal_install ["test-for-cabal"]
withPackage "testlib" $ cabal_install []
cabal "configure" ["testsuite"]
cabal "build" []
cabal "test" []

-- Test that per-component copy works, when only building library
tc "CopyComponent/Lib" $
withPackageDb $ do
Expand Down Expand Up @@ -580,17 +605,17 @@ tests config = do
uid = componentUnitId (targetCLBI target)
dir = libdir (absoluteComponentInstallDirs pkg_descr lbi uid
NoCopyDest)
assertBool "interface files should NOT be installed" . not
assertBool "interface files should be installed"
=<< liftIO (doesFileExist (dir </> "Foo.hi"))
assertBool "static library should NOT be installed" . not
assertBool "static library should be installed"
=<< liftIO (doesFileExist (dir </> mkLibName uid))
if is_dynamic
then
assertBool "dynamic library MUST be installed"
=<< liftIO (doesFileExist (dir </> mkSharedLibName
compiler_id uid))
else
assertBool "dynamic library should NOT be installed" . not
assertBool "dynamic library should be installed"
=<< liftIO (doesFileExist (dir </> mkSharedLibName
compiler_id uid))
shouldFail $ ghcPkg "describe" ["foo"]
Expand Down
1 change: 1 addition & 0 deletions cabal-install/Distribution/Client/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ instance Semigroup SavedConfig where
-- TODO: NubListify
configExtraIncludeDirs = lastNonEmpty configExtraIncludeDirs,
configIPID = combine configIPID,
configCID = combine configCID,
configDistPref = combine configDistPref,
configCabalFilePath = combine configCabalFilePath,
configVerbosity = combine configVerbosity,
Expand Down
1 change: 1 addition & 0 deletions cabal-install/Distribution/Client/InstallPlan.hs
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ configureInstallPlan solverPlan =
ConfiguredPackage {
confPkgId = SimpleUnitId
$ Configure.computeComponentId
Cabal.NoFlag
Cabal.NoFlag
(packageId spkg)
PD.CLibName
Expand Down
2 changes: 2 additions & 0 deletions cabal-install/Distribution/Client/ProjectConfig/Legacy.hs
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ convertToLegacyAllPackageConfig
configDependencies = mempty,
configExtraIncludeDirs = mempty,
configIPID = mempty,
configCID = mempty,
configConfigurationsFlags = mempty,
configTests = mempty,
configCoverage = mempty, --TODO: don't merge
Expand Down Expand Up @@ -633,6 +634,7 @@ convertToLegacyPerPackageConfig PackageConfig {..} =
configDependencies = mempty,
configExtraIncludeDirs = packageConfigExtraIncludeDirs,
configIPID = mempty,
configCID = mempty,
configConfigurationsFlags = packageConfigFlagAssignment,
configTests = packageConfigTests,
configCoverage = packageConfigCoverage, --TODO: don't merge
Expand Down
Loading

0 comments on commit 99d0d2d

Please sign in to comment.