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.  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 930eae6
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 930eae6

Please sign in to comment.