Skip to content

Commit

Permalink
Add new 'autogen-modules' field
Browse files Browse the repository at this point in the history
Modules that are built automatically at setup, like Paths_PACKAGENAME or others created with a build-type custom, appear on 'other-modules' for the Library, Executable, Test-Suite or Benchmark stanzas or also on 'exposed-modules' for libraries but are not really on the package when distributed. This makes commands like sdist fail because the file is not found, so with this new field modules that appear there are treated the same way as Paths_PACKAGENAME was and there is no need to create complex build hooks.
Just add the module names on 'other-modules' and 'exposed-modules' as always and on the new 'autogen-modules' besides.
  • Loading branch information
fmaste committed Aug 11, 2016
1 parent 6309f82 commit c010867
Show file tree
Hide file tree
Showing 37 changed files with 516 additions and 16 deletions.
16 changes: 16 additions & 0 deletions Cabal/Cabal.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,20 @@ extra-source-files:
tests/PackageTests/AllowOlder/benchmarks/Bench.hs
tests/PackageTests/AllowOlder/src/Foo.hs
tests/PackageTests/AllowOlder/tests/Test.hs
tests/PackageTests/AutogenModules/Package/Dummy.hs
tests/PackageTests/AutogenModules/Package/MyBenchModule.hs
tests/PackageTests/AutogenModules/Package/MyExeModule.hs
tests/PackageTests/AutogenModules/Package/MyLibModule.hs
tests/PackageTests/AutogenModules/Package/MyLibrary.hs
tests/PackageTests/AutogenModules/Package/MyTestModule.hs
tests/PackageTests/AutogenModules/Package/my.cabal
tests/PackageTests/AutogenModules/SrcDist/Dummy.hs
tests/PackageTests/AutogenModules/SrcDist/MyBenchModule.hs
tests/PackageTests/AutogenModules/SrcDist/MyExeModule.hs
tests/PackageTests/AutogenModules/SrcDist/MyLibModule.hs
tests/PackageTests/AutogenModules/SrcDist/MyLibrary.hs
tests/PackageTests/AutogenModules/SrcDist/MyTestModule.hs
tests/PackageTests/AutogenModules/SrcDist/my.cabal
tests/PackageTests/BenchmarkExeV10/Foo.hs
tests/PackageTests/BenchmarkExeV10/benchmarks/bench-Foo.hs
tests/PackageTests/BenchmarkExeV10/my.cabal
Expand Down Expand Up @@ -435,6 +449,8 @@ test-suite package-tests
type: exitcode-stdio-1.0
main-is: PackageTests.hs
other-modules:
PackageTests.AutogenModules.Package.Check
PackageTests.AutogenModules.SrcDist.Check
PackageTests.BenchmarkStanza.Check
PackageTests.TestStanza.Check
PackageTests.DeterministicAr.Check
Expand Down
4 changes: 4 additions & 0 deletions Cabal/Distribution/PackageDescription.hs
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ module Distribution.PackageDescription (
hasPublicLib,
hasLibs,
libModules,
libModulesAutogen,

-- ** Executables
Executable(..),
emptyExecutable,
withExe,
hasExes,
exeModules,
exeModulesAutogen,

-- * Tests
TestSuite(..),
Expand All @@ -54,6 +56,7 @@ module Distribution.PackageDescription (
hasTests,
withTest,
testModules,
testModulesAutogen,

-- * Benchmarks
Benchmark(..),
Expand All @@ -65,6 +68,7 @@ module Distribution.PackageDescription (
hasBenchmarks,
withBenchmark,
benchmarkModules,
benchmarkModulesAutogen,

-- * Build information
BuildInfo(..),
Expand Down
58 changes: 58 additions & 0 deletions Cabal/Distribution/PackageDescription/Check.hs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import Distribution.PackageDescription.Configuration
import Distribution.Compiler
import Distribution.System
import Distribution.License
import Distribution.Simple.BuildPaths (autogenPathsModuleName)
import Distribution.Simple.CCompiler
import Distribution.Simple.Utils hiding (findPackageDesc, notice)
import Distribution.Version
Expand Down Expand Up @@ -245,6 +246,14 @@ checkLibrary pkg lib =
PackageDistInexcusable $
"To use the 'required-signatures' field the package needs to specify "
++ "at least 'cabal-version: >= 1.21'."

-- check that all autogen-modules appear on other-modules or exposed-modules
, check
(not $ and $ map (flip elem (libModules lib)) (libModulesAutogen lib)) $
PackageBuildImpossible $
"An 'autogen-module' is neither on 'exposed-modules' or "
++ "'other-modules'."

]

where
Expand Down Expand Up @@ -282,6 +291,14 @@ checkExecutable pkg exe =
PackageBuildImpossible $
"Duplicate modules in executable '" ++ exeName exe ++ "': "
++ commaSep (map display moduleDuplicates)

-- check that all autogen-modules appear on other-modules
, check
(not $ and $ map (flip elem (exeModules exe)) (exeModulesAutogen exe)) $
PackageBuildImpossible $
"On executable '" ++ exeName exe ++ "' an 'autogen-module' is not "
++ "on 'other-modules'"

]
where
moduleDuplicates = dups (exeModules exe)
Expand Down Expand Up @@ -319,6 +336,16 @@ checkTestSuite pkg test =
PackageDistInexcusable $
"The package uses a C/C++/obj-C source file for the 'main-is' field. "
++ "To use this feature you must specify 'cabal-version: >= 1.18'."

-- check that all autogen-modules appear on other-modules
, check
(not $ and $ map
(flip elem (testModules test))
(testModulesAutogen test)
) $
PackageBuildImpossible $
"On test suite '" ++ testName test ++ "' an 'autogen-module' is not "
++ "on 'other-modules'"
]
where
moduleDuplicates = dups $ testModules test
Expand Down Expand Up @@ -358,6 +385,16 @@ checkBenchmark _pkg bm =
PackageBuildImpossible $
"The 'main-is' field must specify a '.hs' or '.lhs' file "
++ "(even if it is generated by a preprocessor)."

-- check that all autogen-modules appear on other-modules
, check
(not $ and $ map
(flip elem (benchmarkModules bm))
(benchmarkModulesAutogen bm)
) $
PackageBuildImpossible $
"On benchmark '" ++ benchmarkName bm ++ "' an 'autogen-module' is "
++ "not on 'other-modules'"
]
where
moduleDuplicates = dups $ benchmarkModules bm
Expand Down Expand Up @@ -1110,6 +1147,18 @@ checkCabalVersion pkg =
++ "that specifies the dependencies of the Setup.hs script itself. "
++ "The 'setup-depends' field uses the same syntax as 'build-depends', "
++ "so a simple example would be 'setup-depends: base, Cabal'."

, check (specVersion pkg >= Version [1,25] []
&& elem (autogenPathsModuleName pkg) allModuleNames
&& not (elem (autogenPathsModuleName pkg) allModuleNamesAutogen) ) $
PackageDistInexcusable $
"Packages using 'cabal-version: >= 1.25' 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."

]
where
-- Perform a check on packages that use a version of the spec less than
Expand Down Expand Up @@ -1244,6 +1293,15 @@ checkCabalVersion pkg =
map DisableExtension
[MonoPatBinds]

allModuleNames =
(case library pkg of
Nothing -> []
(Just lib) -> libModules lib
)
++ concatMap otherModules (allBuildInfo pkg)

allModuleNamesAutogen = concatMap autogenModules (allBuildInfo pkg)

-- | A variation on the normal 'Text' instance, shows any ()'s in the original
-- textual syntax. We need to show these otherwise it's confusing to users when
-- we complain of their presence but do not pretty print them!
Expand Down
3 changes: 3 additions & 0 deletions Cabal/Distribution/PackageDescription/Parse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ binfoFieldDescrs =
, listFieldWithSep vcat "other-modules"
disp parseModuleNameQ
otherModules (\val binfo -> binfo{otherModules=val})
, listFieldWithSep vcat "autogen-modules"
disp parseModuleNameQ
autogenModules (\val binfo -> binfo{autogenModules=val})
, optsField "ghc-prof-options" GHC
profOptions (\val binfo -> binfo{profOptions=val})
, optsField "ghcjs-prof-options" GHCJS
Expand Down
1 change: 1 addition & 0 deletions Cabal/Distribution/ParseUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ ppField name fielddoc
, "includes"
, "install-includes"
, "other-modules"
, "autogen-modules"
, "depends"
]

Expand Down
2 changes: 1 addition & 1 deletion Cabal/Distribution/Simple/Build.hs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ writeAutogenFiles verbosity pkg lbi clbi = do
createDirectoryIfMissingVerbose verbosity True (autogenComponentModulesDir lbi clbi)

let pathsModulePath = autogenComponentModulesDir lbi clbi
</> ModuleName.toFilePath (autogenModuleName pkg) <.> "hs"
</> ModuleName.toFilePath (autogenPathsModuleName pkg) <.> "hs"
rewriteFile pathsModulePath (Build.PathsModule.generate pkg lbi clbi)

let cppHeaderPath = autogenComponentModulesDir lbi clbi </> cppHeaderName
Expand Down
2 changes: 1 addition & 1 deletion Cabal/Distribution/Simple/Build/PathsModule.hs
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ generate pkg_descr lbi clbi =
_ -> False
supportsRelocatableProgs _ = False

paths_modulename = autogenModuleName pkg_descr
paths_modulename = autogenPathsModuleName pkg_descr

get_prefix_stuff = get_prefix_win32 buildArch

Expand Down
8 changes: 7 additions & 1 deletion Cabal/Distribution/Simple/BuildPaths.hs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module Distribution.Simple.BuildPaths (
autogenComponentModulesDir,

autogenModuleName,
autogenPathsModuleName,
cppHeaderName,
haddockName,

Expand Down Expand Up @@ -87,9 +88,14 @@ autogenComponentModulesDir lbi clbi = componentBuildDir lbi clbi </> "autogen"
cppHeaderName :: String
cppHeaderName = "cabal_macros.h"

{-# DEPRECATED autogenModuleName "Use autogenPathsModuleName instead" #-}
-- |The name of the auto-generated module associated with a package
autogenModuleName :: PackageDescription -> ModuleName
autogenModuleName pkg_descr =
autogenModuleName = autogenPathsModuleName

-- | The name of the auto-generated Paths_* module associated with a package
autogenPathsModuleName :: PackageDescription -> ModuleName
autogenPathsModuleName pkg_descr =
ModuleName.fromString $
"Paths_" ++ map fixchar (display (packageName pkg_descr))
where fixchar '-' = '_'
Expand Down
24 changes: 14 additions & 10 deletions Cabal/Distribution/Simple/SrcDist.hs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ listPackageSources verbosity pkg_descr0 pps = do
maybeExecutable <- listPackageSourcesMaybeExecutable pkg_descr
return (ordinary, maybeExecutable)
where
pkg_descr = filterAutogenModule pkg_descr0
pkg_descr = filterAutogenModules pkg_descr0

-- | List those source files that may be executable (e.g. the configure script).
listPackageSourcesMaybeExecutable :: PackageDescription -> IO [FilePath]
Expand Down Expand Up @@ -259,7 +259,7 @@ prepareTree verbosity pkg_descr0 mb_lbi targetDir pps = do
maybeCreateDefaultSetupScript targetDir

where
pkg_descr = filterAutogenModule pkg_descr0
pkg_descr = filterAutogenModules pkg_descr0

-- | Find the setup script file, if it exists.
findSetupFile :: FilePath -> IO (Maybe FilePath)
Expand Down Expand Up @@ -305,21 +305,24 @@ findIncludeFile (d:ds) f = do
b <- doesFileExist path
if b then return (f,path) else findIncludeFile ds f

-- | Remove the auto-generated module ('Paths_*') from 'exposed-modules' and
-- 'other-modules'.
filterAutogenModule :: PackageDescription -> PackageDescription
filterAutogenModule pkg_descr0 = mapLib filterAutogenModuleLib $
-- | Remove the auto-generated modules (like 'Paths_*') from 'exposed-modules'
-- and 'other-modules'.
filterAutogenModules :: PackageDescription -> PackageDescription
filterAutogenModules pkg_descr0 = mapLib filterAutogenModuleLib $
mapAllBuildInfo filterAutogenModuleBI pkg_descr0
where
mapLib f pkg = pkg { library = fmap f (library pkg)
, subLibraries = map f (subLibraries pkg) }
filterAutogenModuleLib lib = lib {
exposedModules = filter (/=autogenModule) (exposedModules lib)
exposedModules = filter (filterFunction (libBuildInfo lib)) (exposedModules lib)
}
filterAutogenModuleBI bi = bi {
otherModules = filter (/=autogenModule) (otherModules bi)
otherModules = filter (filterFunction bi) (otherModules bi)
}
autogenModule = autogenModuleName pkg_descr0
pathsModule = autogenPathsModuleName pkg_descr0
filterFunction bi = \mn ->
mn /= pathsModule
&& not (elem mn (autogenModules bi))

-- | Prepare a directory tree of source files for a snapshot version.
-- It is expected that the appropriate snapshot version has already been set
Expand Down Expand Up @@ -437,7 +440,8 @@ allSourcesBuildInfo bi pps modules = do
nonEmpty _ f xs = f xs
suffixes = ppSuffixes pps ++ ["hs", "lhs"]
notFound m = die $ "Error: Could not find module: " ++ display m
++ " with any suffix: " ++ show suffixes
++ " with any suffix: " ++ show suffixes ++ ". If the module "
++ "is autogenerated it should be added to 'autogen-modules'."


printPackageProblems :: Verbosity -> PackageDescription -> IO ()
Expand Down
6 changes: 6 additions & 0 deletions Cabal/Distribution/Types/Benchmark.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Distribution.Types.Benchmark (
emptyBenchmark,
benchmarkType,
benchmarkModules,
benchmarkModulesAutogen
) where

import Prelude ()
Expand Down Expand Up @@ -60,3 +61,8 @@ benchmarkType benchmark = case benchmarkInterface benchmark of
-- | Get all the module names from a benchmark.
benchmarkModules :: Benchmark -> [ModuleName]
benchmarkModules benchmark = otherModules (benchmarkBuildInfo benchmark)

-- | Get all the auto generated module names from a benchmark.
-- This are a subset of 'benchmarkModules'.
benchmarkModulesAutogen :: Benchmark -> [ModuleName]
benchmarkModulesAutogen benchmark = autogenModules (benchmarkBuildInfo benchmark)
3 changes: 3 additions & 0 deletions Cabal/Distribution/Types/BuildInfo.hs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ data BuildInfo = BuildInfo {
jsSources :: [FilePath],
hsSourceDirs :: [FilePath], -- ^ where to look for the Haskell module hierarchy
otherModules :: [ModuleName], -- ^ non-exposed or non-main modules
autogenModules :: [ModuleName], -- ^ not present on sdist, Paths_* or user-generated with a custom Setup.hs

defaultLanguage :: Maybe Language,-- ^ language used when not explicitly specified
otherLanguages :: [Language], -- ^ other languages used within the package
Expand Down Expand Up @@ -80,6 +81,7 @@ instance Monoid BuildInfo where
jsSources = [],
hsSourceDirs = [],
otherModules = [],
autogenModules = [],
defaultLanguage = Nothing,
otherLanguages = [],
defaultExtensions = [],
Expand Down Expand Up @@ -114,6 +116,7 @@ instance Semigroup BuildInfo where
jsSources = combineNub jsSources,
hsSourceDirs = combineNub hsSourceDirs,
otherModules = combineNub otherModules,
autogenModules = combineNub autogenModules,
defaultLanguage = combineMby defaultLanguage,
otherLanguages = combineNub otherLanguages,
defaultExtensions = combineNub defaultExtensions,
Expand Down
6 changes: 6 additions & 0 deletions Cabal/Distribution/Types/Executable.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Distribution.Types.Executable (
Executable(..),
emptyExecutable,
exeModules,
exeModulesAutogen
) where

import Prelude ()
Expand Down Expand Up @@ -46,3 +47,8 @@ emptyExecutable = mempty
-- | Get all the module names from an exe
exeModules :: Executable -> [ModuleName]
exeModules exe = otherModules (buildInfo exe)

-- | Get all the auto generated module names from an exe
-- This are a subset of 'exeModules'.
exeModulesAutogen :: Executable -> [ModuleName]
exeModulesAutogen exe = autogenModules (buildInfo exe)
6 changes: 6 additions & 0 deletions Cabal/Distribution/Types/Library.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Distribution.Types.Library (
Library(..),
emptyLibrary,
libModules,
libModulesAutogen
) where

import Prelude ()
Expand Down Expand Up @@ -58,3 +59,8 @@ libModules :: Library -> [ModuleName]
libModules lib = exposedModules lib
++ otherModules (libBuildInfo lib)
++ requiredSignatures lib

-- | Get all the auto generated module names from the library, exposed or not.
-- This are a subset of 'libModules'.
libModulesAutogen :: Library -> [ModuleName]
libModulesAutogen lib = autogenModules (libBuildInfo lib)
6 changes: 6 additions & 0 deletions Cabal/Distribution/Types/TestSuite.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module Distribution.Types.TestSuite (
emptyTestSuite,
testType,
testModules,
testModulesAutogen
) where

import Prelude ()
Expand Down Expand Up @@ -65,3 +66,8 @@ testModules test = (case testInterface test of
TestSuiteLibV09 _ m -> [m]
_ -> [])
++ otherModules (testBuildInfo test)

-- | Get all the auto generated module names from a test suite.
-- This are a subset of 'testModules'.
testModulesAutogen :: TestSuite -> [ModuleName]
testModulesAutogen test = autogenModules (testBuildInfo test)
11 changes: 11 additions & 0 deletions Cabal/changelog
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@
* 'getComponentLocalBuildInfo', 'withComponentsInBuildOrder'
and 'componentsInBuildOrder' are deprecated in favor of a
new interface in "Distribution.Types.LocalBuildInfo".
* New 'autogen-modules' field. Modules that are built automatically at
setup, like Paths_PACKAGENAME or others created with a build-type
custom, appear on 'other-modules' for the Library, Executable,
Test-Suite or Benchmark stanzas or also on 'exposed-modules' for
libraries but are not really on the package when distributed. This
makes commands like sdist fail because the file is not found, so with
this new field modules that appear there are treated the same way as
Paths_PACKAGENAME was and there is no need to create complex build
hooks. Just add the module names on 'other-modules' and
'exposed-modules' as always and on the new 'autogen-modules' besides.
(#3656).

1.24.0.0 Ryan Thomas <ryan@ryant.org> March 2016
* Support GHC 8.
Expand Down
Loading

1 comment on commit c010867

@23Skidoo
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with @hvr and @phadej on this one, having to list Paths_ in autogen-modules is not that onerous, so it's better to avoid special magic.

Please sign in to comment.