Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PackageInfos_ (#3909) #8534

Merged
merged 1 commit into from
Dec 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ library
Distribution.Simple.Bench
Distribution.Simple.Build
Distribution.Simple.Build.Macros
Distribution.Simple.Build.PackageInfoModule
Distribution.Simple.Build.PathsModule
Distribution.Simple.BuildPaths
Distribution.Simple.BuildTarget
Expand Down Expand Up @@ -319,6 +320,7 @@ library
Distribution.GetOpt
Distribution.Lex
Distribution.Simple.Build.Macros.Z
Distribution.Simple.Build.PackageInfoModule.Z
Distribution.Simple.Build.PathsModule.Z
Distribution.Simple.GHC.EnvironmentParser
Distribution.Simple.GHC.Internal
Expand Down
45 changes: 39 additions & 6 deletions Cabal/src/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import Distribution.PackageDescription
import Distribution.PackageDescription.Configuration
import Distribution.Parsec.Warning (PWarning, showPWarning)
import Distribution.Pretty (prettyShow)
import Distribution.Simple.BuildPaths (autogenPathsModuleName)
import Distribution.Simple.BuildPaths (autogenPackageInfoModuleName, autogenPathsModuleName)
import Distribution.Simple.BuildToolDepends
import Distribution.Simple.CCompiler
import Distribution.Simple.Glob
Expand Down Expand Up @@ -220,6 +220,7 @@ data CheckExplanation =
| CVCustomSetup
| CVExpliticDepsCustomSetup
| CVAutogenPaths
| CVAutogenPackageInfo
| GlobNoMatch String String
| GlobExactMatch String String FilePath
| GlobNoDir String String FilePath
Expand All @@ -231,7 +232,8 @@ data CheckExplanation =
| SuspiciousFlagName [String]
| DeclaredUsedFlags (Set FlagName) (Set FlagName)
| NonASCIICustomField [String]
| RebindableClash
| RebindableClashPaths
| RebindableClashPackageInfo
| WErrorUnneeded String
| JUnneeded String
| FDeferTypeErrorsUnneeded String
Expand Down Expand Up @@ -648,6 +650,13 @@ ppExplanation CVAutogenPaths =
++ "the module does not come with the package and is generated on "
++ "setup. Modules built with a custom Setup.hs script also go here "
++ "to ensure that commands like sdist don't fail."
ppExplanation CVAutogenPackageInfo =
"Packages using 'cabal-version: 2.0' and the autogenerated "
++ "module PackageInfo_* must include it in 'autogen-modules' as well as"
++ " 'exposed-modules' and 'other-modules'. This specifies that "
++ "the module does not come with the package and is generated on "
++ "setup. Modules built with a custom Setup.hs script also go here "
++ "to ensure that commands like sdist don't fail."
ppExplanation (GlobNoMatch field glob) =
"In '" ++ field ++ "': the pattern '" ++ glob ++ "' does not"
++ " match any files."
Expand Down Expand Up @@ -700,12 +709,18 @@ ppExplanation (NonASCIICustomField nonAsciiXFields) =
"Non ascii custom fields: " ++ unwords nonAsciiXFields ++ ". "
++ "For better compatibility, custom field names "
++ "shouldn't contain non-ascii characters."
ppExplanation RebindableClash =
ppExplanation RebindableClashPaths =
"Packages using RebindableSyntax with OverloadedStrings or"
++ " OverloadedLists in default-extensions, in conjunction with the"
++ " autogenerated module Paths_*, are known to cause compile failures"
++ " with Cabal < 2.2. To use these default-extensions with a Paths_*"
++ " autogen module, specify at least 'cabal-version: 2.2'."
ppExplanation RebindableClashPackageInfo =
"Packages using RebindableSyntax with OverloadedStrings or"
++ " OverloadedLists in default-extensions, in conjunction with the"
++ " autogenerated module PackageInfo_*, are known to cause compile failures"
++ " with Cabal < 2.2. To use these default-extensions with a PackageInfo_*"
++ " autogen module, specify at least 'cabal-version: 2.2'."
ppExplanation (WErrorUnneeded fieldName) = addConditionalExp $
"'" ++ fieldName ++ ": -Werror' makes the package easy to "
++ "break with future GHC versions because new GHC versions often "
Expand Down Expand Up @@ -851,6 +866,7 @@ checkPackage gpkg mpkg =
++ checkUnusedFlags gpkg
++ checkUnicodeXFields gpkg
++ checkPathsModuleExtensions pkg
++ checkPackageInfoModuleExtensions pkg
++ checkSetupVersions gpkg
++ checkDuplicateModules gpkg
where
Expand Down Expand Up @@ -1749,6 +1765,11 @@ checkCabalVersion pkg =
&& not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $
PackageDistInexcusable CVAutogenPaths

, check (specVersion pkg >= CabalSpecV2_0
&& elem (autogenPackageInfoModuleName pkg) allModuleNames
&& not (elem (autogenPackageInfoModuleName pkg) allModuleNamesAutogen) ) $
PackageDistInexcusable CVAutogenPackageInfo

]
where
-- Perform a check on packages that use a version of the spec less than
Expand Down Expand Up @@ -1925,13 +1946,25 @@ checkUnicodeXFields gpd

-- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build.
checkPathsModuleExtensions :: PackageDescription -> [PackageCheck]
checkPathsModuleExtensions pd
checkPathsModuleExtensions = checkAutogenModuleExtensions autogenPathsModuleName RebindableClashPaths

-- | cabal-version <2.2 + PackageInfo_module + default-extensions: doesn't build.
checkPackageInfoModuleExtensions :: PackageDescription -> [PackageCheck]
checkPackageInfoModuleExtensions = checkAutogenModuleExtensions autogenPackageInfoModuleName RebindableClashPackageInfo

-- | cabal-version <2.2 + *_module + default-extensions: doesn't build.
checkAutogenModuleExtensions ::
(PackageDescription -> ModuleName) ->
CheckExplanation ->
PackageDescription ->
[PackageCheck]
checkAutogenModuleExtensions autogenModuleName rebindableClashExplanation pd
| specVersion pd >= CabalSpecV2_2 = []
| any checkBI (allBuildInfo pd) || any checkLib (allLibraries pd)
= return (PackageBuildImpossible RebindableClash)
= return (PackageBuildImpossible rebindableClashExplanation)
| otherwise = []
where
mn = autogenPathsModuleName pd
mn = autogenModuleName pd

checkLib :: Library -> Bool
checkLib l = mn `elem` exposedModules l && checkExts (l ^. L.defaultExtensions)
Expand Down
10 changes: 9 additions & 1 deletion Cabal/src/Distribution/Simple/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import qualified Distribution.Simple.HaskellSuite as HaskellSuite
import qualified Distribution.Simple.PackageIndex as Index

import Distribution.Simple.Build.Macros (generateCabalMacrosHeader)
import Distribution.Simple.Build.PackageInfoModule (generatePackageInfoModule)
import Distribution.Simple.Build.PathsModule (generatePathsModule)
import qualified Distribution.Simple.Program.HcPkg as HcPkg

Expand Down Expand Up @@ -773,7 +774,7 @@ componentInitialBuildSteps _distPref pkg_descr lbi clbi verbosity = do

writeAutogenFiles verbosity pkg_descr lbi clbi

-- | Generate and write out the Paths_<pkg>.hs and cabal_macros.h files
-- | Generate and write out the Paths_<pkg>.hs, PackageInfo_<pkg>.hs, and cabal_macros.h files
--
writeAutogenFiles :: Verbosity
-> PackageDescription
Expand All @@ -790,6 +791,13 @@ writeAutogenFiles verbosity pkg lbi clbi = do
createDirectoryIfMissingVerbose verbosity True pathsModuleDir
rewriteFileEx verbosity pathsModulePath (generatePathsModule pkg lbi clbi)

let packageInfoModulePath = autogenComponentModulesDir lbi clbi
</> ModuleName.toFilePath (autogenPackageInfoModuleName pkg) <.> "hs"
packageInfoModuleDir = takeDirectory packageInfoModulePath
-- Ensure that the directory exists!
createDirectoryIfMissingVerbose verbosity True packageInfoModuleDir
rewriteFileEx verbosity packageInfoModulePath (generatePackageInfoModule pkg lbi)

--TODO: document what we're doing here, and move it to its own function
case clbi of
LibComponentLocalBuildInfo { componentInstantiatedWith = insts } ->
Expand Down
56 changes: 56 additions & 0 deletions Cabal/src/Distribution/Simple/Build/PackageInfoModule.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-----------------------------------------------------------------------------
-- |
-- Module : Distribution.Simple.Build.PackageInfoModule
-- Copyright :
--
-- Maintainer : [email protected]
-- Portability : portable
--
-- Generating the PackageInfo_pkgname module.
--
-- This is a module that Cabal generates for the benefit of packages. It
-- enables them to find their package informations.
--
module Distribution.Simple.Build.PackageInfoModule (
generatePackageInfoModule
) where

import Distribution.Compat.Prelude
import Prelude ()

import Distribution.Package
import Distribution.PackageDescription
import Distribution.Simple.Compiler
import Distribution.Simple.LocalBuildInfo
import Distribution.Utils.ShortText
import Distribution.Version

import qualified Distribution.Simple.Build.PackageInfoModule.Z as Z

-- ------------------------------------------------------------
-- * Building Paths_<pkg>.hs
-- ------------------------------------------------------------

generatePackageInfoModule :: PackageDescription -> LocalBuildInfo -> String
generatePackageInfoModule pkg_descr lbi = Z.render Z.Z
{ Z.zPackageName = showPkgName $ packageName pkg_descr
, Z.zVersionDigits = show $ versionNumbers $ packageVersion pkg_descr
, Z.zSynopsis = fromShortText $ synopsis pkg_descr
, Z.zCopyright = fromShortText $ copyright pkg_descr
, Z.zHomepage = fromShortText $ homepage pkg_descr
, Z.zSupportsNoRebindableSyntax = supports_rebindable_syntax
}
where
supports_rebindable_syntax = ghc_newer_than (mkVersion [7,0,1])

ghc_newer_than minVersion =
case compilerCompatVersion GHC (compiler lbi) of
Nothing -> False
Just version -> version `withinRange` orLaterVersion minVersion

showPkgName :: PackageName -> String
showPkgName = map fixchar . unPackageName

fixchar :: Char -> Char
fixchar '-' = '_'
fixchar c = c
60 changes: 60 additions & 0 deletions Cabal/src/Distribution/Simple/Build/PackageInfoModule/Z.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{-# LANGUAGE DeriveGeneric #-}

module Distribution.Simple.Build.PackageInfoModule.Z (render, Z (..)) where

import Distribution.ZinzaPrelude

data Z = Z
{ zPackageName :: String,
zVersionDigits :: String,
zSynopsis :: String,
zCopyright :: String,
zHomepage :: String,
zSupportsNoRebindableSyntax :: Bool
}
deriving (Generic)

render :: Z -> String
render z_root = execWriter $ do
if (zSupportsNoRebindableSyntax z_root)
then do
tell "{-# LANGUAGE NoRebindableSyntax #-}\n"
return ()
else do
return ()
tell "{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}\n"
tell "{-# OPTIONS_GHC -w #-}\n"
tell "module PackageInfo_"
tell (zPackageName z_root)
tell " (\n"
tell " name,\n"
tell " version,\n"
tell " synopsis,\n"
tell " copyright,\n"
tell " homepage,\n"
tell " ) where\n"
tell "\n"
tell "import Data.Version (Version(..))\n"
tell "import Prelude\n"
tell "\n"
tell "name :: String\n"
tell "name = "
tell (show $ zPackageName z_root)
tell "\n"
tell "version :: Version\n"
tell "version = Version "
tell (zVersionDigits z_root)
tell " []\n"
tell "\n"
tell "synopsis :: String\n"
tell "synopsis = "
tell (show $ zSynopsis z_root)
tell "\n"
tell "copyright :: String\n"
tell "copyright = "
tell (show $ zCopyright z_root)
tell "\n"
tell "homepage :: String\n"
tell "homepage = "
tell (show $ zHomepage z_root)
tell "\n"
9 changes: 9 additions & 0 deletions Cabal/src/Distribution/Simple/BuildPaths.hs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Distribution.Simple.BuildPaths (
autogenComponentModulesDir,

autogenPathsModuleName,
autogenPackageInfoModuleName,
cppHeaderName,
haddockName,

Expand Down Expand Up @@ -105,6 +106,14 @@ autogenPathsModuleName pkg_descr =
where fixchar '-' = '_'
fixchar c = c

-- | The name of the auto-generated PackageInfo_* module associated with a package
autogenPackageInfoModuleName :: PackageDescription -> ModuleName
autogenPackageInfoModuleName pkg_descr =
ModuleName.fromString $
"PackageInfo_" ++ map fixchar (prettyShow (packageName pkg_descr))
where fixchar '-' = '_'
fixchar c = c

haddockName :: PackageDescription -> FilePath
haddockName pkg_descr = prettyShow (packageName pkg_descr) <.> "haddock"

Expand Down
2 changes: 2 additions & 0 deletions Cabal/src/Distribution/Simple/SrcDist.hs
Original file line number Diff line number Diff line change
Expand Up @@ -361,8 +361,10 @@ filterAutogenModules pkg_descr0 = mapLib filterAutogenModuleLib $
otherModules = filter (filterFunction bi) (otherModules bi)
}
pathsModule = autogenPathsModuleName pkg_descr0
packageInfoModule = autogenPackageInfoModuleName pkg_descr0
filterFunction bi = \mn ->
mn /= pathsModule
&& mn /= packageInfoModule
&& not (mn `elem` autogenModules bi)

-- | Prepare a directory tree of source files for a snapshot version.
Expand Down
4 changes: 4 additions & 0 deletions cabal-testsuite/PackageTests/AutogenModules/Package/my.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Library
build-depends: base
exposed-modules:
MyLibrary
PackageInfo_AutogenModules
Paths_AutogenModules
MyLibHelperModule
other-modules:
Expand All @@ -30,6 +31,7 @@ Executable Exe
build-depends: base
other-modules:
MyExeModule
PackageInfo_AutogenModules
Paths_AutogenModules
MyExeHelperModule
autogen-modules:
Expand All @@ -42,6 +44,7 @@ Test-Suite Test
build-depends: base
other-modules:
MyTestModule
PackageInfo_AutogenModules
Paths_AutogenModules
MyTestHelperModule
autogen-modules:
Expand All @@ -54,6 +57,7 @@ Benchmark Bench
build-depends: base
other-modules:
MyBenchModule
PackageInfo_AutogenModules
Paths_AutogenModules
MyBenchHelperModule
autogen-modules:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ On executable 'Exe' an 'autogen-module' is not on 'other-modules'
On test suite 'Test' an 'autogen-module' is not on 'other-modules'
On benchmark 'Bench' an 'autogen-module' is not on 'other-modules'
Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
Packages using 'cabal-version: 2.0' and the autogenerated module PackageInfo_* must include it in 'autogen-modules' as well as 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
The filename './my.cabal' does not match package name (expected: 'AutogenModules.cabal')
Note: the public hackage server would reject this package.
Building source dist for AutogenModules-0.1...
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ On executable 'Exe' an 'autogen-module' is not on 'other-modules'
On test suite 'Test' an 'autogen-module' is not on 'other-modules'
On benchmark 'Bench' an 'autogen-module' is not on 'other-modules'
Packages using 'cabal-version: 2.0' and the autogenerated module Paths_* must include it also on the 'autogen-modules' field besides 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
Packages using 'cabal-version: 2.0' and the autogenerated module PackageInfo_* must include it in 'autogen-modules' as well as 'exposed-modules' and 'other-modules'. This specifies that the module does not come with the package and is generated on setup. Modules built with a custom Setup.hs script also go here to ensure that commands like sdist don't fail.
The filename './my.cabal' does not match package name (expected: 'AutogenModules.cabal')
Note: the public hackage server would reject this package.
Building source dist for AutogenModules-0.1...
Expand Down
Loading