From c421cb78e5cbce9afb94661e77674ced73918d17 Mon Sep 17 00:00:00 2001 From: "Edward Z. Yang" Date: Wed, 20 Jul 2016 21:51:04 -0700 Subject: [PATCH] BC fix: libraries -> library/subLibraries (#3574) The resulting code is more verbose, but it is more backwards-compatible and actually is simpler to understand in some cases (because CLibName uniquely identifies the "public library"; no faffing about with package names to figure it out.) Signed-off-by: Edward Z. Yang --- Cabal/Distribution/PackageDescription.hs | 70 ++++++++------- .../Distribution/PackageDescription/Check.hs | 48 ++++++---- .../PackageDescription/Configuration.hs | 88 ++++++++++++------- .../Distribution/PackageDescription/Parse.hs | 77 +++++++++------- .../PackageDescription/PrettyPrint.hs | 27 +++--- Cabal/Distribution/Simple/Build.hs | 10 ++- Cabal/Distribution/Simple/BuildTarget.hs | 36 ++++---- Cabal/Distribution/Simple/Configure.hs | 36 +++++--- Cabal/Distribution/Simple/Install.hs | 6 +- Cabal/Distribution/Simple/JHC.hs | 7 +- Cabal/Distribution/Simple/LocalBuildInfo.hs | 36 ++++---- Cabal/Distribution/Simple/PreProcess.hs | 4 +- Cabal/Distribution/Simple/SrcDist.hs | 8 +- Cabal/tests/PackageTests/Macros/macros.cabal | 2 +- Cabal/tests/PackageTests/Tests.hs | 4 +- .../Distribution/Client/BuildTarget.hs | 40 +++++---- .../Distribution/Client/Dependency/TopDown.hs | 6 +- .../Distribution/Client/InstallPlan.hs | 2 +- cabal-install/Distribution/Client/List.hs | 7 +- .../Distribution/Client/PackageUtils.hs | 2 +- .../Distribution/Client/ProjectPlanOutput.hs | 3 +- .../Distribution/Client/ProjectPlanning.hs | 9 +- .../Solver/Modular/IndexConversion.hs | 16 ++-- .../Solver/Types/ComponentDeps.hs | 15 ++-- .../Solver/Types/PackageFixedDeps.hs | 6 +- .../Distribution/Solver/Modular/DSL.hs | 10 ++- .../Distribution/Solver/Modular/QuickCheck.hs | 7 +- 27 files changed, 338 insertions(+), 244 deletions(-) diff --git a/Cabal/Distribution/PackageDescription.hs b/Cabal/Distribution/PackageDescription.hs index fd745299728..2bba2d8309f 100644 --- a/Cabal/Distribution/PackageDescription.hs +++ b/Cabal/Distribution/PackageDescription.hs @@ -32,6 +32,7 @@ module Distribution.PackageDescription ( descCabalVersion, BuildType(..), knownBuildTypes, + allLibraries, -- ** Renaming ModuleRenaming(..), @@ -125,7 +126,7 @@ import Distribution.Text import Language.Haskell.Extension import Data.Data (Data) -import Data.List (nub, intercalate) +import Data.List (nub, intercalate, find) import Data.Maybe (fromMaybe, maybeToList) import Data.Foldable as Fold (Foldable(foldMap)) import Data.Traversable as Trav (Traversable(traverse)) @@ -189,7 +190,8 @@ data PackageDescription buildType :: Maybe BuildType, setupBuildInfo :: Maybe SetupBuildInfo, -- components - libraries :: [Library], + library :: Maybe Library, + subLibraries :: [Library], executables :: [Executable], testSuites :: [TestSuite], benchmarks :: [Benchmark], @@ -256,7 +258,8 @@ emptyPackageDescription category = "", customFieldsPD = [], setupBuildInfo = Nothing, - libraries = [], + library = Nothing, + subLibraries = [], executables = [], testSuites = [], benchmarks = [], @@ -393,7 +396,7 @@ instance Text ModuleRenaming where -- The Library type data Library = Library { - libName :: String, + libName :: Maybe String, exposedModules :: [ModuleName], reexportedModules :: [ModuleReexport], requiredSignatures:: [ModuleName], -- ^ What sigs need implementations? @@ -417,7 +420,7 @@ instance Monoid Library where instance Semigroup Library where a <> b = Library { - libName = combine' libName, + libName = combine libName, exposedModules = combine exposedModules, reexportedModules = combine reexportedModules, requiredSignatures = combine requiredSignatures, @@ -425,25 +428,23 @@ instance Semigroup Library where libBuildInfo = combine libBuildInfo } where combine field = field a `mappend` field b - combine' field = case (field a, field b) of - ("","") -> "" - ("", x) -> x - (x, "") -> x - (x, y) -> error $ "Ambiguous values for library field: '" - ++ x ++ "' and '" ++ y ++ "'" emptyLibrary :: Library emptyLibrary = mempty --- | Does this package have a PUBLIC library? +-- | Does this package have a buildable PUBLIC library? hasPublicLib :: PackageDescription -> Bool -hasPublicLib p = any f (libraries p) - where f lib = buildable (libBuildInfo lib) && - libName lib == display (packageName (package p)) +hasPublicLib p = + case library p of + Just lib -> buildable (libBuildInfo lib) + Nothing -> False -- | Does this package have any libraries? hasLibs :: PackageDescription -> Bool -hasLibs p = any (buildable . libBuildInfo) (libraries p) +hasLibs p = any (buildable . libBuildInfo) (allLibraries p) + +allLibraries :: PackageDescription -> [Library] +allLibraries p = maybeToList (library p) ++ subLibraries p -- | If the package description has a buildable library section, -- call the given function with the library build info as argument. @@ -453,7 +454,7 @@ hasLibs p = any (buildable . libBuildInfo) (libraries p) -- for more information. withLib :: PackageDescription -> (Library -> IO ()) -> IO () withLib pkg_descr f = - sequence_ [f lib | lib <- libraries pkg_descr, buildable (libBuildInfo lib)] + sequence_ [f lib | lib <- allLibraries pkg_descr, buildable (libBuildInfo lib)] -- | Get all the module names from the library (exposed and internal modules) -- which need to be compiled. (This does not include reexports, which @@ -920,7 +921,7 @@ emptyBuildInfo = mempty -- all buildable executables, test suites and benchmarks. Useful for gathering -- dependencies. allBuildInfo :: PackageDescription -> [BuildInfo] -allBuildInfo pkg_descr = [ bi | lib <- libraries pkg_descr +allBuildInfo pkg_descr = [ bi | lib <- allLibraries pkg_descr , let bi = libBuildInfo lib , buildable bi ] ++ [ bi | exe <- executables pkg_descr @@ -954,7 +955,8 @@ usedExtensions bi = oldExtensions bi ++ defaultExtensions bi -- Libraries live in a separate namespace, so must distinguish -data ComponentName = CLibName String +data ComponentName = CLibName + | CSubLibName String | CExeName String | CTestName String | CBenchName String @@ -964,13 +966,17 @@ instance Binary ComponentName -- Build-target-ish syntax instance Text ComponentName where - disp (CLibName str) = Disp.text ("lib:" ++ str) + disp CLibName = Disp.text "lib" + disp (CSubLibName str) = Disp.text ("lib:" ++ str) disp (CExeName str) = Disp.text ("exe:" ++ str) disp (CTestName str) = Disp.text ("test:" ++ str) disp (CBenchName str) = Disp.text ("bench:" ++ str) - parse = do - ctor <- Parse.choice [ Parse.string "lib:" >> return CLibName + parse = parseComposite <++ parseSingle + where + parseSingle = Parse.string "lib" >> return CLibName + parseComposite = do + ctor <- Parse.choice [ Parse.string "lib:" >> return CSubLibName , Parse.string "exe:" >> return CExeName , Parse.string "bench:" >> return CBenchName , Parse.string "test:" >> return CTestName ] @@ -979,8 +985,8 @@ instance Text ComponentName where -- as package names.) fmap (ctor . unPackageName) parse -defaultLibName :: PackageIdentifier -> ComponentName -defaultLibName pid = CLibName (display (pkgName pid)) +defaultLibName :: ComponentName +defaultLibName = CLibName type HookedBuildInfo = [(ComponentName, BuildInfo)] @@ -1143,11 +1149,16 @@ lowercase = map Char.toLower updatePackageDescription :: HookedBuildInfo -> PackageDescription -> PackageDescription updatePackageDescription hooked_bis p = p{ executables = updateMany (CExeName . exeName) updateExecutable (executables p) - , libraries = updateMany (CLibName . libName) updateLibrary (libraries p) + , library = fmap (updateLibrary lib_bi) (library p) + , subLibraries = updateMany (maybe CLibName CSubLibName . libName) updateLibrary (subLibraries p) , benchmarks = updateMany (CBenchName . benchmarkName) updateBenchmark (benchmarks p) , testSuites = updateMany (CTestName . testName) updateTestSuite (testSuites p) } where + lib_bi = case find ((== CLibName) . fst) hooked_bis of + Nothing -> mempty + Just (_, bi) -> bi + updateMany :: (a -> ComponentName) -- ^ get 'ComponentName' from @a@ -> (BuildInfo -> a -> a) -- ^ @updateExecutable@, @updateLibrary@, etc -> [a] -- ^list of components to update @@ -1161,11 +1172,7 @@ updatePackageDescription hooked_bis p -> [a] -- ^list with name component updated updateOne _ _ _ [] = [] updateOne name_sel update hooked_bi'@(name,bi) (c:cs) - | name_sel c == name || - -- Special case: an empty name means "please update the BuildInfo for - -- the public library, i.e. the one with the same name as the - -- package." See 'parseHookedBuildInfo'. - name == CLibName "" && name_sel c == defaultLibName (package p) + | name_sel c == name = update bi c : cs | otherwise = c : updateOne name_sel update hooked_bi' cs @@ -1181,7 +1188,8 @@ data GenericPackageDescription = GenericPackageDescription { packageDescription :: PackageDescription, genPackageFlags :: [Flag], - condLibraries :: [(String, CondTree ConfVar [Dependency] Library)], + condLibrary :: Maybe (CondTree ConfVar [Dependency] Library), + condSubLibraries :: [(String, CondTree ConfVar [Dependency] Library)], condExecutables :: [(String, CondTree ConfVar [Dependency] Executable)], condTestSuites :: [(String, CondTree ConfVar [Dependency] TestSuite)], condBenchmarks :: [(String, CondTree ConfVar [Dependency] Benchmark)] diff --git a/Cabal/Distribution/PackageDescription/Check.hs b/Cabal/Distribution/PackageDescription/Check.hs index c9e024aae21..b06de578c36 100644 --- a/Cabal/Distribution/PackageDescription/Check.hs +++ b/Cabal/Distribution/PackageDescription/Check.hs @@ -47,7 +47,7 @@ import Distribution.Simple.LocalBuildInfo hiding (compiler) import Language.Haskell.Extension import Data.Maybe - ( isNothing, isJust, catMaybes, mapMaybe, fromMaybe ) + ( isNothing, isJust, catMaybes, mapMaybe, fromMaybe, maybeToList ) import Data.List (sort, group, isPrefixOf, nub, find) import Control.Monad ( filterM, liftM ) @@ -174,7 +174,7 @@ checkSanity pkg = , check (all ($ pkg) [ null . executables , null . testSuites , null . benchmarks - , null . libraries ]) $ + , null . allLibraries ]) $ PackageBuildImpossible "No executables, libraries, tests, or benchmarks found. Nothing to do." @@ -182,11 +182,18 @@ checkSanity pkg = PackageBuildImpossible $ "Duplicate sections: " ++ commaSep duplicateNames ++ ". The name of every library, executable, test suite, and benchmark section in" ++ " the package must be unique." + + -- NB: but it's OK for executables to have the same name! + , check (any (== display (packageName pkg)) subLibNames) $ + PackageBuildImpossible $ "Illegal internal library name " ++ display (packageName pkg) + ++ ". Internal libraries cannot have the same name as the package. Maybe" + ++ " you wanted a non-internal library? If so, rewrite the section stanza" + ++ " from 'library: '" ++ display (packageName pkg) ++ "' to 'library'." ] --TODO: check for name clashes case insensitively: windows file systems cannot --cope. - ++ concatMap (checkLibrary pkg) (libraries pkg) + ++ concatMap (checkLibrary pkg) (allLibraries pkg) ++ concatMap (checkExecutable pkg) (executables pkg) ++ concatMap (checkTestSuite pkg) (testSuites pkg) ++ concatMap (checkBenchmark pkg) (benchmarks pkg) @@ -200,15 +207,14 @@ checkSanity pkg = ++ "tool only supports up to version " ++ display cabalVersion ++ "." ] where - -- The public library gets special dispensation, because it + -- The public 'library' gets special dispensation, because it -- is common practice to export a library and name the executable - -- the same as the package. We always put the public library - -- in the top-level directory in dist, so no conflicts either. - libNames = filter (/= unPackageName (packageName pkg)) . map libName $ libraries pkg + -- the same as the package. + subLibNames = catMaybes . map libName $ subLibraries pkg exeNames = map exeName $ executables pkg testNames = map testName $ testSuites pkg bmNames = map benchmarkName $ benchmarks pkg - duplicateNames = dups $ libNames ++ exeNames ++ testNames ++ bmNames + duplicateNames = dups $ subLibNames ++ exeNames ++ testNames ++ bmNames checkLibrary :: PackageDescription -> Library -> [PackageCheck] checkLibrary pkg lib = @@ -221,7 +227,10 @@ checkLibrary pkg lib = , check (null (libModules lib) && null (reexportedModules lib)) $ PackageDistSuspiciousWarn $ - "Library " ++ libName lib ++ " does not expose any modules" + "Library " ++ (case libName lib of + Nothing -> "" + Just n -> n + ) ++ "does not expose any modules" -- check use of required-signatures/exposed-signatures sections , checkVersion [1,21] (not (null (requiredSignatures lib))) $ @@ -691,7 +700,7 @@ checkGhcOptions pkg = where all_ghc_options = concatMap get_ghc_options (allBuildInfo pkg) - lib_ghc_options = concatMap (get_ghc_options . libBuildInfo) (libraries pkg) + lib_ghc_options = concatMap (get_ghc_options . libBuildInfo) (allLibraries pkg) get_ghc_options bi = hcOptions GHC bi ++ hcProfOptions GHC bi ++ hcSharedOptions GHC bi @@ -915,17 +924,14 @@ checkCabalVersion pkg = ++ "'other-languages' field." , checkVersion [1,23] - (case libraries pkg of - [lib] -> libName lib /= unPackageName (packageName pkg) - [] -> False - _ -> True) $ + (not (null (subLibraries pkg))) $ PackageDistInexcusable $ "To use multiple 'library' sections or a named library section " ++ "the package needs to specify at least 'cabal-version >= 1.23'." -- check use of reexported-modules sections , checkVersion [1,21] - (any (not.null.reexportedModules) (libraries pkg)) $ + (any (not.null.reexportedModules) (allLibraries pkg)) $ PackageDistInexcusable $ "To use the 'reexported-module' field the package needs to specify " ++ "at least 'cabal-version: >= 1.21'." @@ -1331,8 +1337,11 @@ checkConditionals pkg = unknownOSs = [ os | OS (OtherOS os) <- conditions ] unknownArches = [ arch | Arch (OtherArch arch) <- conditions ] unknownImpls = [ impl | Impl (OtherCompiler impl) _ <- conditions ] - conditions = concatMap (fvs . snd) (condLibraries pkg) + conditions = concatMap fvs (maybeToList (condLibrary pkg)) + ++ concatMap (fvs . snd) (condSubLibraries pkg) ++ concatMap (fvs . snd) (condExecutables pkg) + ++ concatMap (fvs . snd) (condTestSuites pkg) + ++ concatMap (fvs . snd) (condBenchmarks pkg) fvs (CondNode _ _ ifs) = concatMap compfv ifs -- free variables compfv (c, ct, mct) = condfv c ++ fvs ct ++ maybe [] fvs mct condfv c = case c of @@ -1435,8 +1444,11 @@ checkDevelopmentOnlyFlags pkg = allConditionalBuildInfo :: [([Condition ConfVar], BuildInfo)] allConditionalBuildInfo = - concatMap (collectCondTreePaths libBuildInfo . snd) - (condLibraries pkg) + concatMap (collectCondTreePaths libBuildInfo) + (maybeToList (condLibrary pkg)) + + ++ concatMap (collectCondTreePaths libBuildInfo . snd) + (condSubLibraries pkg) ++ concatMap (collectCondTreePaths buildInfo . snd) (condExecutables pkg) diff --git a/Cabal/Distribution/PackageDescription/Configuration.hs b/Cabal/Distribution/PackageDescription/Configuration.hs index cd5e9b740f5..fc208bbb059 100644 --- a/Cabal/Distribution/PackageDescription/Configuration.hs +++ b/Cabal/Distribution/PackageDescription/Configuration.hs @@ -282,7 +282,8 @@ resolveWithFlags dom enabled os arch impl constrs trees checkDeps = env flags flag = (maybe (Left flag) Right . lookup flag) flags pdTaggedBuildInfo :: PDTagged -> BuildInfo - pdTaggedBuildInfo (Lib _ l) = libBuildInfo l + pdTaggedBuildInfo (Lib l) = libBuildInfo l + pdTaggedBuildInfo (SubLib _ l) = libBuildInfo l pdTaggedBuildInfo (Exe _ e) = buildInfo e pdTaggedBuildInfo (Test _ t) = testBuildInfo t pdTaggedBuildInfo (Bench _ b) = benchmarkBuildInfo b @@ -339,7 +340,8 @@ extractConditions :: (BuildInfo -> Bool) -> GenericPackageDescription -> [Condition ConfVar] extractConditions f gpkg = concat [ - extractCondition (f . libBuildInfo) . snd <$> condLibraries gpkg + extractCondition (f . libBuildInfo) <$> maybeToList (condLibrary gpkg) + , extractCondition (f . libBuildInfo) . snd <$> condSubLibraries gpkg , extractCondition (f . buildInfo) . snd <$> condExecutables gpkg , extractCondition (f . testBuildInfo) . snd <$> condTestSuites gpkg , extractCondition (f . benchmarkBuildInfo) . snd <$> condBenchmarks gpkg @@ -424,7 +426,8 @@ overallDependencies enabled (TargetSet targets) = mconcat depss where (depss, _) = unzip $ filter (removeDisabledSections . snd) targets removeDisabledSections :: PDTagged -> Bool - removeDisabledSections (Lib _ l) = componentEnabled enabled (CLib l) + 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) @@ -449,53 +452,61 @@ constrainBy left extra = -- | Collect up the targets in a TargetSet of tagged targets, storing the -- dependencies as we go. flattenTaggedTargets :: TargetSet PDTagged -> - ([(String, Library)], [(String, Executable)], [(String, TestSuite)] + (Maybe Library + , [(String, Library)], [(String, Executable)], [(String, TestSuite)] , [(String, Benchmark)]) -flattenTaggedTargets (TargetSet targets) = foldr untag ([], [], [], []) targets +flattenTaggedTargets (TargetSet targets) = foldr untag (Nothing, [], [], [], []) targets where - untag (deps, Lib n l) (libs, exes, tests, bms) + untag (_, Lib _) (Just _, _, _, _, _) = userBug "Only one library expected" + untag (deps, Lib l) (Nothing, libs, exes, tests, bms) = + (Just l', libs, exes, tests, bms) + where + l' = l { + libBuildInfo = (libBuildInfo l) { targetBuildDepends = fromDepMap deps } + } + untag (deps, SubLib n l) (mb_lib, libs, exes, tests, bms) | any ((== n) . fst) libs = userBug $ "There exist several libs with the same name: '" ++ n ++ "'" -- NB: libraries live in a different namespace than everything else -- TODO: no, (new-style) TESTS live in same namespace!! - | otherwise = ((n, l'):libs, exes, tests, bms) + | otherwise = (mb_lib, (n, l'):libs, exes, tests, bms) where l' = l { libBuildInfo = (libBuildInfo l) { targetBuildDepends = fromDepMap deps } } - untag (deps, Exe n e) (libs, exes, tests, bms) + untag (deps, Exe n e) (mb_lib, libs, exes, tests, bms) | any ((== n) . fst) exes = userBug $ "There exist several exes with the same name: '" ++ n ++ "'" | any ((== n) . fst) tests = userBug $ "There exists a test with the same name as an exe: '" ++ n ++ "'" | any ((== n) . fst) bms = userBug $ "There exists a benchmark with the same name as an exe: '" ++ n ++ "'" - | otherwise = (libs, (n, e'):exes, tests, bms) + | otherwise = (mb_lib, libs, (n, e'):exes, tests, bms) where e' = e { buildInfo = (buildInfo e) { targetBuildDepends = fromDepMap deps } } - untag (deps, Test n t) (libs, exes, tests, bms) + untag (deps, Test n t) (mb_lib, libs, exes, tests, bms) | any ((== n) . fst) tests = userBug $ "There exist several tests with the same name: '" ++ n ++ "'" | any ((== n) . fst) exes = userBug $ "There exists an exe with the same name as the test: '" ++ n ++ "'" | any ((== n) . fst) bms = userBug $ "There exists a benchmark with the same name as the test: '" ++ n ++ "'" - | otherwise = (libs, exes, (n, t'):tests, bms) + | otherwise = (mb_lib, libs, exes, (n, t'):tests, bms) where t' = t { testBuildInfo = (testBuildInfo t) { targetBuildDepends = fromDepMap deps } } - untag (deps, Bench n b) (libs, exes, tests, bms) + untag (deps, Bench n b) (mb_lib, libs, exes, tests, bms) | any ((== n) . fst) bms = userBug $ "There exist several benchmarks with the same name: '" ++ n ++ "'" | any ((== n) . fst) exes = userBug $ "There exists an exe with the same name as the benchmark: '" ++ n ++ "'" | any ((== n) . fst) tests = userBug $ "There exists a test with the same name as the benchmark: '" ++ n ++ "'" - | otherwise = (libs, exes, tests, (n, b'):bms) + | otherwise = (mb_lib, libs, exes, tests, (n, b'):bms) where b' = b { benchmarkBuildInfo = (benchmarkBuildInfo b) @@ -509,10 +520,10 @@ flattenTaggedTargets (TargetSet targets) = foldr untag ([], [], [], []) targets -- -- ezyang: Arguably, this should be: --- data PDTagged = PDComp String Component +-- data PDTagged = PDComp Component -- | PDNull --- Also, what the heck is the String? The componentName? -data PDTagged = Lib String Library +data PDTagged = Lib Library + | SubLib String Library | Exe String Executable | Test String TestSuite | Bench String Benchmark @@ -526,7 +537,8 @@ instance Monoid PDTagged where instance Semigroup PDTagged where PDNull <> x = x x <> PDNull = x - Lib n l <> Lib n' l' | n == n' = Lib n (l <> l') + Lib l <> Lib l' = Lib (l <> l') + SubLib n l <> SubLib n' l' | n == n' = SubLib n (l <> l') Exe n e <> Exe n' e' | n == n' = Exe n (e <> e') Test n t <> Test n' t' | n == n' = Test n (t <> t') Bench n b <> Bench n' b' | n == n' = Bench n (b <> b') @@ -570,10 +582,11 @@ finalizePD :: -- description along with the flag assignments chosen. finalizePD userflags enabled satisfyDep (Platform arch os) impl constraints - (GenericPackageDescription pkg flags libs0 exes0 tests0 bms0) = + (GenericPackageDescription pkg flags mb_lib0 sub_libs0 exes0 tests0 bms0) = case resolveFlags of - Right ((libs', exes', tests', bms'), targetSet, flagVals) -> - Right ( pkg { libraries = libs' + Right ((mb_lib', sub_libs', exes', tests', bms'), targetSet, flagVals) -> + Right ( pkg { library = mb_lib' + , subLibraries = sub_libs' , executables = exes' , testSuites = tests' , benchmarks = bms' @@ -584,7 +597,8 @@ finalizePD userflags enabled satisfyDep Left missing -> Left missing where -- Combine lib, exes, and tests into one list of @CondTree@s with tagged data - condTrees = map (\(name,tree) -> mapTreeData (Lib name) tree) libs0 + condTrees = maybeToList (fmap (mapTreeData Lib) mb_lib0) + ++ map (\(name,tree) -> mapTreeData (SubLib name) tree) sub_libs0 ++ map (\(name,tree) -> mapTreeData (Exe name) tree) exes0 ++ map (\(name,tree) -> mapTreeData (Test name) tree) tests0 ++ map (\(name,tree) -> mapTreeData (Bench name) tree) bms0 @@ -592,8 +606,9 @@ finalizePD userflags enabled satisfyDep resolveFlags = case resolveWithFlags flagChoices enabled os arch impl constraints condTrees check of Right (targetSet, fs) -> - let (libs, exes, tests, bms) = flattenTaggedTargets targetSet in - Right ( (map (\(n,l) -> (libFillInDefaults l) { libName = n }) libs, + let (mb_lib, sub_libs, exes, tests, bms) = flattenTaggedTargets targetSet in + Right ( (fmap (\l -> (libFillInDefaults l) { libName = Nothing }) mb_lib, + map (\(n,l) -> (libFillInDefaults l) { libName = Just n }) sub_libs, map (\(n,e) -> (exeFillInDefaults e) { exeName = n }) exes, map (\(n,t) -> (testFillInDefaults t) { testName = n }) tests, map (\(n,b) -> (benchFillInDefaults b) { benchmarkName = n }) bms), @@ -650,21 +665,26 @@ resolveWithFlags [] Distribution.System.Linux Distribution.System.I386 (Distribu -- default path will be missing from the package description returned by this -- function. flattenPackageDescription :: GenericPackageDescription -> PackageDescription -flattenPackageDescription (GenericPackageDescription pkg _ libs0 exes0 tests0 bms0) = - pkg { libraries = reverse libs +flattenPackageDescription (GenericPackageDescription pkg _ mlib0 sub_libs0 exes0 tests0 bms0) = + pkg { library = mlib + , subLibraries = reverse sub_libs , executables = reverse exes , testSuites = reverse tests , benchmarks = reverse bms - , buildDepends = reverse ldeps ++ reverse edeps ++ reverse tdeps ++ reverse bdeps + , buildDepends = ldeps ++ reverse sub_ldeps ++ reverse edeps ++ reverse tdeps ++ reverse bdeps } where - (libs, ldeps) = foldr flattenLib ([],[]) libs0 + (mlib, ldeps) = case mlib0 of + Just lib -> let (l,ds) = ignoreConditions lib in + (Just ((libFillInDefaults l) { libName = Nothing }), ds) + Nothing -> (Nothing, []) + (sub_libs, sub_ldeps) = foldr flattenLib ([],[]) sub_libs0 (exes, edeps) = foldr flattenExe ([],[]) exes0 (tests, tdeps) = foldr flattenTst ([],[]) tests0 (bms, bdeps) = foldr flattenBm ([],[]) bms0 flattenLib (n, t) (es, ds) = let (e, ds') = ignoreConditions t in - ( (libFillInDefaults $ e { libName = n }) : es, ds' ++ ds ) + ( (libFillInDefaults $ e { libName = Just n }) : es, ds' ++ ds ) flattenExe (n, t) (es, ds) = let (e, ds') = ignoreConditions t in ( (exeFillInDefaults $ e { exeName = n }) : es, ds' ++ ds ) @@ -720,7 +740,8 @@ transformAllBuildInfos onBuildInfo onSetupBuildInfo gpd = gpd' pd = packageDescription gpd pd' = pd { - libraries = map onLibrary (libraries pd), + library = fmap onLibrary (library pd), + subLibraries = map onLibrary (subLibraries pd), executables = map onExecutable (executables pd), testSuites = map onTestSuite (testSuites pd), benchmarks = map onBenchmark (benchmarks pd), @@ -760,18 +781,21 @@ transformAllCondTrees onLibrary onExecutable onTestSuite onBenchmark onDepends gpd = gpd' where gpd' = gpd { - condLibraries = condLibs', + condLibrary = condLib', + condSubLibraries = condSubLibs', condExecutables = condExes', condTestSuites = condTests', condBenchmarks = condBenchs' } - condLibs = condLibraries gpd + condLib = condLibrary gpd + condSubLibs = condSubLibraries gpd condExes = condExecutables gpd condTests = condTestSuites gpd condBenchs = condBenchmarks gpd - condLibs' = map (mapSnd $ onCondTree onLibrary) condLibs + condLib' = fmap (onCondTree onLibrary) condLib + condSubLibs' = map (mapSnd $ onCondTree onLibrary) condSubLibs condExes' = map (mapSnd $ onCondTree onExecutable) condExes condTests' = map (mapSnd $ onCondTree onTestSuite) condTests condBenchs' = map (mapSnd $ onCondTree onBenchmark) condBenchs diff --git a/Cabal/Distribution/PackageDescription/Parse.hs b/Cabal/Distribution/PackageDescription/Parse.hs index b8dee20bf34..0f8aacc3a8b 100644 --- a/Cabal/Distribution/PackageDescription/Parse.hs +++ b/Cabal/Distribution/PackageDescription/Parse.hs @@ -56,7 +56,7 @@ import Distribution.Text import Distribution.Compat.ReadP hiding (get) import Data.Char (isSpace) -import Data.Maybe (listToMaybe, isJust) +import Data.Maybe (listToMaybe, isJust, maybeToList) import Data.List (nub, unfoldr, partition, (\\)) import Control.Monad (liftM, foldM, when, unless, ap) #if __GLASGOW_HASKELL__ < 710 @@ -738,14 +738,14 @@ parsePackageDescription file = do -- 'getBody' assumes that the remaining fields only consist of -- flags, lib and exe sections. - (repos, flags, mcsetup, libs, exes, tests, bms) <- getBody pkg + (repos, flags, mcsetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg warnIfRest -- warn if getBody did not parse up to the last field. -- warn about using old/new syntax with wrong cabal-version: maybeWarnCabalVersion (not $ oldSyntax fields0) pkg - checkForUndefinedFlags flags libs exes tests + checkForUndefinedFlags flags mlib sub_libs exes tests return $ GenericPackageDescription pkg { sourceRepos = repos, setupBuildInfo = mcsetup } - flags libs exes tests bms + flags mlib sub_libs exes tests bms where oldSyntax = all isSimpleField @@ -852,6 +852,7 @@ parsePackageDescription file = do getBody :: PackageDescription -> PM ([SourceRepo], [Flag] ,Maybe SetupBuildInfo + ,(Maybe (CondTree ConfVar [Dependency] Library)) ,[(String, CondTree ConfVar [Dependency] Library)] ,[(String, CondTree ConfVar [Dependency] Executable)] ,[(String, CondTree ConfVar [Dependency] TestSuite)] @@ -864,8 +865,8 @@ parsePackageDescription file = do exename <- lift $ runP line_no "executable" parseTokenQ sec_label flds <- collectFields parseExeFields sec_fields skipField - (repos, flags, csetup, lib, exes, tests, bms) <- getBody pkg - return (repos, flags, csetup, lib, (exename, flds): exes, tests, bms) + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + return (repos, flags, csetup, mlib, sub_libs, (exename, flds): exes, tests, bms) | sec_type == "test-suite" -> do when (null sec_label) $ lift $ syntaxError line_no @@ -905,8 +906,8 @@ parsePackageDescription file = do if checkTestType emptyTestSuite flds then do skipField - (repos, flags, csetup, lib, exes, tests, bms) <- getBody pkg - return (repos, flags, csetup, lib, exes, + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + return (repos, flags, csetup, mlib, sub_libs, exes, (testname, flds) : tests, bms) else lift $ syntaxError line_no $ "Test suite \"" ++ testname @@ -953,8 +954,8 @@ parsePackageDescription file = do if checkBenchmarkType emptyBenchmark flds then do skipField - (repos, flags, csetup, lib, exes, tests, bms) <- getBody pkg - return (repos, flags, csetup, lib, exes, + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + return (repos, flags, csetup, mlib, sub_libs, exes, tests, (benchname, flds) : bms) else lift $ syntaxError line_no $ "Benchmark \"" ++ benchname @@ -964,15 +965,22 @@ parsePackageDescription file = do ++ intercalate ", " (map display knownBenchmarkTypes) | sec_type == "library" -> do - libname <- if null sec_label - then return (unPackageName (packageName pkg)) - -- TODO: relax this parsing so that scoping is handled - -- correctly - else lift $ runP line_no "library" parseTokenQ sec_label + mb_libname <- if null sec_label + then return Nothing + -- TODO: relax this parsing so that scoping is handled + -- correctly + else fmap Just . lift + $ runP line_no "library" parseTokenQ sec_label flds <- collectFields parseLibFields sec_fields skipField - (repos, flags, csetup, libs, exes, tests, bms) <- getBody pkg - return (repos, flags, csetup, (libname, flds) : libs, exes, tests, bms) + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + case mb_libname of + Just libname -> + return (repos, flags, csetup, mlib, (libname, flds) : sub_libs, exes, tests, bms) + Nothing -> do + when (isJust mlib) $ lift $ syntaxError line_no + "There can only be one (public) library section in a package description." + return (repos, flags, csetup, Just flds, sub_libs, exes, tests, bms) | sec_type == "flag" -> do when (null sec_label) $ lift $ @@ -983,8 +991,8 @@ parsePackageDescription file = do (MkFlag (FlagName (lowercase sec_label)) "" True False) sec_fields skipField - (repos, flags, csetup, lib, exes, tests, bms) <- getBody pkg - return (repos, flag:flags, csetup, lib, exes, tests, bms) + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + return (repos, flag:flags, csetup, mlib, sub_libs, exes, tests, bms) | sec_type == "source-repository" -> do when (null sec_label) $ lift $ syntaxError line_no $ @@ -1008,8 +1016,8 @@ parsePackageDescription file = do } sec_fields skipField - (repos, flags, csetup, lib, exes, tests, bms) <- getBody pkg - return (repo:repos, flags, csetup, lib, exes, tests, bms) + (repos, flags, csetup, mlib, sub_libs, exes, tests, bms) <- getBody pkg + return (repo:repos, flags, csetup, mlib, sub_libs, exes, tests, bms) | sec_type == "custom-setup" -> do unless (null sec_label) $ lift $ @@ -1020,10 +1028,10 @@ parsePackageDescription file = do mempty sec_fields skipField - (repos, flags, csetup0, lib, exes, tests, bms) <- getBody pkg + (repos, flags, csetup0, mlib, sub_libs, exes, tests, bms) <- getBody pkg when (isJust csetup0) $ lift $ syntaxError line_no "There can only be one 'custom-setup' section in a package description." - return (repos, flags, Just flds, lib, exes, tests, bms) + return (repos, flags, Just flds, mlib, sub_libs, exes, tests, bms) | otherwise -> do lift $ warning $ "Ignoring unknown section type: " ++ sec_type @@ -1039,7 +1047,7 @@ parsePackageDescription file = do "If-blocks are not allowed in between stanzas: " ++ show f skipField getBody pkg - Nothing -> return ([], [], Nothing, [], [], [], []) + Nothing -> return ([], [], Nothing, Nothing, [], [], [], []) -- Extracts all fields in a block and returns a 'CondTree'. -- @@ -1116,13 +1124,15 @@ parsePackageDescription file = do checkForUndefinedFlags :: [Flag] -> + Maybe (CondTree ConfVar [Dependency] Library) -> [(String, CondTree ConfVar [Dependency] Library)] -> [(String, CondTree ConfVar [Dependency] Executable)] -> [(String, CondTree ConfVar [Dependency] TestSuite)] -> PM () - checkForUndefinedFlags flags libs exes tests = do + checkForUndefinedFlags flags mlib sub_libs exes tests = do let definedFlags = map flagName flags - mapM_ (checkCondTreeFlags definedFlags . snd) libs + mapM_ (checkCondTreeFlags definedFlags) (maybeToList mlib) + mapM_ (checkCondTreeFlags definedFlags . snd) sub_libs mapM_ (checkCondTreeFlags definedFlags . snd) exes mapM_ (checkCondTreeFlags definedFlags . snd) tests @@ -1213,14 +1223,17 @@ parseHookedBuildInfo inp = do lowercase inFieldName /= "library" && lowercase inFieldName /= "benchmark" && lowercase inFieldName /= "test-suite" - = liftM (\bis -> [(CLibName "", bis)]) (parseBI bi) + = liftM (\bis -> [(CLibName, bis)]) (parseBI bi) parseLib _ = return [] parseStanza :: HookedBuildInfo -> [Field] -> ParseResult HookedBuildInfo parseStanza bis (F line inFieldName mName:bi) | Just k <- case lowercase inFieldName of "executable" -> Just CExeName - "library" -> Just CLibName + -- An *explicit* library indicates a + -- sub-library; only way to get main + -- library is to have a bare section. + "library" -> Just CSubLibName "benchmark" -> Just CBenchName "test-suite" -> Just CTestName _ -> Nothing @@ -1247,7 +1260,10 @@ showPackageDescription :: PackageDescription -> String showPackageDescription pkg = render $ ppPackage pkg $$ ppCustomFields (customFieldsPD pkg) - $$ vcat [ space $$ ppLibrary lib | lib <- libraries pkg ] + $$ (case library pkg of + Nothing -> empty + Just lib -> ppLibrary lib) + $$ vcat [ space $$ ppLibrary lib | lib <- subLibraries pkg ] $$ vcat [ space $$ ppExecutable exe | exe <- executables pkg ] where ppPackage = ppFields pkgDescrFieldDescrs @@ -1271,7 +1287,8 @@ showHookedBuildInfo bis = render $ $$ ppBuildInfo bi | (name, bi) <- bis ] where - ppName (CLibName name) = text "library:" <+> text name + ppName CLibName = text "library" + ppName (CSubLibName name) = text "library:" <+> text name ppName (CExeName name) = text "executable:" <+> text name ppName (CTestName name) = text "test-suite:" <+> text name ppName (CBenchName name) = text "benchmark:" <+> text name diff --git a/Cabal/Distribution/PackageDescription/PrettyPrint.hs b/Cabal/Distribution/PackageDescription/PrettyPrint.hs index 94e8b887136..959faedd3cc 100644 --- a/Cabal/Distribution/PackageDescription/PrettyPrint.hs +++ b/Cabal/Distribution/PackageDescription/PrettyPrint.hs @@ -46,8 +46,8 @@ ppGenericPackageDescription :: GenericPackageDescription -> Doc ppGenericPackageDescription gpd = ppPackageDescription (packageDescription gpd) $+$ ppGenPackageFlags (genPackageFlags gpd) - $+$ ppLibraries (unPackageName (packageName (packageDescription gpd))) - (condLibraries gpd) + $+$ ppLibrary (condLibrary gpd) + $+$ ppSubLibraries (condSubLibraries gpd) $+$ ppExecutables (condExecutables gpd) $+$ ppTestSuites (condTestSuites gpd) $+$ ppBenchmarks (condBenchmarks gpd) @@ -107,15 +107,22 @@ ppFlag flag@(MkFlag name _ _ _) = where fields = ppFieldsFiltered flagDefaults flagFieldDescrs flag -ppLibraries :: String -> [(String, CondTree ConfVar [Dependency] Library)] -> Doc -ppLibraries pn libs = - vcat [emptyLine $ text (if n == pn then "library" else "library " ++ n) +ppLibrary :: Maybe (CondTree ConfVar [Dependency] Library) -> Doc +ppLibrary Nothing = empty +ppLibrary (Just condTree) = + emptyLine $ text "library" + $+$ nest indentWith (ppCondTree condTree Nothing ppLib) + +ppSubLibraries :: [(String, CondTree ConfVar [Dependency] Library)] -> Doc +ppSubLibraries libs = + vcat [emptyLine $ text ("library " ++ n) $+$ nest indentWith (ppCondTree condTree Nothing ppLib)| (n,condTree) <- libs] - where - ppLib lib Nothing = ppFieldsFiltered libDefaults libFieldDescrs lib - $$ ppCustomFields (customFieldsBI (libBuildInfo lib)) - ppLib lib (Just plib) = ppDiffFields libFieldDescrs lib plib - $$ ppCustomFields (customFieldsBI (libBuildInfo lib)) + +ppLib :: Library -> Maybe Library -> Doc +ppLib lib Nothing = ppFieldsFiltered libDefaults libFieldDescrs lib + $$ ppCustomFields (customFieldsBI (libBuildInfo lib)) +ppLib lib (Just plib) = ppDiffFields libFieldDescrs lib plib + $$ ppCustomFields (customFieldsBI (libBuildInfo lib)) ppExecutables :: [(String, CondTree ConfVar [Dependency] Executable)] -> Doc ppExecutables exes = diff --git a/Cabal/Distribution/Simple/Build.hs b/Cabal/Distribution/Simple/Build.hs index 5b9c0f23a8e..c432ee0046a 100644 --- a/Cabal/Distribution/Simple/Build.hs +++ b/Cabal/Distribution/Simple/Build.hs @@ -206,7 +206,9 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes comp@(CLib lib) clbi distPref = do preprocessComponent pkg_descr comp lbi clbi False verbosity suffixes extras <- preprocessExtras comp lbi - info verbosity $ "Building library " ++ libName lib ++ "..." + case libName lib of + Nothing -> info verbosity $ "Building library..." + Just n -> info verbosity $ "Building library " ++ n ++ "..." let libbi = libBuildInfo lib lib' = lib { libBuildInfo = addExtraCSources libbi extras } buildLib verbosity numJobs pkg_descr lbi lib' clbi @@ -407,7 +409,7 @@ testSuiteLibV09AsLibAndExe pkg_descr where bi = testBuildInfo test lib = Library { - libName = testName test, + libName = Nothing, exposedModules = [ m ], reexportedModules = [], requiredSignatures = [], @@ -421,7 +423,7 @@ testSuiteLibV09AsLibAndExe pkg_descr compat_key = computeCompatPackageKey (compiler lbi) compat_name pkg_ver (componentUnitId clbi) libClbi = LibComponentLocalBuildInfo { componentPackageDeps = componentPackageDeps clbi - , componentLocalName = CLibName (testName test) + , componentLocalName = CSubLibName (testName test) , componentIsPublic = False , componentIncludes = componentIncludes clbi , componentUnitId = componentUnitId clbi @@ -434,7 +436,7 @@ testSuiteLibV09AsLibAndExe pkg_descr , buildDepends = targetBuildDepends $ testBuildInfo test , executables = [] , testSuites = [] - , libraries = [lib] + , subLibraries = [lib] } ipi = inplaceInstalledPackageInfo pwd distPref pkg (AbiHash "") lib lbi libClbi testDir = buildDir lbi stubName test diff --git a/Cabal/Distribution/Simple/BuildTarget.hs b/Cabal/Distribution/Simple/BuildTarget.hs index 9cc29242f2e..359427185aa 100644 --- a/Cabal/Distribution/Simple/BuildTarget.hs +++ b/Cabal/Distribution/Simple/BuildTarget.hs @@ -34,6 +34,7 @@ module Distribution.Simple.BuildTarget ( checkBuildTargets ) where +import Distribution.Package import Distribution.PackageDescription import Distribution.ModuleName import Distribution.Simple.LocalBuildInfo @@ -231,9 +232,9 @@ showUserBuildTarget = intercalate ":" . getComponents getComponents (UserBuildTargetDouble s1 s2) = [s1,s2] getComponents (UserBuildTargetTriple s1 s2 s3) = [s1,s2,s3] -showBuildTarget :: QualLevel -> BuildTarget -> String -showBuildTarget ql bt = - showUserBuildTarget (renderBuildTarget ql bt) +showBuildTarget :: QualLevel -> PackageId -> BuildTarget -> String +showBuildTarget ql pkgid bt = + showUserBuildTarget (renderBuildTarget ql bt pkgid) -- ------------------------------------------------------------ @@ -270,6 +271,7 @@ resolveBuildTarget pkg userTarget fexists = Unambiguous target -> Right target Ambiguous targets -> Left (BuildTargetAmbiguous userTarget targets') where targets' = disambiguateBuildTargets + (packageId pkg) userTarget targets None errs -> Left (classifyMatchErrors errs) @@ -294,9 +296,9 @@ data BuildTargetProblem deriving Show -disambiguateBuildTargets :: UserBuildTarget -> [BuildTarget] +disambiguateBuildTargets :: PackageId -> UserBuildTarget -> [BuildTarget] -> [(UserBuildTarget, BuildTarget)] -disambiguateBuildTargets original = +disambiguateBuildTargets pkgid original = disambiguate (userTargetQualLevel original) where disambiguate ql ts @@ -315,13 +317,13 @@ disambiguateBuildTargets original = . partition (\g -> length g > 1) . groupBy (equating fst) . sortBy (comparing fst) - . map (\t -> (renderBuildTarget ql t, t)) + . map (\t -> (renderBuildTarget ql t pkgid, t)) data QualLevel = QL1 | QL2 | QL3 deriving (Enum, Show) -renderBuildTarget :: QualLevel -> BuildTarget -> UserBuildTarget -renderBuildTarget ql target = +renderBuildTarget :: QualLevel -> BuildTarget -> PackageId -> UserBuildTarget +renderBuildTarget ql target pkgid = case ql of QL1 -> UserBuildTargetSingle s1 where s1 = single target QL2 -> UserBuildTargetDouble s1 s2 where (s1, s2) = double target @@ -340,7 +342,7 @@ renderBuildTarget ql target = triple (BuildTargetModule cn m) = (dispKind cn, dispCName cn, display m) triple (BuildTargetFile cn f) = (dispKind cn, dispCName cn, f) - dispCName = componentStringName + dispCName = componentStringName pkgid dispKind = showComponentKindShort . componentKind reportBuildTargetProblems :: [BuildTargetProblem] -> IO () @@ -443,7 +445,7 @@ pkgComponentInfo :: PackageDescription -> [ComponentInfo] pkgComponentInfo pkg = [ ComponentInfo { cinfoName = componentName c, - cinfoStrName = componentStringName (componentName c), + cinfoStrName = componentStringName pkg (componentName c), cinfoSrcDirs = hsSourceDirs bi, cinfoModules = componentModules c, cinfoHsFiles = componentHsFiles c, @@ -453,11 +455,12 @@ pkgComponentInfo pkg = | c <- pkgComponents pkg , let bi = componentBuildInfo c ] -componentStringName :: ComponentName -> ComponentStringName -componentStringName (CLibName name) = name -componentStringName (CExeName name) = name -componentStringName (CTestName name) = name -componentStringName (CBenchName name) = name +componentStringName :: Package pkg => pkg -> ComponentName -> ComponentStringName +componentStringName pkg CLibName = display (packageName pkg) +componentStringName _ (CSubLibName name) = name +componentStringName _ (CExeName name) = name +componentStringName _ (CTestName name) = name +componentStringName _ (CBenchName name) = name componentModules :: Component -> [ModuleName] componentModules (CLib lib) = libModules lib @@ -497,7 +500,8 @@ data ComponentKind = LibKind | ExeKind | TestKind | BenchKind deriving (Eq, Ord, Show) componentKind :: ComponentName -> ComponentKind -componentKind (CLibName _) = LibKind +componentKind CLibName = LibKind +componentKind (CSubLibName _) = LibKind componentKind (CExeName _) = ExeKind componentKind (CTestName _) = TestKind componentKind (CBenchName _) = BenchKind diff --git a/Cabal/Distribution/Simple/Configure.hs b/Cabal/Distribution/Simple/Configure.hs index 377d139ce07..86151ac5fe6 100644 --- a/Cabal/Distribution/Simple/Configure.hs +++ b/Cabal/Distribution/Simple/Configure.hs @@ -820,15 +820,18 @@ getInternalPackages pkg_descr0 = -- for the internal package set. What we do here -- is skeevy, but we're highly unlikely to accidentally -- shadow something legitimate. - Installed.installedUnitId = mkUnitId (libName lib), + Installed.installedUnitId = mkUnitId n, -- NB: we TEMPORARILY set the package name to be the -- library name. When we actually register, it won't -- look like this; this is just so that internal -- build-depends get resolved correctly. - Installed.sourcePackageId = PackageIdentifier (PackageName (libName lib)) + Installed.sourcePackageId = PackageIdentifier (PackageName n) (pkgVersion (package pkg_descr)) } - in PackageIndex.fromList (map mkInternalPackage (libraries pkg_descr)) + where n = case libName lib of + Nothing -> display (packageName pkg_descr) + Just n' -> n' + in PackageIndex.fromList (map mkInternalPackage (allLibraries pkg_descr)) -- | Returns true if a dependency is satisfiable. This is to be passed @@ -945,7 +948,8 @@ configureFinalizedPackage verbosity cfg enabled `mappend` extraBi } modifyExecutable e = e{ buildInfo = buildInfo e `mappend` extraBi} - in pkg_descr{ libraries = modifyLib `map` libraries pkg_descr + in pkg_descr{ library = modifyLib `fmap` library pkg_descr + , subLibraries = modifyLib `map` subLibraries pkg_descr , executables = modifyExecutable `map` executables pkg_descr} @@ -960,7 +964,7 @@ checkCompilerProblems comp pkg_descr = do ++ "package flags. To use this feature you probably must use " ++ "GHC 7.9 or later." - when (any (not.null.PD.reexportedModules) (PD.libraries pkg_descr) + when (any (not.null.PD.reexportedModules) (PD.allLibraries pkg_descr) && not (reexportedModulesSupported comp)) $ do die $ "Your compiler does not support module re-exports. To use " ++ "this feature you probably must use GHC 7.9 or later." @@ -1288,11 +1292,13 @@ configurePkgconfigPackages verbosity pkg_descr conf (lessVerbose verbosity) pkgConfigProgram (orLaterVersion $ Version [0,9,0] []) conf mapM_ requirePkg allpkgs - libs' <- mapM addPkgConfigBILib (libraries pkg_descr) + mlib' <- mapM addPkgConfigBILib (library pkg_descr) + libs' <- mapM addPkgConfigBILib (subLibraries pkg_descr) exes' <- mapM addPkgConfigBIExe (executables pkg_descr) tests' <- mapM addPkgConfigBITest (testSuites pkg_descr) benches' <- mapM addPkgConfigBIBench (benchmarks pkg_descr) - let pkg_descr' = pkg_descr { libraries = libs', executables = exes', + let pkg_descr' = pkg_descr { library = mlib', + subLibraries = libs', executables = exes', testSuites = tests', benchmarks = benches' } return (pkg_descr', conf') @@ -1454,7 +1460,10 @@ mkComponentsGraph enabled pkg_descr internalPkgDeps = , toolname `elem` map exeName (executables pkg_descr) ] - ++ [ CLibName toolname | Dependency pkgname@(PackageName toolname) _ + ++ [ if pkgname == packageName pkg_descr + then CLibName + else CSubLibName toolname + | Dependency pkgname@(PackageName toolname) _ <- targetBuildDepends bi , pkgname `elem` map packageName internalPkgDeps ] where @@ -1500,7 +1509,7 @@ computeComponentId mb_explicit pid cname dep_ipids flagAssignment = do Flag cid0 -> explicit_base cid0 NoFlag -> generated_base ComponentId $ actual_base - ++ (case componentNameString (pkgName pid) cname of + ++ (case componentNameString cname of Nothing -> "" Just s -> "-" ++ s) @@ -1543,7 +1552,7 @@ hashToBase62 s = showFingerprint $ fingerprintString s -- computeCompatPackageName :: PackageName -> ComponentName -> PackageName computeCompatPackageName pkg_name cname - | Just cname_str <- componentNameString pkg_name cname + | Just cname_str <- componentNameString cname = let zdashcode s = go s (Nothing :: Maybe Int) [] where go [] _ r = reverse r go ('-':z) (Just n) r | n > 0 = go z (Just 0) ('-':'z':r) @@ -1685,7 +1694,7 @@ mkComponentsLocalBuildInfo cfg comp installedPackages pkg_descr componentPackageDeps = cpds, componentUnitId = uid, componentLocalName = componentName component, - componentIsPublic = libName lib == display (packageName (package pkg_descr)), + componentIsPublic = libName lib == Nothing, componentCompatPackageKey = compat_key, componentCompatPackageName = compat_name, componentIncludes = includes, @@ -1729,7 +1738,10 @@ mkComponentsLocalBuildInfo cfg comp installedPackages pkg_descr lookupInternalPkg :: PackageId -> UnitId lookupInternalPkg pkgid = do let matcher (clbi, _) - | CLibName str <- componentLocalName clbi + | CLibName <- componentLocalName clbi + , pkgName pkgid == packageName pkg_descr + = Just (componentUnitId clbi) + | CSubLibName str <- componentLocalName clbi , str == display (pkgName pkgid) = Just (componentUnitId clbi) matcher _ = Nothing diff --git a/Cabal/Distribution/Simple/Install.hs b/Cabal/Distribution/Simple/Install.hs index 1773b9d5e8c..04490a9ed34 100644 --- a/Cabal/Distribution/Simple/Install.hs +++ b/Cabal/Distribution/Simple/Install.hs @@ -169,9 +169,9 @@ copyComponent verbosity pkg_descr lbi (CLib lib) clbi copydest = do -- For the moment use dynlibdir = libdir dynlibPref = libPref - if componentUnitId clbi == localUnitId lbi - then notice verbosity ("Installing library in " ++ libPref) - else notice verbosity ("Installing internal library " ++ libName lib ++ " in " ++ libPref) + case libName lib of + Nothing -> notice verbosity ("Installing library in " ++ libPref) + Just n -> notice verbosity ("Installing internal library " ++ n ++ " in " ++ libPref) -- install include files for all compilers - they may be needed to compile -- haskell files (using the CPP extension) diff --git a/Cabal/Distribution/Simple/JHC.hs b/Cabal/Distribution/Simple/JHC.hs index dbdb3234f59..4441ccc3600 100644 --- a/Cabal/Distribution/Simple/JHC.hs +++ b/Cabal/Distribution/Simple/JHC.hs @@ -154,10 +154,9 @@ constructJHCCmdLine lbi bi clbi _odir verbosity = jhcPkgConf :: PackageDescription -> String jhcPkgConf pd = let sline name sel = name ++ ": "++sel pd - lib pd' = case libraries pd' of - [lib'] -> lib' - [] -> error "no library available" - _ -> error "JHC does not support multiple libraries (yet)" + lib pd' = case library pd' of + Just lib' -> lib' + Nothing -> error "no library available" comma = intercalate "," . map display in unlines [sline "name" (display . pkgName . packageId) ,sline "version" (display . pkgVersion . packageId) diff --git a/Cabal/Distribution/Simple/LocalBuildInfo.hs b/Cabal/Distribution/Simple/LocalBuildInfo.hs index 222dd065432..4712ea21f19 100644 --- a/Cabal/Distribution/Simple/LocalBuildInfo.hs +++ b/Cabal/Distribution/Simple/LocalBuildInfo.hs @@ -291,16 +291,17 @@ data Component = CLib Library -- | This gets the 'String' component name. In fact, it is -- guaranteed to uniquely identify a component, returning -- @Nothing@ if the 'ComponentName' was for the public --- library (which CAN conflict with an executable name.) -componentNameString :: PackageName -> ComponentName -> Maybe String -componentNameString (PackageName pkg_name) (CLibName n) | pkg_name == n = Nothing -componentNameString _ (CLibName n) = Just n -componentNameString _ (CExeName n) = Just n -componentNameString _ (CTestName n) = Just n -componentNameString _ (CBenchName n) = Just n +-- library. +componentNameString :: ComponentName -> Maybe String +componentNameString CLibName = Nothing +componentNameString (CSubLibName n) = Just n +componentNameString (CExeName n) = Just n +componentNameString (CTestName n) = Just n +componentNameString (CBenchName n) = Just n showComponentName :: ComponentName -> String -showComponentName (CLibName name) = "library '" ++ name ++ "'" +showComponentName CLibName = "library" +showComponentName (CSubLibName name) = "library '" ++ name ++ "'" showComponentName (CExeName name) = "executable '" ++ name ++ "'" showComponentName (CTestName name) = "test suite '" ++ name ++ "'" showComponentName (CBenchName name) = "benchmark '" ++ name ++ "'" @@ -322,16 +323,20 @@ componentBuildInfo = componentName :: Component -> ComponentName componentName = - foldComponent (CLibName . libName) + foldComponent getLibName (CExeName . exeName) (CTestName . testName) (CBenchName . benchmarkName) + where + getLibName lib = case libName lib of + Nothing -> CLibName + Just n -> CSubLibName n -- | All the components in the package. -- pkgComponents :: PackageDescription -> [Component] pkgComponents pkg = - [ CLib lib | lib <- libraries pkg ] + [ CLib lib | lib <- allLibraries pkg ] ++ [ CExe exe | exe <- executables pkg ] ++ [ CTest tst | tst <- testSuites pkg ] ++ [ CBench bm | bm <- benchmarks pkg ] @@ -356,9 +361,9 @@ componentBuildable :: Component -> Bool componentBuildable = buildable . componentBuildInfo lookupComponent :: PackageDescription -> ComponentName -> Maybe Component -lookupComponent pkg (CLibName "") = lookupComponent pkg (defaultLibName (package pkg)) -lookupComponent pkg (CLibName name) = - fmap CLib $ find ((name ==) . libName) (libraries pkg) +lookupComponent pkg CLibName = fmap CLib (library pkg) +lookupComponent pkg (CSubLibName name) = + fmap CLib $ find ((Just name ==) . libName) (subLibraries pkg) lookupComponent pkg (CExeName name) = fmap CExe $ find ((name ==) . exeName) (executables pkg) lookupComponent pkg (CTestName name) = @@ -443,14 +448,13 @@ componentComponentId clbi = case componentUnitId clbi of SimpleUnitId cid -> cid componentBuildDir :: LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath -componentBuildDir lbi LibComponentLocalBuildInfo{ componentIsPublic = True } - = buildDir lbi -- For now, we assume that libraries/executables/test-suites/benchmarks -- are only ever built once. With Backpack, we need a special case for -- libraries so that we can handle building them multiple times. componentBuildDir lbi clbi = buildDir lbi case componentLocalName clbi of - CLibName s -> s + CLibName -> "" + CSubLibName s -> s CExeName s -> s CTestName s -> s CBenchName s -> s diff --git a/Cabal/Distribution/Simple/PreProcess.hs b/Cabal/Distribution/Simple/PreProcess.hs index df11ade8bb7..3b012258423 100644 --- a/Cabal/Distribution/Simple/PreProcess.hs +++ b/Cabal/Distribution/Simple/PreProcess.hs @@ -46,7 +46,7 @@ import Distribution.Version import Distribution.Verbosity import Control.Monad -import Data.Maybe (fromMaybe) +import Data.Maybe (fromMaybe, mapMaybe) import Data.List (nub, isSuffixOf, isPrefixOf) import System.Directory (doesFileExist) import System.Info (os, arch) @@ -664,7 +664,7 @@ preprocessExtras comp lbi = case comp of component_dirs = component_names (localPkgDescr lbi) -- TODO: libify me component_names pkg_descr = - map libName (libraries pkg_descr) ++ + mapMaybe libName (subLibraries pkg_descr) ++ map exeName (executables pkg_descr) ++ map testName (testSuites pkg_descr) ++ map benchmarkName (benchmarks pkg_descr) diff --git a/Cabal/Distribution/Simple/SrcDist.hs b/Cabal/Distribution/Simple/SrcDist.hs index c0eea1d7ca5..1d1e0f48850 100644 --- a/Cabal/Distribution/Simple/SrcDist.hs +++ b/Cabal/Distribution/Simple/SrcDist.hs @@ -230,7 +230,7 @@ listPackageSourcesOrdinary verbosity pkg_descr pps = where -- We have to deal with all libs and executables, so we have local -- versions of these functions that ignore the 'buildable' attribute: - withAllLib action = mapM action (libraries pkg_descr) + withAllLib action = mapM action (allLibraries pkg_descr) withAllExe action = mapM action (executables pkg_descr) withAllTest action = mapM action (testSuites pkg_descr) withAllBenchmark action = mapM action (benchmarks pkg_descr) @@ -311,7 +311,8 @@ filterAutogenModule :: PackageDescription -> PackageDescription filterAutogenModule pkg_descr0 = mapLib filterAutogenModuleLib $ mapAllBuildInfo filterAutogenModuleBI pkg_descr0 where - mapLib f pkg = pkg { libraries = map f (libraries pkg) } + mapLib f pkg = pkg { library = fmap f (library pkg) + , subLibraries = map f (subLibraries pkg) } filterAutogenModuleLib lib = lib { exposedModules = filter (/=autogenModule) (exposedModules lib) } @@ -467,7 +468,8 @@ tarBallName = display . packageId mapAllBuildInfo :: (BuildInfo -> BuildInfo) -> (PackageDescription -> PackageDescription) mapAllBuildInfo f pkg = pkg { - libraries = fmap mapLibBi (libraries pkg), + library = fmap mapLibBi (library pkg), + subLibraries = fmap mapLibBi (subLibraries pkg), executables = fmap mapExeBi (executables pkg), testSuites = fmap mapTestBi (testSuites pkg), benchmarks = fmap mapBenchBi (benchmarks pkg) diff --git a/Cabal/tests/PackageTests/Macros/macros.cabal b/Cabal/tests/PackageTests/Macros/macros.cabal index c9611bdf396..9043a4a181a 100644 --- a/Cabal/tests/PackageTests/Macros/macros.cabal +++ b/Cabal/tests/PackageTests/Macros/macros.cabal @@ -7,7 +7,7 @@ maintainer: ezyang@cs.stanford.edu build-type: Simple cabal-version: >=1.10 -library macros +library exposed-modules: C hs-source-dirs: src build-depends: base, filepath diff --git a/Cabal/tests/PackageTests/Tests.hs b/Cabal/tests/PackageTests/Tests.hs index 124d65dd6b0..f571f5436f3 100644 --- a/Cabal/tests/PackageTests/Tests.hs +++ b/Cabal/tests/PackageTests/Tests.hs @@ -10,7 +10,7 @@ import qualified PackageTests.TestSuiteTests.ExeV10.Check import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(localPkgDescr, compiler), absoluteComponentInstallDirs , InstallDirs(libdir), maybeGetComponentLocalBuildInfo - , ComponentLocalBuildInfo(componentUnitId), ComponentName(CLibName) ) + , ComponentLocalBuildInfo(componentUnitId), ComponentName(..) ) import Distribution.Simple.InstallDirs ( CopyDest(NoCopyDest) ) import Distribution.Simple.BuildPaths ( mkLibName, mkSharedLibName ) import Distribution.Simple.Compiler ( compilerId ) @@ -540,7 +540,7 @@ tests config = do lbi <- liftIO $ getPersistBuildConfig dist_dir let pkg_descr = localPkgDescr lbi compiler_id = compilerId (compiler lbi) - cname = (CLibName "foo-internal") + cname = CSubLibName "foo-internal" Just clbi = maybeGetComponentLocalBuildInfo lbi cname uid = componentUnitId clbi dir = libdir (absoluteComponentInstallDirs pkg_descr lbi uid diff --git a/cabal-install/Distribution/Client/BuildTarget.hs b/cabal-install/Distribution/Client/BuildTarget.hs index 88303d6c068..537b743f9ff 100644 --- a/cabal-install/Distribution/Client/BuildTarget.hs +++ b/cabal-install/Distribution/Client/BuildTarget.hs @@ -604,29 +604,29 @@ renderBuildTarget ql t = BuildTargetComponent p c -> case ql of - QL1 -> [t1 (dispC c)] - QL2 -> [t2 (dispP p) (dispC c), - t2 (dispK c) (dispC c)] - QL3 -> [t3 (dispP p) (dispK c) (dispC c)] + QL1 -> [t1 (dispC p c)] + QL2 -> [t2 (dispP p) (dispC p c), + t2 (dispK c) (dispC p c)] + QL3 -> [t3 (dispP p) (dispK c) (dispC p c)] QL4 -> [] BuildTargetModule p c m -> case ql of QL1 -> [t1 (dispM m)] QL2 -> [t2 (dispP p) (dispM m), - t2 (dispC c) (dispM m)] - QL3 -> [t3 (dispP p) (dispC c) (dispM m), - t3 (dispK c) (dispC c) (dispM m)] - QL4 -> [t4 (dispP p) (dispK c) (dispC c) (dispM m)] + t2 (dispC p c) (dispM m)] + QL3 -> [t3 (dispP p) (dispC p c) (dispM m), + t3 (dispK c) (dispC p c) (dispM m)] + QL4 -> [t4 (dispP p) (dispK c) (dispC p c) (dispM m)] BuildTargetFile p c f -> case ql of QL1 -> [t1 f] QL2 -> [t2 (dispP p) f, - t2 (dispC c) f] - QL3 -> [t3 (dispP p) (dispC c) f, - t3 (dispK c) (dispC c) f] - QL4 -> [t4 (dispP p) (dispK c) (dispC c) f] + t2 (dispC p c) f] + QL3 -> [t3 (dispP p) (dispC p c) f, + t3 (dispK c) (dispC p c) f] + QL4 -> [t4 (dispP p) (dispK c) (dispC p c) f] where t1 s1 = UserBuildTargetFileStatus1 s1 none t1' s1 = UserBuildTargetFileStatus1 s1 @@ -1062,7 +1062,7 @@ selectComponentInfo :: PackageInfo -> PackageDescription -> [ComponentInfo] selectComponentInfo pinfo pkg = [ ComponentInfo { cinfoName = componentName c, - cinfoStrName = componentStringName (componentName c), + cinfoStrName = componentStringName pkg (componentName c), cinfoPackage = pinfo, cinfoSrcDirs = hsSourceDirs bi, -- [ pkgroot srcdir @@ -1077,11 +1077,12 @@ selectComponentInfo pinfo pkg = , let bi = componentBuildInfo c ] -componentStringName :: ComponentName -> ComponentStringName -componentStringName (CLibName name) = name -componentStringName (CExeName name) = name -componentStringName (CTestName name) = name -componentStringName (CBenchName name) = name +componentStringName :: Package pkg => pkg -> ComponentName -> ComponentStringName +componentStringName pkg CLibName = display (packageName pkg) +componentStringName _ (CSubLibName name) = name +componentStringName _ (CExeName name) = name +componentStringName _ (CTestName name) = name +componentStringName _ (CBenchName name) = name componentModules :: Component -> [ModuleName] componentModules (CLib lib) = libModules lib @@ -1108,7 +1109,8 @@ data ComponentKind = LibKind | ExeKind | TestKind | BenchKind deriving (Eq, Ord, Show) componentKind :: ComponentName -> ComponentKind -componentKind (CLibName _) = LibKind +componentKind CLibName = LibKind +componentKind (CSubLibName _) = LibKind componentKind (CExeName _) = ExeKind componentKind (CTestName _) = TestKind componentKind (CBenchName _) = BenchKind diff --git a/cabal-install/Distribution/Client/Dependency/TopDown.hs b/cabal-install/Distribution/Client/Dependency/TopDown.hs index baf47f1bc8a..a1de90deb37 100644 --- a/cabal-install/Distribution/Client/Dependency/TopDown.hs +++ b/cabal-install/Distribution/Client/Dependency/TopDown.hs @@ -308,10 +308,9 @@ topDownResolver' platform cinfo installedPkgIndex sourcePkgIndex toResolverPackage :: FinalSelectedPackage -> ResolverPackage UnresolvedPkgLoc toResolverPackage (SelectedInstalled (InstalledPackage pkg pid_deps)) = PreExisting pkg deps - where deps = CD.fromLibraryDeps lib + where deps = CD.fromLibraryDeps . zipWith PreExistingId pid_deps $ InstalledPackageInfo.depends pkg - lib = display (packageName pkg) toResolverPackage (SelectedSource pkg) = Configured pkg addTopLevelTargets :: [PackageName] @@ -624,8 +623,7 @@ finaliseSelectedPackages pref selected constraints = -- We cheat in the cabal solver, and classify all dependencies as -- library dependencies. deps' :: ComponentDeps [SolverId] - deps' = CD.fromLibraryDeps (unPackageName (packageName pkg)) - (map (confId . pickRemaining mipkg) deps) + deps' = CD.fromLibraryDeps (map (confId . pickRemaining mipkg) deps) -- InstalledOrSource indicates that we either have a source package -- available, or an installed one, or both. In the case that we have both diff --git a/cabal-install/Distribution/Client/InstallPlan.hs b/cabal-install/Distribution/Client/InstallPlan.hs index 71d68d6d3e5..01e71bfd426 100644 --- a/cabal-install/Distribution/Client/InstallPlan.hs +++ b/cabal-install/Distribution/Client/InstallPlan.hs @@ -629,7 +629,7 @@ configureInstallPlan solverPlan = $ Configure.computeComponentId Cabal.NoFlag (packageId spkg) - (PD.CLibName (display (pkgName (packageId spkg)))) + PD.CLibName -- TODO: this is a hack that won't work for Backpack. (map ((\(SimpleUnitId cid0) -> cid0) . confInstId) (CD.libraryDeps deps)) diff --git a/cabal-install/Distribution/Client/List.hs b/cabal-install/Distribution/Client/List.hs index 615e953ae0a..da6a346be4c 100644 --- a/cabal-install/Distribution/Client/List.hs +++ b/cabal-install/Distribution/Client/List.hs @@ -63,7 +63,7 @@ import Distribution.Client.FetchUtils import Data.List ( sortBy, groupBy, sort, nub, intersperse, maximumBy, partition ) import Data.Maybe - ( listToMaybe, fromJust, fromMaybe, isJust ) + ( listToMaybe, fromJust, fromMaybe, isJust, maybeToList ) import qualified Data.Map as Map import Data.Tree as Tree import Control.Monad @@ -458,13 +458,14 @@ mergePackageInfo versionPref installedPkgs sourcePkgs selectedPkg showVer = flags = maybe [] Source.genPackageFlags sourceGeneric, hasLib = isJust installed || fromMaybe False - (fmap (not . null . Source.condLibraries) sourceGeneric), + (fmap (isJust . Source.condLibrary) sourceGeneric), hasExe = fromMaybe False (fmap (not . null . Source.condExecutables) sourceGeneric), executables = map fst (maybe [] Source.condExecutables sourceGeneric), modules = combine (map Installed.exposedName . Installed.exposedModules) installed - (concatMap getListOfExposedModules . Source.libraries) + -- NB: only for the PUBLIC library + (concatMap getListOfExposedModules . maybeToList . Source.library) source, dependencies = combine (map (SourceDependency . simplifyDependency) diff --git a/cabal-install/Distribution/Client/PackageUtils.hs b/cabal-install/Distribution/Client/PackageUtils.hs index 3b5fa7bc4ef..926467bd80c 100644 --- a/cabal-install/Distribution/Client/PackageUtils.hs +++ b/cabal-install/Distribution/Client/PackageUtils.hs @@ -32,5 +32,5 @@ externalBuildDepends pkg = filter (not . internal) (buildDepends pkg) internal (Dependency depName versionRange) = (depName == packageName pkg && packageVersion pkg `withinRange` versionRange) || - (unPackageName depName `elem` map libName (libraries pkg) && + (Just (unPackageName depName) `elem` map libName (subLibraries pkg) && isAnyVersion versionRange) diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index a3b62344ed5..3d5853d25b0 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -90,7 +90,8 @@ encodePlanAsJson elaboratedInstallPlan _elaboratedSharedConfig = -- TODO: maybe move this helper to "ComponentDeps" module? -- Or maybe define a 'Text' instance? comp2str c = case c of - ComponentDeps.ComponentLib s -> "lib:" <> s + ComponentDeps.ComponentLib -> "lib" + ComponentDeps.ComponentSubLib s -> "lib:" <> s ComponentDeps.ComponentExe s -> "exe:" <> s ComponentDeps.ComponentTest s -> "test:" <> s ComponentDeps.ComponentBench s -> "bench:" <> s diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index fd642f8ad6c..00e32025418 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -1612,7 +1612,7 @@ pruneInstallPlanPass2 pkgs = keepNeeded _ _ = True targetsRequiredForRevDeps = - [ ComponentTarget (Cabal.defaultLibName (pkgSourceId pkg)) WholeComponent + [ ComponentTarget Cabal.defaultLibName WholeComponent -- if anything needs this pkg, build the library component | installedPackageId pkg `Set.member` hasReverseLibDeps ] @@ -2036,11 +2036,11 @@ setupHsBuildArgs pkg = showComponentTarget :: ElaboratedConfiguredPackage -> ComponentTarget -> String -showComponentTarget _pkg = +showComponentTarget pkg = showBuildTarget . toBuildTarget where showBuildTarget t = - Cabal.showBuildTarget (qlBuildTarget t) t + Cabal.showBuildTarget (qlBuildTarget t) (packageId pkg) t qlBuildTarget Cabal.BuildTargetComponent{} = Cabal.QL2 qlBuildTarget _ = Cabal.QL3 @@ -2213,7 +2213,8 @@ packageHashInputs } where -- Obviously the main deps are relevant - relevantDeps (CD.ComponentLib _) = True + relevantDeps CD.ComponentLib = True + relevantDeps (CD.ComponentSubLib _) = True relevantDeps (CD.ComponentExe _) = True -- Setup deps can affect the Setup.hs behaviour and thus what is built relevantDeps CD.ComponentSetup = True diff --git a/cabal-install/Distribution/Solver/Modular/IndexConversion.hs b/cabal-install/Distribution/Solver/Modular/IndexConversion.hs index f7620555f6e..971c7796bfd 100644 --- a/cabal-install/Distribution/Solver/Modular/IndexConversion.hs +++ b/cabal-install/Distribution/Solver/Modular/IndexConversion.hs @@ -72,7 +72,7 @@ convIP idx ipi = ipid = IPI.installedUnitId ipi i = I (pkgVersion (sourcePackageId ipi)) (Inst ipid) pn = pkgName (sourcePackageId ipi) - setComp = setCompFlaggedDeps (ComponentLib (unPackageName pn)) + setComp = setCompFlaggedDeps ComponentLib -- TODO: Installed packages should also store their encapsulations! -- | Convert dependencies specified by an installed package id into @@ -108,8 +108,8 @@ convSP os arch cinfo strfl (SourcePackage (PackageIdentifier pn pv) gpd _ _pl) = -- | Convert a generic package description to a solver-specific 'PInfo'. convGPD :: OS -> Arch -> CompilerInfo -> StrongFlags -> PI PN -> GenericPackageDescription -> PInfo -convGPD os arch cinfo strfl pi@(PI pn _) - (GenericPackageDescription pkg flags libs exes tests benchs) = +convGPD os arch cinfo strfl pi + (GenericPackageDescription pkg flags mlib sub_libs exes tests benchs) = let fds = flagInfo strfl flags @@ -119,12 +119,7 @@ convGPD os arch cinfo strfl pi@(PI pn _) -- by creating a set of package names which are "internal" -- and dropping them as we convert. ipns = S.fromList [ PackageName nm - | (nm, _) <- libs - -- Don't include the true package name; - -- qualification could make this relevant. - -- TODO: Can we qualify over internal - -- dependencies? Not for now! - , PackageName nm /= pn ] + | (nm, _) <- sub_libs ] conv :: Mon.Monoid a => Component -> (a -> BuildInfo) -> CondTree ConfVar [Dependency] a -> FlaggedDeps Component PN @@ -132,7 +127,8 @@ convGPD os arch cinfo strfl pi@(PI pn _) PDC.addBuildableCondition getInfo flagged_deps - = concatMap (\(nm, ds) -> conv (ComponentLib nm) libBuildInfo ds) libs + = concatMap (\ds -> conv ComponentLib libBuildInfo ds) (maybeToList mlib) + ++ concatMap (\(nm, ds) -> conv (ComponentSubLib nm) libBuildInfo ds) sub_libs ++ concatMap (\(nm, ds) -> conv (ComponentExe nm) buildInfo ds) exes ++ prefix (Stanza (SN pi TestStanzas)) (L.map (\(nm, ds) -> conv (ComponentTest nm) testBuildInfo ds) tests) diff --git a/cabal-install/Distribution/Solver/Types/ComponentDeps.hs b/cabal-install/Distribution/Solver/Types/ComponentDeps.hs index 0da9dd4494b..94781b8d0e1 100644 --- a/cabal-install/Distribution/Solver/Types/ComponentDeps.hs +++ b/cabal-install/Distribution/Solver/Types/ComponentDeps.hs @@ -53,7 +53,8 @@ import Data.Traversable (Traversable(traverse)) -- | Component of a package. data Component = - ComponentLib String + ComponentLib + | ComponentSubLib String | ComponentExe String | ComponentTest String | ComponentBench String @@ -113,8 +114,8 @@ filterDeps :: (Component -> a -> Bool) -> ComponentDeps a -> ComponentDeps a filterDeps p = ComponentDeps . Map.filterWithKey p . unComponentDeps -- | ComponentDeps containing library dependencies only -fromLibraryDeps :: String -> a -> ComponentDeps a -fromLibraryDeps n = singleton (ComponentLib n) +fromLibraryDeps :: a -> ComponentDeps a +fromLibraryDeps = singleton ComponentLib -- | ComponentDeps containing setup dependencies only. fromSetupDeps :: a -> ComponentDeps a @@ -123,7 +124,7 @@ fromSetupDeps = singleton ComponentSetup -- | ComponentDeps for installed packages. -- -- We assume that installed packages only record their library dependencies. -fromInstalled :: String -> a -> ComponentDeps a +fromInstalled :: a -> ComponentDeps a fromInstalled = fromLibraryDeps {------------------------------------------------------------------------------- @@ -148,9 +149,11 @@ flatDeps = fold nonSetupDeps :: Monoid a => ComponentDeps a -> a nonSetupDeps = select (/= ComponentSetup) --- | Library dependencies proper only. +-- | Library dependencies proper only. (Includes dependencies +-- of internal libraries.) libraryDeps :: Monoid a => ComponentDeps a -> a -libraryDeps = select (\c -> case c of ComponentLib _ -> True +libraryDeps = select (\c -> case c of ComponentSubLib _ -> True + ComponentLib -> True _ -> False) -- | Setup dependencies. diff --git a/cabal-install/Distribution/Solver/Types/PackageFixedDeps.hs b/cabal-install/Distribution/Solver/Types/PackageFixedDeps.hs index 0b8811e5116..259305867bc 100644 --- a/cabal-install/Distribution/Solver/Types/PackageFixedDeps.hs +++ b/cabal-install/Distribution/Solver/Types/PackageFixedDeps.hs @@ -4,10 +4,9 @@ module Distribution.Solver.Types.PackageFixedDeps import Distribution.InstalledPackageInfo ( InstalledPackageInfo ) import Distribution.Package - ( Package(..), UnitId(..), pkgName, installedDepends) + ( Package(..), UnitId(..), installedDepends) import Distribution.Solver.Types.ComponentDeps ( ComponentDeps ) import qualified Distribution.Solver.Types.ComponentDeps as CD -import Distribution.Text (display) -- | Subclass of packages that have specific versioned dependencies. -- @@ -20,6 +19,5 @@ class Package pkg => PackageFixedDeps pkg where depends :: pkg -> ComponentDeps [UnitId] instance PackageFixedDeps InstalledPackageInfo where - depends pkg = CD.fromInstalled (display (pkgName (packageId pkg))) - (installedDepends pkg) + depends pkg = CD.fromInstalled (installedDepends pkg) diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs index 1afb1bb79ea..3ae64ccd098 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/DSL.hs @@ -172,7 +172,7 @@ data ExampleQualifier = exAv :: ExamplePkgName -> ExamplePkgVersion -> [ExampleDependency] -> ExampleAvailable exAv n v ds = ExAv { exAvName = n, exAvVersion = v - , exAvDeps = CD.fromLibraryDeps n ds } + , exAvDeps = CD.fromLibraryDeps ds } withSetupDeps :: ExampleAvailable -> [ExampleDependency] -> ExampleAvailable withSetupDeps ex setupDeps = ex { @@ -231,7 +231,8 @@ exAvSrcPkg ex = , packageDescription = C.GenericPackageDescription { C.packageDescription = C.emptyPackageDescription { C.package = exAvPkgId ex - , C.libraries = error "not yet configured: library" + , C.library = error "not yet configured: library" + , C.subLibraries = error "not yet configured: subLibraries" , C.executables = error "not yet configured: executables" , C.testSuites = error "not yet configured: testSuites" , C.benchmarks = error "not yet configured: benchmarks" @@ -243,9 +244,10 @@ exAvSrcPkg ex = } , C.genPackageFlags = nub $ concatMap extractFlags $ CD.libraryDeps (exAvDeps ex) ++ concatMap snd testSuites - , C.condLibraries = [(exAvName ex, mkCondTree (extsLib exts <> langLib mlang <> pcpkgLib pcpkgs) + , C.condLibrary = Just (mkCondTree (extsLib exts <> langLib mlang <> pcpkgLib pcpkgs) disableLib - (Buildable libraryDeps))] + (Buildable libraryDeps)) + , C.condSubLibraries = [] , C.condExecutables = [] , C.condTestSuites = let mkTree = mkCondTree mempty disableTest . Buildable diff --git a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs index 362e9049644..fbc38e4b0df 100644 --- a/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs +++ b/cabal-install/tests/UnitTests/Distribution/Solver/Modular/QuickCheck.hs @@ -280,15 +280,16 @@ instance Arbitrary Solver where shrink TopDown = [Modular] instance Arbitrary Component where - arbitrary = oneof [ ComponentLib <$> arbitraryComponentName + arbitrary = oneof [ return ComponentLib + , ComponentSubLib <$> arbitraryComponentName , ComponentExe <$> arbitraryComponentName , ComponentTest <$> arbitraryComponentName , ComponentBench <$> arbitraryComponentName , return ComponentSetup ] - shrink (ComponentLib "") = [] - shrink _ = [ComponentLib ""] + shrink ComponentLib = [] + shrink _ = [ComponentLib] instance Arbitrary ExampleInstalled where arbitrary = error "arbitrary not implemented: ExampleInstalled"