Skip to content

Commit e6170f1

Browse files
authored
Merge pull request #6928 from commercialhaskell/re6896
Fix #6896 Allow dependency package to have no main library
2 parents caabafa + a7f8659 commit e6170f1

36 files changed

Lines changed: 415 additions & 159 deletions

File tree

.stan.toml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -140,25 +140,25 @@
140140

141141
# Anti-pattern: Data.ByteString.Char8.pack
142142
[[ignore]]
143-
id = "OBS-STAN-0203-erw24B-1084:3"
143+
id = "OBS-STAN-0203-erw24B-1138:3"
144144
# ✦ Description: Usage of 'pack' function that doesn't handle Unicode characters
145145
# ✦ Category: #AntiPattern
146146
# ✦ File: src\Stack\Build\ExecuteEnv.hs
147147
#
148-
# 1083
149-
# 1084 ┃ S8.pack . formatTime defaultTimeLocale "%Y-%m-%dT%H:%M:%S%6Q"
150-
# 1085 ┃ ^^^^^^^
148+
# 1137
149+
# 1138 ┃ S8.pack . formatTime defaultTimeLocale "%Y-%m-%dT%H:%M:%S%6Q"
150+
# 1139 ┃ ^^^^^^^
151151

152152
# Anti-pattern: Data.ByteString.Char8.pack
153153
[[ignore]]
154-
id = "OBS-STAN-0203-tuE+RG-253:24"
154+
id = "OBS-STAN-0203-tuE+RG-252:24"
155155
# ✦ Description: Usage of 'pack' function that doesn't handle Unicode characters
156156
# ✦ Category: #AntiPattern
157157
# ✦ File: src\Stack\Build\ExecutePackage.hs
158158
#
159-
# 252
160-
# 253 ┃ newConfigFileRoot <- S8.pack . toFilePath <$> view configFileRootL
161-
# 254 ┃ ^^^^^^^
159+
# 251
160+
# 252 ┃ newConfigFileRoot <- S8.pack . toFilePath <$> view configFileRootL
161+
# 253 ┃ ^^^^^^^
162162

163163
# Anti-pattern: Data.ByteString.Char8.pack
164164
[[ignore]]

src/Stack/Build/Cache.hs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,7 @@ import Stack.Types.EnvConfig
7979
)
8080
import Stack.Types.GhcPkgId ( ghcPkgIdString )
8181
import Stack.Types.Installed
82-
( InstallLocation (..), Installed (..)
83-
, InstalledLibraryInfo (..), foldOnGhcPkgId'
84-
)
82+
( InstallLocation (..), Installed (..), foldOnGhcPkgId' )
8583
import Stack.Types.NamedComponent
8684
( NamedComponent (..), componentCachePath )
8785
import Stack.Types.SourceMap ( smRelDir )
@@ -301,12 +299,9 @@ deleteCaches dir =
301299
flagCacheKey :: (HasEnvConfig env) => Installed -> RIO env ConfigCacheKey
302300
flagCacheKey installed = do
303301
installationRoot <- installationRootLocal
304-
case installed of
305-
Library _ installedInfo -> do
306-
let gid = installedInfo.ghcPkgId
307-
pure $ configCacheKey installationRoot (ConfigCacheTypeFlagLibrary gid)
308-
Executable ident -> pure $
309-
configCacheKey installationRoot (ConfigCacheTypeFlagExecutable ident)
302+
pure $ configCacheKey installationRoot $ case installed of
303+
Library ident _ -> ConfigCacheTypeFlagLibrary ident
304+
Executable ident -> ConfigCacheTypeFlagExecutable ident
310305

311306
-- | Loads the Cabal flag cache for the given installed extra-deps.
312307
tryGetFlagCache ::

src/Stack/Build/ConstructPlan.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1081,7 +1081,7 @@ checkDirtiness ::
10811081
PackageSource
10821082
-> Installed
10831083
-> Package
1084-
-> Map PackageIdentifier GhcPkgId
1084+
-> Map MungedPackageId GhcPkgId
10851085
-> Bool
10861086
-- ^ Is Haddock documentation being built?
10871087
-> M Bool

src/Stack/Build/ExecuteEnv.hs

Lines changed: 71 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ import Stack.Types.CompilerPaths
9797
import Stack.Types.Config
9898
( Config (..), HasConfig (..), stackRootL )
9999
import Stack.Types.ConfigureOpts ( BaseConfigOpts (..) )
100-
import Stack.Types.Dependency ( DepValue(..) )
100+
import Stack.Types.Dependency
101+
( DepLibrary (..), DepType (..), DepValue (..) )
101102
import Stack.Types.DumpLogs ( DumpLogs (..) )
102103
import Stack.Types.DumpPackage ( DumpPackage (..) )
103104
import Stack.Types.EnvConfig
@@ -108,7 +109,9 @@ import Stack.Types.EnvSettings ( EnvSettings (..) )
108109
import Stack.Types.GhcPkgId ( GhcPkgId, ghcPkgIdString )
109110
import Stack.Types.Installed ( InstallLocation (..), Installed (..) )
110111
import Stack.Types.Package
111-
( LocalPackage (..), Package (..), packageIdentifier )
112+
( LocalPackage (..), Package (..), packageIdentifier
113+
, toCabalMungedPackageName
114+
)
112115
import Stack.Types.Plan
113116
( TaskType (..), taskTypeLocation, taskTypePackageIdentifier
114117
)
@@ -596,7 +599,7 @@ withSingleContext ::
596599
=> ActionContext
597600
-> ExecuteEnv
598601
-> TaskType
599-
-> Map PackageIdentifier GhcPkgId
602+
-> Map MungedPackageId GhcPkgId
600603
-- ^ Ids of Installed packages that are assumed to be available to build a
601604
-- package's custom @Setup.hs@, given its dependencies specified in its
602605
-- @custom-setup@ stanza of its Cabal file.
@@ -800,25 +803,57 @@ withSingleContext
800803
pure cabalPackageArg
801804
matchedDeps <-
802805
forM (Map.toList customSetupDeps) $ \(name, depValue) -> do
803-
let matches (PackageIdentifier name' version) =
804-
name == name'
806+
let mungedPkgNames = depToMungedPkgNames name depValue
807+
countMungedPkgNames = Set.size mungedPkgNames
808+
matches (MungedPackageId mungedPkgName version) _ =
809+
mungedPkgName `Set.member` mungedPkgNames
805810
&& version `withinRange` depValue.versionRange
806-
case filter (matches . fst) (Map.toList allDeps) of
807-
x:xs -> do
808-
unless (null xs) $
809-
prettyWarnL
810-
[ flow "Found multiple installed packages for \
811-
\custom-setup dep:"
812-
, style Current (fromPackageName name) <> "."
813-
]
814-
pure ("-package-id=" ++ ghcPkgIdString (snd x), Just (fst x))
815-
[] -> do
811+
case Map.filterWithKey matches allDeps of
812+
matchedDeps | Map.null matchedDeps -> do
816813
prettyWarnL
817814
[ flow "Could not find custom-setup dep:"
818815
, style Current (fromPackageName name) <> "."
819816
]
820-
pure ("-package=" ++ packageNameString name, Nothing)
821-
let depsArgs = map fst matchedDeps
817+
pure (["-package=" <> packageNameString name], Nothing)
818+
matchedDeps -> do
819+
let groupMatchedByVersion =
820+
Map.foldlWithKey'
821+
( \acc k v ->
822+
let p = mungedVersion k
823+
innerMap = Map.singleton k v
824+
in Map.insertWith Map.union p innerMap acc
825+
)
826+
Map.empty
827+
matchedDeps
828+
countMatchedDeps = Map.size matchedDeps
829+
if Map.size groupMatchedByVersion == 1
830+
then do
831+
when (countMatchedDeps < countMungedPkgNames) $
832+
prettyWarnL
833+
[ flow "Found insufficent installed packages \
834+
\for custom-setup dep:"
835+
, style Current (fromPackageName name) <> "."
836+
]
837+
else do
838+
prettyWarnL
839+
[ flow "Found installed packages with multiple \
840+
\versions for custom-setup dep:"
841+
, style Current (fromPackageName name) <> "."
842+
]
843+
let packageIdOpt ghcPkgId =
844+
"-package-id=" <> ghcPkgIdString ghcPkgId
845+
-- The previous algorithm (arbitrarily?) selected
846+
-- the first relevant item yielded by Map.toList
847+
-- (which is Map.toAscList), so we select the
848+
-- minimum:
849+
selectedGroup = Map.findMin groupMatchedByVersion
850+
selectedVersion = fst selectedGroup
851+
packageIdOpts =
852+
map packageIdOpt $ Map.elems $ snd selectedGroup
853+
selectedPkgId =
854+
PackageIdentifier name selectedVersion
855+
pure (packageIdOpts, Just selectedPkgId)
856+
let depsArgs = L.concatMap fst matchedDeps
822857
-- Generate setup_macros.h and provide it to ghc
823858
let macroDeps = mapMaybe snd matchedDeps
824859
cppMacrosFile = setupDir </> relFileSetupMacrosH
@@ -880,6 +915,25 @@ withSingleContext
880915
setupArgs =
881916
("--builddir=" ++ toFilePathNoTrailingSep distRelativeDir') : args
882917

918+
depToMungedPkgNames ::
919+
PackageName
920+
-- ^ The name of the Cabal package.
921+
-> DepValue
922+
-- ^ The dependency value for that package.
923+
-> Set.Set MungedPackageName
924+
depToMungedPkgNames pkgName depValue
925+
| AsLibrary depLibrary <- depValue.depType =
926+
let addMain = if depLibrary.main
927+
then Set.insert mungedMainPkgName
928+
else id
929+
mungedMainPkgName = toCabalMungedPackageName pkgName Nothing
930+
subLibSet =
931+
Set.map
932+
(toCabalMungedPackageName pkgName . Just)
933+
depLibrary.subLib
934+
in addMain subLibSet
935+
| otherwise = Set.empty
936+
883937
runExe :: Path Abs File -> [String] -> RIO env ()
884938
runExe exeName fullArgs = do
885939
runAndOutput `catch` \ece -> do

src/Stack/Build/ExecutePackage.hs

Lines changed: 31 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ import Stack.Types.GhcPkgId ( GhcPkgId, ghcPkgIdToText )
130130
import Stack.Types.GlobalOpts ( GlobalOpts (..) )
131131
import Stack.Types.Installed
132132
( InstallLocation (..), Installed (..), InstalledMap
133-
, InstalledLibraryInfo (..)
133+
, InstalledLibraryInfo (..), simpleInstalledLib
134134
)
135135
import Stack.Types.IsMutable ( IsMutable (..) )
136136
import Stack.Types.NamedComponent
@@ -139,8 +139,7 @@ import Stack.Types.NamedComponent
139139
)
140140
import Stack.Types.Package
141141
( LocalPackage (..), Package (..), installedPackageToGhcPkgId
142-
, runMemoizedWith, simpleInstalledLib
143-
, toCabalMungedPackageName
142+
, runMemoizedWith, toCabalMungedPackageName
144143
)
145144
import Stack.Types.PackageFile ( PackageWarning (..) )
146145
import Stack.Types.Plan
@@ -164,7 +163,7 @@ getConfigCache ::
164163
-> InstalledMap
165164
-> Bool
166165
-> Bool
167-
-> RIO env (Map PackageIdentifier GhcPkgId, ConfigCache)
166+
-> RIO env (Map MungedPackageId GhcPkgId, ConfigCache)
168167
getConfigCache ee task installedMap enableTest enableBench = do
169168
let extra =
170169
-- We enable tests if the test suite dependencies are already
@@ -425,7 +424,7 @@ realConfigAndBuild ::
425424
-- ^ (isFinalBuild, buildingFinals)
426425
-> ConfigCache
427426
-> Maybe Curator
428-
-> Map PackageIdentifier GhcPkgId
427+
-> Map MungedPackageId GhcPkgId
429428
-- ^ Ids of installed packages that are assumed to be available to build a
430429
-- package's custom @Setup.hs@, given its dependencies specified in its
431430
-- @custom-setup@ stanza of its Cabal file.
@@ -726,27 +725,28 @@ fetchAndMarkInstalledPackage ::
726725
-> PackageIdentifier
727726
-> RIO env Installed
728727
fetchAndMarkInstalledPackage ee taskInstallLocation package pkgId = do
729-
let ghcPkgIdLoader = fetchGhcPkgIdForLib ee taskInstallLocation package.name
730-
-- Only pure the sub-libraries to cache them if we also cache the main
731-
-- library (that is, if it exists)
732-
if hasBuildableMainLibrary package
728+
let hasMainLibrary = hasBuildableMainLibrary package
729+
subLibs = package.subLibraries
730+
if not hasMainLibrary && null subLibs
733731
then do
734-
let foldSubLibToMap subLib mapInMonad = do
735-
maybeGhcpkgId <- ghcPkgIdLoader (Just subLib.name)
736-
mapInMonad <&> case maybeGhcpkgId of
737-
Just v -> Map.insert subLib.name v
738-
_ -> id
739-
subLibsPkgIds <- foldComponentToAnotherCollection
740-
package.subLibraries
741-
foldSubLibToMap
742-
mempty
743-
ghcPkgIdLoader Nothing >>= \case
744-
Nothing -> throwM $ Couldn'tFindPkgId package.name
745-
Just ghcPkgId -> pure $ simpleInstalledLib pkgId ghcPkgId subLibsPkgIds
746-
else do
747-
markExeInstalled taskInstallLocation pkgId -- TODO unify somehow
748-
-- with writeFlagCache?
732+
markExeInstalled taskInstallLocation pkgId
733+
-- TODO: Unify the above somehow with writeFlagCache?
749734
pure $ Executable pkgId
735+
else do
736+
ghcPkgId <- if hasMainLibrary
737+
then ghcPkgIdLoader Nothing
738+
else pure Nothing
739+
subLibsPkgIds <-
740+
foldComponentToAnotherCollection subLibs foldSubLibToMap mempty
741+
pure $ simpleInstalledLib pkgId ghcPkgId subLibsPkgIds
742+
where
743+
ghcPkgIdLoader = fetchGhcPkgIdForLib ee taskInstallLocation package.name
744+
745+
foldSubLibToMap subLib mapInMonad = do
746+
maybeGhcpkgId <- ghcPkgIdLoader (Just subLib.name)
747+
mapInMonad <&> case maybeGhcpkgId of
748+
Just v -> Map.insert subLib.name v
749+
_ -> id
750750

751751
fetchGhcPkgIdForLib ::
752752
(HasTerm env, HasEnvConfig env)
@@ -755,7 +755,7 @@ fetchGhcPkgIdForLib ::
755755
-> PackageName
756756
-> Maybe Component.StackUnqualCompName
757757
-> RIO env (Maybe GhcPkgId)
758-
fetchGhcPkgIdForLib ee installLocation pkgName libName = do
758+
fetchGhcPkgIdForLib ee installLocation pkgName mLibName = do
759759
let baseConfigOpts = ee.baseConfigOpts
760760
(installedPkgDb, installedDumpPkgsTVar) =
761761
case installLocation of
@@ -766,11 +766,9 @@ fetchGhcPkgIdForLib ee installLocation pkgName libName = do
766766
( baseConfigOpts.localDB
767767
, ee.localDumpPkgs )
768768
let commonLoader = loadInstalledPkg [installedPkgDb] installedDumpPkgsTVar
769-
case libName of
770-
Nothing -> commonLoader pkgName
771-
Just v -> do
772-
let mungedName = encodeCompatPackageName $ toCabalMungedPackageName pkgName v
773-
commonLoader mungedName
769+
mungedPkgName = toCabalMungedPackageName pkgName mLibName
770+
encodedPkgName = encodeCompatPackageName mungedPkgName
771+
commonLoader encodedPkgName
774772

775773
-- | Copy ddump-* files, if we are building finals and a non-empty ddump-dir
776774
-- has been specified.
@@ -926,7 +924,7 @@ copyPreCompiled ee task pkgId (PrecompiledCache mlib subLibs exes) = do
926924
pure $ Just $
927925
case mpkgid of
928926
Nothing -> assert False $ Executable pkgId
929-
Just pkgid -> simpleInstalledLib pkgId pkgid mempty
927+
_ -> simpleInstalledLib pkgId mpkgid mempty
930928
where
931929
bindir = ee.baseConfigOpts.snapInstallRoot </> bindirSuffix
932930

@@ -1067,8 +1065,8 @@ singleTest topts testsToRun ac ee task installedMap = do
10671065
idMap <- liftIO $ readTVarIO ee.ghcPkgIds
10681066
pure $ Map.lookup (taskProvides task) idMap
10691067
let pkgGhcIdList = case installed of
1070-
Just (Library _ libInfo) -> [libInfo.ghcPkgId]
1071-
_ -> []
1068+
Just (Library _ libInfo) -> maybeToList libInfo.mMainGhcPkgId
1069+
_ -> []
10721070
-- doctest relies on template-haskell in QuickCheck-based tests
10731071
thGhcId <-
10741072
case L.find ((== "template-haskell") . pkgName . (.packageIdent) . snd)

src/Stack/Build/Installed.hs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ toLoadHelper compiler pkgDb dp = LoadHelper
287287
if name `Set.member` wiredInPackages compiler
288288
then []
289289
else dp.depends
290-
installedLibInfo = InstalledLibraryInfo ghcPkgId (Right <$> dp.license) mempty
290+
installedLibInfo = InstalledLibraryInfo (Just ghcPkgId) mempty
291291

292292
toInstallLocation :: PackageDbVariety -> InstallLocation
293293
toInstallLocation GlobalDb = Snap
@@ -313,23 +313,26 @@ gatherAndTransformSubLoadHelper lh =
313313
(_, Library _ existingLibInfo)
314314
= ( pLoc
315315
, Library pn existingLibInfo
316-
{ subLib = Map.union
317-
incomingLibInfo.subLib
318-
existingLibInfo.subLib
319-
, ghcPkgId = if isJust lh.subLibDump
320-
then existingLibInfo.ghcPkgId
321-
else incomingLibInfo.ghcPkgId
316+
{ subLib = Map.union incomingLibInfo.subLib existingLibInfo.subLib
317+
, mMainGhcPkgId =
318+
if isJust lh.subLibDump
319+
then existingLibInfo.mMainGhcPkgId
320+
else incomingLibInfo.mMainGhcPkgId
322321
}
323322
)
324323
onPreviousLoadHelper newVal _oldVal = newVal
325324
(key, value) = case lh.subLibDump of
326325
Nothing -> (rawPackageName, rawValue)
327326
Just sd -> (sd.packageName, updateAsSublib sd <$> rawValue)
327+
-- rawValue should always have a main library: see toLoadHelper.
328328
(rawPackageName, rawValue) = lh.pair
329329
updateAsSublib
330330
sd
331331
(Library (PackageIdentifier _sublibMungedPackageName version) libInfo)
332-
= Library
333-
(PackageIdentifier key version)
334-
libInfo { subLib = Map.singleton sd.libraryName libInfo.ghcPkgId }
332+
= case libInfo.mMainGhcPkgId of
333+
Nothing ->
334+
error "gatherAndTransformSubLoadHelper: the impossible happened!"
335+
Just ghcPkgId' -> Library
336+
(PackageIdentifier key version)
337+
libInfo { subLib = Map.singleton sd.libraryName ghcPkgId' }
335338
updateAsSublib _ v = v

0 commit comments

Comments
 (0)