Skip to content

Commit

Permalink
Don't generate build-tools starting with cabal-version: 2
Browse files Browse the repository at this point in the history
(fixes #596)
  • Loading branch information
sol committed Jan 23, 2025
1 parent 1323330 commit f845bbe
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 111 deletions.
2 changes: 1 addition & 1 deletion .ghci
Original file line number Diff line number Diff line change
@@ -1 +1 @@
:set -XHaskell2010 -Wredundant-constraints -fno-warn-incomplete-uni-patterns -DTEST -isrc -itest -i./dist-newstyle/build/x86_64-linux/ghc-9.6.2/hpack-0.36.0/build/autogen
:set -XHaskell2010 -Wredundant-constraints -fno-warn-incomplete-uni-patterns -DTEST -isrc -itest -i./dist-newstyle/build/x86_64-linux/ghc-9.10.1/hpack-0.37.0/build/autogen
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## Changes in 0.38.0
- Don't generate `build-tools` starting with `cabal-version: 2` (fixes #596)

## Changes in 0.37.0
- Add support for `asm-options` and `asm-sources` (see #573)

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2014-2023 Simon Hengel <[email protected]>
Copyright (c) 2014-2025 Simon Hengel <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
156 changes: 98 additions & 58 deletions src/Hpack/Config.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
Expand Down Expand Up @@ -41,6 +42,8 @@ module Hpack.Config (
, package
, section
, Package(..)
, CabalVersion(..)
, makeCabalVersion
, Dependencies(..)
, DependencyInfo(..)
, VersionConstraint(..)
Expand Down Expand Up @@ -104,7 +107,8 @@ import Control.Monad.State (MonadState, StateT, evalStateT)
import qualified Control.Monad.State as State
import Control.Monad.Writer (MonadWriter, WriterT, runWriterT, tell)
import Control.Monad.Except
import Data.Version (Version, makeVersion, showVersion)
import Data.Version (Version, showVersion)
import qualified Data.Version as Version

import Distribution.Pretty (prettyShow)
import qualified Distribution.SPDX.License as SPDX
Expand Down Expand Up @@ -132,9 +136,13 @@ import qualified Path

import qualified Paths_hpack as Hpack (version)

defaultCabalVersion :: Version
defaultCabalVersion = Version.makeVersion [1,12]

package :: String -> String -> Package
package name version = Package {
packageName = name
packageCabalVersion = CabalVersion defaultCabalVersion
, packageName = name
, packageVersion = version
, packageSynopsis = Nothing
, packageDescription = Nothing
Expand Down Expand Up @@ -698,8 +706,13 @@ readPackageConfigWithError (DecodeOptions _ file mUserDataDir readValue formatYa
userDataDir <- liftIO $ maybe (getAppUserDataDirectory "hpack") return mUserDataDir
toPackage formatYamlParseError userDataDir dir config
where
addCabalFile :: ((Package, String), [String]) -> DecodeResult
addCabalFile ((pkg, cabalVersion), warnings) = DecodeResult pkg cabalVersion (takeDirectory_ file </> (packageName pkg ++ ".cabal")) warnings
addCabalFile :: (Package, [String]) -> DecodeResult
addCabalFile (pkg, warnings) = DecodeResult {
decodeResultPackage = pkg
, decodeResultCabalVersion = "cabal-version: " ++ showCabalVersion (packageCabalVersion pkg) ++ "\n\n"
, decodeResultCabalFile = takeDirectory_ file </> packageName pkg <.> "cabal"
, decodeResultWarnings = warnings
}

takeDirectory_ :: FilePath -> FilePath
takeDirectory_ p
Expand All @@ -718,9 +731,9 @@ verbatimValueToString = \ case
VerbatimBool b -> show b
VerbatimNull -> ""

addPathsModuleToGeneratedModules :: Package -> Version -> Package
addPathsModuleToGeneratedModules pkg cabalVersion
| cabalVersion < makeVersion [2] = pkg
addPathsModuleToGeneratedModules :: Package -> Package
addPathsModuleToGeneratedModules pkg
| packageCabalVersion pkg < makeCabalVersion [2] = pkg
| otherwise = pkg {
packageLibrary = fmap mapLibrary <$> packageLibrary pkg
, packageInternalLibraries = fmap mapLibrary <$> packageInternalLibraries pkg
Expand Down Expand Up @@ -749,22 +762,56 @@ addPathsModuleToGeneratedModules pkg cabalVersion
where
generatedModules = executableGeneratedModules executable

determineCabalVersion :: Maybe (License SPDX.License) -> Package -> (Package, String, Maybe Version)
determineCabalVersion inferredLicense pkg@Package{..} = (
pkg {
packageVerbatim = deleteVerbatimField "cabal-version" packageVerbatim
, packageLicense = formatLicense <$> license
}
, "cabal-version: " ++ effectiveCabalVersion ++ "\n\n"
, parseVersion effectiveCabalVersion
)
data CabalVersion = CabalVersion Version | VerbatimCabalVersion String
deriving (Eq, Ord, Show)

makeCabalVersion :: [Int] -> CabalVersion
makeCabalVersion = CabalVersion . Version.makeVersion

showCabalVersion :: CabalVersion -> String
showCabalVersion = \ case
CabalVersion v -> showVersion v
VerbatimCabalVersion v -> v

extractVerbatimCabalVersion :: [Verbatim] -> (Maybe CabalVersion, [Verbatim])
extractVerbatimCabalVersion verbatim = case listToMaybe (mapMaybe extractCabalVersion verbatim) of
Nothing -> (Nothing, verbatim)
Just verbatimVersion -> (Just cabalVersion, deleteVerbatimField "cabal-version" verbatim)
where
cabalVersion :: CabalVersion
cabalVersion = case parseVersion verbatimVersion of
Nothing -> VerbatimCabalVersion verbatimVersion
Just v -> CabalVersion v
where


extractCabalVersion :: Verbatim -> Maybe String
extractCabalVersion = \ case
VerbatimLiteral _ -> Nothing
VerbatimObject o -> case Map.lookup "cabal-version" o of
Just v -> Just (verbatimValueToString v)
Nothing -> Nothing

ensureRequiredCabalVersion :: Maybe (License SPDX.License) -> Package -> Package
ensureRequiredCabalVersion inferredLicense pkg@Package{..} = pkg {
packageCabalVersion = version
, packageLicense = formatLicense <$> license
, packageVerbatim = verbatim
}
where
effectiveCabalVersion = fromMaybe inferredCabalVersion verbatimCabalVersion
(verbatimCabalVersion, verbatim) = extractVerbatimCabalVersion packageVerbatim


makeVersion :: [Int] -> CabalVersion
makeVersion = makeCabalVersion

license :: Maybe (License String)
license = fmap prettyShow <$> (parsedLicense <|> inferredLicense)

parsedLicense :: Maybe (License SPDX.License)
parsedLicense = parseLicense <$> packageLicense

formatLicense :: License String -> String
formatLicense = \ case
MustSPDX spdx -> spdx
CanSPDX _ spdx | version >= makeVersion [2,2] -> spdx
Expand All @@ -779,37 +826,19 @@ determineCabalVersion inferredLicense pkg@Package{..} = (
CanSPDX _ _ -> False
MustSPDX _ -> True

verbatimCabalVersion :: Maybe String
verbatimCabalVersion = listToMaybe (mapMaybe f packageVerbatim)
where
f :: Verbatim -> Maybe String
f = \ case
VerbatimLiteral _ -> Nothing
VerbatimObject o -> case Map.lookup "cabal-version" o of
Just v -> Just (verbatimValueToString v)
Nothing -> Nothing

inferredCabalVersion :: String
inferredCabalVersion = showVersion version

version = fromMaybe (makeVersion [1,12]) $ maximum [
packageCabalVersion
version :: CabalVersion
version = flip fromMaybe verbatimCabalVersion $ fromMaybe packageCabalVersion $ maximum [
makeVersion [2,2] <$ guard mustSPDX
, makeVersion [1,24] <$ packageCustomSetup
, makeVersion [1,18] <$ guard (not (null packageExtraDocFiles))
, packageLibrary >>= libraryCabalVersion
, internalLibsCabalVersion packageInternalLibraries
, executablesCabalVersion packageExecutables
, executablesCabalVersion packageTests
, executablesCabalVersion packageBenchmarks
]

packageCabalVersion :: Maybe Version
packageCabalVersion = maximum [
Nothing
, makeVersion [2,2] <$ guard mustSPDX
, makeVersion [1,24] <$ packageCustomSetup
, makeVersion [1,18] <$ guard (not (null packageExtraDocFiles))
]

libraryCabalVersion :: Section Library -> Maybe Version
libraryCabalVersion :: Section Library -> Maybe CabalVersion
libraryCabalVersion sect = maximum [
makeVersion [1,22] <$ guard (has libraryReexportedModules)
, makeVersion [2,0] <$ guard (has librarySignatures)
Expand All @@ -820,17 +849,17 @@ determineCabalVersion inferredLicense pkg@Package{..} = (
where
has field = any (not . null . field) sect

internalLibsCabalVersion :: Map String (Section Library) -> Maybe Version
internalLibsCabalVersion :: Map String (Section Library) -> Maybe CabalVersion
internalLibsCabalVersion internalLibraries
| Map.null internalLibraries = Nothing
| otherwise = foldr max (Just $ makeVersion [2,0]) versions
where
versions = libraryCabalVersion <$> Map.elems internalLibraries

executablesCabalVersion :: Map String (Section Executable) -> Maybe Version
executablesCabalVersion :: Map String (Section Executable) -> Maybe CabalVersion
executablesCabalVersion = foldr max Nothing . map executableCabalVersion . Map.elems

executableCabalVersion :: Section Executable -> Maybe Version
executableCabalVersion :: Section Executable -> Maybe CabalVersion
executableCabalVersion sect = maximum [
makeVersion [2,0] <$ guard (executableHasGeneratedModules sect)
, sectionCabalVersion (concatMap getExecutableModules) sect
Expand All @@ -839,7 +868,7 @@ determineCabalVersion inferredLicense pkg@Package{..} = (
executableHasGeneratedModules :: Section Executable -> Bool
executableHasGeneratedModules = any (not . null . executableGeneratedModules)

sectionCabalVersion :: (Section a -> [Module]) -> Section a -> Maybe Version
sectionCabalVersion :: (Section a -> [Module]) -> Section a -> Maybe CabalVersion
sectionCabalVersion getMentionedModules sect = maximum $ [
makeVersion [2,2] <$ guard (sectionSatisfies (not . null . sectionCxxSources) sect)
, makeVersion [2,2] <$ guard (sectionSatisfies (not . null . sectionCxxOptions) sect)
Expand All @@ -853,17 +882,23 @@ determineCabalVersion inferredLicense pkg@Package{..} = (
&& pathsModule `elem` getMentionedModules sect)
] ++ map versionFromSystemBuildTool systemBuildTools
where
defaultExtensions :: [String]
defaultExtensions = sectionAll sectionDefaultExtensions sect

uses :: String -> Bool
uses = (`elem` defaultExtensions)

pathsModule :: Module
pathsModule = pathsModuleFromPackageName packageName

versionFromSystemBuildTool :: String -> Maybe CabalVersion
versionFromSystemBuildTool name
| name `elem` known_1_10 = Nothing
| name `elem` known_1_14 = Just (makeVersion [1,14])
| name `elem` known_1_22 = Just (makeVersion [1,22])
| otherwise = Just (makeVersion [2,0])

known_1_10 :: [String]
known_1_10 = [
"ghc"
, "ghc-pkg"
Expand Down Expand Up @@ -891,9 +926,13 @@ determineCabalVersion inferredLicense pkg@Package{..} = (
, "lhc"
, "lhc-pkg"
]

known_1_14 :: [String]
known_1_14 = [
"hpc"
]

known_1_22 :: [String]
known_1_22 = [
"ghcjs"
, "ghcjs-pkg"
Expand Down Expand Up @@ -966,7 +1005,8 @@ instance FromValue ParseSpecVersion where
Nothing -> fail ("invalid value " ++ show s)

data Package = Package {
packageName :: String
packageCabalVersion :: CabalVersion
, packageName :: String
, packageVersion :: String
, packageSynopsis :: Maybe String
, packageDescription :: Maybe String
Expand Down Expand Up @@ -1093,7 +1133,7 @@ type ConfigWithDefaults = Product
type CommonOptionsWithDefaults a = Product DefaultsConfig (CommonOptions ParseAsmSources ParseCSources ParseCxxSources ParseJsSources a)
type WithCommonOptionsWithDefaults a = Product DefaultsConfig (WithCommonOptions ParseAsmSources ParseCSources ParseCxxSources ParseJsSources a)

toPackage :: FormatYamlParseError -> FilePath -> FilePath -> ConfigWithDefaults -> ConfigM IO (Package, String)
toPackage :: FormatYamlParseError -> FilePath -> FilePath -> ConfigWithDefaults -> ConfigM IO Package
toPackage formatYamlParseError userDataDir dir =
expandDefaultsInConfig formatYamlParseError userDataDir dir
>=> setDefaultLanguage "Haskell2010"
Expand Down Expand Up @@ -1195,23 +1235,23 @@ toExecutableMap name executables mExecutable = do

type GlobalOptions = CommonOptions AsmSources CSources CxxSources JsSources Empty

toPackage_ :: (MonadIO m, Warnings m, State m) => FilePath -> Product GlobalOptions (PackageConfig AsmSources CSources CxxSources JsSources) -> m (Package, String)
toPackage_ :: (MonadIO m, Warnings m, State m) => FilePath -> Product GlobalOptions (PackageConfig AsmSources CSources CxxSources JsSources) -> m Package
toPackage_ dir (Product g PackageConfig{..}) = do
executableMap <- toExecutableMap packageName_ packageConfigExecutables packageConfigExecutable
executableMap <- toExecutableMap packageName packageConfigExecutables packageConfigExecutable
let
globalVerbatim = commonOptionsVerbatim g
globalOptions = g {commonOptionsVerbatim = Nothing}

executableNames = maybe [] Map.keys executableMap

toSect :: (Warnings m, Monoid a) => WithCommonOptions AsmSources CSources CxxSources JsSources a -> m (Section a)
toSect = toSection packageName_ executableNames . first ((mempty <$ globalOptions) <>)
toSect = toSection packageName executableNames . first ((mempty <$ globalOptions) <>)

toSections :: (Warnings m, Monoid a) => Maybe (Map String (WithCommonOptions AsmSources CSources CxxSources JsSources a)) -> m (Map String (Section a))
toSections = maybe (return mempty) (traverse toSect)

toLib = toLibrary dir packageName_
toExecutables = toSections >=> traverse (toExecutable dir packageName_)
toLib = toLibrary dir packageName
toExecutables = toSections >=> traverse (toExecutable dir packageName)

mLibrary <- traverse (toSect >=> toLib) packageConfigLibrary
internalLibraries <- toSections packageConfigInternalLibraries >>= traverse toLib
Expand Down Expand Up @@ -1257,7 +1297,8 @@ toPackage_ dir (Product g PackageConfig{..}) = do
defaultBuildType = maybe Simple (const Custom) mCustomSetup

pkg = Package {
packageName = packageName_
packageCabalVersion = CabalVersion defaultCabalVersion
, packageName
, packageVersion = maybe "0.0.0" unPackageVersion packageConfigVersion
, packageSynopsis = packageConfigSynopsis
, packageDescription = packageConfigDescription
Expand Down Expand Up @@ -1290,12 +1331,11 @@ toPackage_ dir (Product g PackageConfig{..}) = do
tell nameWarnings
tell (formatMissingSourceDirs missingSourceDirs)

let (pkg_, renderedCabalVersion, cabalVersion) = determineCabalVersion inferredLicense pkg
return (maybe pkg_ (addPathsModuleToGeneratedModules pkg_) cabalVersion, renderedCabalVersion)
return $ addPathsModuleToGeneratedModules $ ensureRequiredCabalVersion inferredLicense pkg
where
nameWarnings :: [String]
packageName_ :: String
(nameWarnings, packageName_) = case packageConfigName of
packageName :: String
(nameWarnings, packageName) = case packageConfigName of
Nothing -> let inferredName = takeBaseName dir in
(["Package name not specified, inferred " ++ show inferredName], inferredName)
Just n -> ([], n)
Expand Down Expand Up @@ -1418,7 +1458,7 @@ inferModules dir packageName_ getMentionedModules getInferredModules fromData fr
let
pathsModule :: [Module]
pathsModule = case specVersion of
SpecVersion v | v >= makeVersion [0,36,0] -> []
SpecVersion v | v >= Version.makeVersion [0,36,0] -> []
_ -> [pathsModuleFromPackageName packageName_]

removeConditionalsThatAreAlwaysFalse <$> traverseSectionAndConditionals
Expand Down
Loading

0 comments on commit f845bbe

Please sign in to comment.