1 -----------------------------------------------------------------------------
3 -- Module : Distribution.PackageDescription.Check
4 -- Copyright : Lennart Kolmodin 2008
7 -- Maintainer : cabal-devel@haskell.org
8 -- Portability : portable
10 -- This has code for checking for various problems in packages. There is one
11 -- set of checks that just looks at a 'PackageDescription' in isolation and
12 -- another set of checks that also looks at files in the package. Some of the
13 -- checks are basic sanity checks, others are portability standards that we'd
14 -- like to encourage. There is a 'PackageCheck' type that distinguishes the
15 -- different kinds of checks so we can see which ones are appropriate to report
16 -- in different situations. This code gets used when configuring a package when
17 -- we consider only basic problems. The higher standard is used when
18 -- preparing a source tarball and by Hackage when uploading new packages. The
19 -- reason for this is that we want to hold packages that are expected to be
20 -- distributed to a higher standard than packages that are only ever expected
21 -- to be used on the author's own environment.
23 module Distribution
.PackageDescription
.Check
(
28 checkConfiguredPackage
,
32 -- ** Checking package contents
35 CheckPackageContentOps
(..),
36 checkPackageFileNames
,
39 import Distribution
.Compat
.Prelude
42 import Data
.List
(group)
43 import Distribution
.CabalSpecVersion
44 import Distribution
.Compat
.Lens
45 import Distribution
.Compiler
46 import Distribution
.License
47 import Distribution
.ModuleName
(ModuleName
)
48 import Distribution
.Package
49 import Distribution
.PackageDescription
50 import Distribution
.PackageDescription
.Configuration
51 import Distribution
.Parsec
.Warning
(PWarning
, showPWarning
)
52 import Distribution
.Pretty
(prettyShow
)
53 import Distribution
.Simple
.BuildPaths
(autogenPathsModuleName
)
54 import Distribution
.Simple
.BuildToolDepends
55 import Distribution
.Simple
.CCompiler
56 import Distribution
.Simple
.Glob
57 import Distribution
.Simple
.Utils
hiding (findPackageDesc
, notice
)
58 import Distribution
.System
59 import Distribution
.Types
.ComponentRequestedSpec
60 import Distribution
.Types
.PackageName
.Magic
61 import Distribution
.Utils
.Generic
(isAscii)
62 import Distribution
.Verbosity
63 import Distribution
.Version
64 import Distribution
.Utils
.Path
65 import Language
.Haskell
.Extension
66 import System
.FilePath
67 (splitDirectories
, splitExtension
, splitPath
, takeExtension
, takeFileName
, (<.>), (</>))
69 import qualified Data
.ByteString
.Lazy
as BS
70 import qualified Data
.Map
as Map
71 import qualified Distribution
.Compat
.DList
as DList
72 import qualified Distribution
.SPDX
as SPDX
73 import qualified System
.Directory
as System
75 import qualified System
.Directory
(getDirectoryContents)
76 import qualified System
.FilePath.Windows
as FilePath.Windows
(isValid
)
78 import qualified Data
.Set
as Set
79 import qualified Distribution
.Utils
.ShortText
as ShortText
81 import qualified Distribution
.Types
.BuildInfo
.Lens
as L
82 import qualified Distribution
.Types
.GenericPackageDescription
.Lens
as L
83 import qualified Distribution
.Types
.PackageDescription
.Lens
as L
86 -- >>> import Control.Arrow ((&&&))
88 -- ------------------------------------------------------------
90 -- ------------------------------------------------------------
92 -- | Which stanza does `CheckExplanation` refer to?
94 data CEType
= CETLibrary | CETExecutable | CETTest | CETBenchmark
95 deriving (Eq
, Ord
, Show)
97 -- | Pretty printing `CEType`.
99 ppCE
:: CEType
-> String
100 ppCE CETLibrary
= "library"
101 ppCE CETExecutable
= "executable"
102 ppCE CETTest
= "test suite"
103 ppCE CETBenchmark
= "benchmark"
105 -- | Which field does `CheckExplanation` refer to?
107 data CEField
= CEFCategory | CEFMaintainer | CEFSynopsis
108 | CEFDescription | CEFSynOrDesc
109 deriving (Eq
, Ord
, Show)
111 -- | Pretty printing `CEField`.
113 ppCEField
:: CEField
-> String
114 ppCEField CEFCategory
= "category"
115 ppCEField CEFMaintainer
= "maintainer"
116 ppCEField CEFSynopsis
= "synopsis"
117 ppCEField CEFDescription
= "description"
118 ppCEField CEFSynOrDesc
= "synopsis' or 'description"
120 -- | Explanations of 'PackageCheck`'s errors/warnings.
122 data CheckExplanation
=
123 ParseWarning
FilePath PWarning
128 | DuplicateSections
[UnqualComponentName
]
129 | IllegalLibraryName PackageDescription
130 | NoModulesExposed Library
133 | AutogenIncludesNotIncluded
134 | NoMainIs Executable
137 | AutogenNoOther CEType UnqualComponentName
138 | AutogenIncludesNotIncludedExe
139 | TestsuiteTypeNotKnown TestType
140 | TestsuiteNotSupported TestType
141 | BenchmarkTypeNotKnown BenchmarkType
142 | BenchmarkNotSupported BenchmarkType
144 | InvalidNameWin PackageDescription
148 | UnknownCompilers
[String]
149 | UnknownLanguages
[String]
150 | UnknownExtensions
[String]
151 | LanguagesAsExtension
[String]
152 | DeprecatedExtensions
[(Extension
, Maybe Extension
)]
153 | MissingField CEField
156 | InvalidTestWith
[Dependency
]
157 | ImpossibleInternalDep
[Dependency
]
158 | ImpossibleInternalExe
[ExeDependency
]
159 | MissingInternalExe
[ExeDependency
]
162 | AllRightsReservedLicense
163 | LicenseMessParse PackageDescription
164 | UnrecognisedLicense
String
166 | UnknownLicenseVersion License
[Version
]
168 | UnrecognisedSourceRepo
String
174 | SubdirGoodRelPath
String
186 | OptSplitSections
String
187 | OptSplitObjs
String
193 | COptONumber
String String
195 | OptAlternatives
String String [(String, String)]
196 | RelativeOutside
String FilePath
197 | AbsolutePath
String FilePath
198 | BadRelativePAth
String FilePath String
199 | DistPoint
(Maybe String) FilePath
200 | GlobSyntaxError
String String
201 | InvalidOnWin
[FilePath]
202 | FilePathTooLong
FilePath
203 | FilePathNameTooLong
FilePath
204 | FilePathSplitTooLong
FilePath
208 | CVDefaultLanguageComponent
213 | CVExtraFrameworkDirs
214 | CVDefaultExtensions
215 | CVExtensionsDeprecated
217 | CVExtraDynamic
[[String]]
220 | CVExtensions CabalSpecVersion
[Extension
]
222 | CVExpliticDepsCustomSetup
224 | GlobNoMatch
String String
225 | GlobExactMatch
String String FilePath
226 | GlobNoDir
String String FilePath
228 | UnknownArch
[String]
229 | UnknownCompiler
[String]
231 | SuspiciousFlagName
[String]
232 | DeclaredUsedFlags
(Set FlagName
) (Set FlagName
)
233 | NonASCIICustomField
[String]
235 | WErrorUnneeded
String
237 | FDeferTypeErrorsUnneeded
String
238 | DynamicUnneeded
String
239 | ProfilingUnneeded
String
240 | UpperBoundSetup
String
241 | DuplicateModule
String [ModuleName
]
242 | PotentialDupModule
String [ModuleName
]
244 | NotPackageName
FilePath String
247 | UnknownFile
String (SymbolicPath PackageDir LicenseFile
)
249 | MissingConfigureScript
250 | UnknownDirectory
String FilePath
251 | MissingSourceControl
252 deriving (Eq
, Ord
, Show)
254 -- | Wraps `ParseWarning` into `PackageCheck`.
256 wrapParseWarning
:: FilePath -> PWarning
-> PackageCheck
257 wrapParseWarning fp pw
= PackageDistSuspicious
(ParseWarning fp pw
)
258 -- TODO: as Jul 2022 there is no severity indication attached PWarnType.
259 -- Once that is added, we can output something more appropriate
260 -- than PackageDistSuspicious for every parse warning.
261 -- (see: Cabal-syntax/src/Distribution/Parsec/Warning.hs)
263 -- | Pretty printing `CheckExplanation`.
265 ppExplanation
:: CheckExplanation
-> String
266 ppExplanation
(ParseWarning fp pp
) = showPWarning fp pp
267 ppExplanation NoNameField
= "No 'name' field."
268 ppExplanation NoVersionField
= "No 'version' field."
269 ppExplanation NoTarget
=
270 "No executables, libraries, tests, or benchmarks found. Nothing to do."
271 ppExplanation UnnamedInternal
=
272 "Found one or more unnamed internal libraries. Only the non-internal"
273 ++ " library can have the same name as the package."
274 ppExplanation
(DuplicateSections duplicateNames
) =
275 "Duplicate sections: "
276 ++ commaSep
(map unUnqualComponentName duplicateNames
)
277 ++ ". The name of every library, executable, test suite,"
278 ++ " and benchmark section in the package must be unique."
279 ppExplanation
(IllegalLibraryName pkg
) =
280 "Illegal internal library name "
281 ++ prettyShow
(packageName pkg
)
282 ++ ". Internal libraries cannot have the same name as the package."
283 ++ " Maybe you wanted a non-internal library?"
284 ++ " If so, rewrite the section stanza"
285 ++ " from 'library: '" ++ prettyShow
(packageName pkg
)
287 ppExplanation
(NoModulesExposed lib
) =
288 showLibraryName
(libName lib
) ++ " does not expose any modules"
289 ppExplanation SignaturesCabal2
=
290 "To use the 'signatures' field the package needs to specify "
291 ++ "at least 'cabal-version: 2.0'."
292 ppExplanation AutogenNotExposed
=
293 "An 'autogen-module' is neither on 'exposed-modules' or 'other-modules'."
294 ppExplanation AutogenIncludesNotIncluded
=
295 "An include in 'autogen-includes' is neither in 'includes' or "
296 ++ "'install-includes'."
297 ppExplanation
(NoMainIs exe
) =
298 "No 'main-is' field found for executable " ++ prettyShow
(exeName exe
)
299 ppExplanation NoHsLhsMain
=
300 "The 'main-is' field must specify a '.hs' or '.lhs' file "
301 ++ "(even if it is generated by a preprocessor), "
302 ++ "or it may specify a C/C++/obj-C source file."
303 ppExplanation MainCCabal1_18
=
304 "The package uses a C/C++/obj-C source file for the 'main-is' field. "
305 ++ "To use this feature you need to specify 'cabal-version: 1.18' or"
307 ppExplanation
(AutogenNoOther ct ucn
) =
308 "On " ++ ppCE ct
++ " '" ++ prettyShow ucn
++ "' an 'autogen-module'"
309 ++ " is not on 'other-modules'"
310 ppExplanation AutogenIncludesNotIncludedExe
=
311 "An include in 'autogen-includes' is not in 'includes'."
312 ppExplanation
(TestsuiteTypeNotKnown tt
) =
313 quote
(prettyShow tt
) ++ " is not a known type of test suite. "
314 ++ "Either remove the 'type' field or use a known type. "
315 ++ "The known test suite types are: "
316 ++ commaSep
(map prettyShow knownTestTypes
)
317 ppExplanation
(TestsuiteNotSupported tt
) =
318 quote
(prettyShow tt
) ++ " is not a supported test suite version. "
319 ++ "Either remove the 'type' field or use a known type. "
320 ++ "The known test suite types are: "
321 ++ commaSep
(map prettyShow knownTestTypes
)
322 ppExplanation
(BenchmarkTypeNotKnown tt
) =
323 quote
(prettyShow tt
) ++ " is not a known type of benchmark. "
324 ++ "Either remove the 'type' field or use a known type. "
325 ++ "The known benchmark types are: "
326 ++ commaSep
(map prettyShow knownBenchmarkTypes
)
327 ppExplanation
(BenchmarkNotSupported tt
) =
328 quote
(prettyShow tt
) ++ " is not a supported benchmark version. "
329 ++ "Either remove the 'type' field or use a known type. "
330 ++ "The known benchmark types are: "
331 ++ commaSep
(map prettyShow knownBenchmarkTypes
)
332 ppExplanation NoHsLhsMainBench
=
333 "The 'main-is' field must specify a '.hs' or '.lhs' file "
334 ++ "(even if it is generated by a preprocessor)."
335 ppExplanation
(InvalidNameWin pkg
) =
336 "The package name '" ++ prettyShow
(packageName pkg
) ++ "' is "
337 ++ "invalid on Windows. Many tools need to convert package names to "
338 ++ "file names so using this name would cause problems."
339 ppExplanation ZPrefix
=
340 "Package names with the prefix 'z-' are reserved by Cabal and "
342 ppExplanation NoBuildType
=
343 "No 'build-type' specified. If you do not need a custom Setup.hs or "
344 ++ "./configure script then use 'build-type: Simple'."
345 ppExplanation NoCustomSetup
=
346 "Ignoring the 'custom-setup' section because the 'build-type' is "
347 ++ "not 'Custom'. Use 'build-type: Custom' if you need to use a "
348 ++ "custom Setup.hs script."
349 ppExplanation
(UnknownCompilers unknownCompilers
) =
350 "Unknown compiler " ++ commaSep
(map quote unknownCompilers
)
351 ++ " in 'tested-with' field."
352 ppExplanation
(UnknownLanguages unknownLanguages
) =
353 "Unknown languages: " ++ commaSep unknownLanguages
354 ppExplanation
(UnknownExtensions unknownExtensions
) =
355 "Unknown extensions: " ++ commaSep unknownExtensions
356 ppExplanation
(LanguagesAsExtension languagesUsedAsExtensions
) =
357 "Languages listed as extensions: "
358 ++ commaSep languagesUsedAsExtensions
359 ++ ". Languages must be specified in either the 'default-language' "
360 ++ " or the 'other-languages' field."
361 ppExplanation
(DeprecatedExtensions ourDeprecatedExtensions
) =
362 "Deprecated extensions: "
363 ++ commaSep
(map (quote
. prettyShow
. fst) ourDeprecatedExtensions
)
365 [ "Instead of '" ++ prettyShow ext
366 ++ "' use '" ++ prettyShow replacement
++ "'."
367 |
(ext
, Just replacement
) <- ourDeprecatedExtensions
]
368 ppExplanation
(MissingField cef
) =
369 "No '" ++ ppCEField cef
++ "' field."
370 ppExplanation SynopsisTooLong
=
371 "The 'synopsis' field is rather long (max 80 chars is recommended)."
372 ppExplanation ShortDesc
=
373 "The 'description' field should be longer than the 'synopsis' field. "
374 ++ "It's useful to provide an informative 'description' to allow "
375 ++ "Haskell programmers who have never heard about your package to "
376 ++ "understand the purpose of your package. "
377 ++ "The 'description' field content is typically shown by tooling "
378 ++ "(e.g. 'cabal info', Haddock, Hackage) below the 'synopsis' which "
379 ++ "serves as a headline. "
380 ++ "Please refer to <https://cabal.readthedocs.io/en/stable/"
381 ++ "cabal-package.html#package-properties> for more details."
382 ppExplanation
(InvalidTestWith testedWithImpossibleRanges
) =
383 "Invalid 'tested-with' version range: "
384 ++ commaSep
(map prettyShow testedWithImpossibleRanges
)
385 ++ ". To indicate that you have tested a package with multiple "
386 ++ "different versions of the same compiler use multiple entries, "
387 ++ "for example 'tested-with: GHC==6.10.4, GHC==6.12.3' and not "
388 ++ "'tested-with: GHC==6.10.4 && ==6.12.3'."
389 ppExplanation
(ImpossibleInternalDep depInternalLibWithImpossibleVersion
) =
390 "The package has an impossible version range for a dependency on an "
391 ++ "internal library: "
392 ++ commaSep
(map prettyShow depInternalLibWithImpossibleVersion
)
393 ++ ". This version range does not include the current package, and must "
394 ++ "be removed as the current package's library will always be used."
395 ppExplanation
(ImpossibleInternalExe depInternalExecWithImpossibleVersion
) =
396 "The package has an impossible version range for a dependency on an "
397 ++ "internal executable: "
398 ++ commaSep
(map prettyShow depInternalExecWithImpossibleVersion
)
399 ++ ". This version range does not include the current package, and must "
400 ++ "be removed as the current package's executable will always be used."
401 ppExplanation
(MissingInternalExe depInternalExeWithImpossibleVersion
) =
402 "The package depends on a missing internal executable: "
403 ++ commaSep
(map prettyShow depInternalExeWithImpossibleVersion
)
404 ppExplanation NONELicense
= "The 'license' field is missing or is NONE."
405 ppExplanation NoLicense
= "The 'license' field is missing."
406 ppExplanation AllRightsReservedLicense
=
407 "The 'license' is AllRightsReserved. Is that really what you want?"
408 ppExplanation
(LicenseMessParse pkg
) =
409 "Unfortunately the license " ++ quote
(prettyShow
(license pkg
))
410 ++ " messes up the parser in earlier Cabal versions so you need to "
411 ++ "specify 'cabal-version: >= 1.4'. Alternatively if you require "
412 ++ "compatibility with earlier Cabal versions then use 'OtherLicense'."
413 ppExplanation
(UnrecognisedLicense l
) =
414 quote
("license: " ++ l
) ++ " is not a recognised license. The "
415 ++ "known licenses are: " ++ commaSep
(map prettyShow knownLicenses
)
416 ppExplanation UncommonBSD4
=
417 "Using 'license: BSD4' is almost always a misunderstanding. 'BSD4' "
418 ++ "refers to the old 4-clause BSD license with the advertising "
419 ++ "clause. 'BSD3' refers the new 3-clause BSD license."
420 ppExplanation
(UnknownLicenseVersion lic known
) =
421 "'license: " ++ prettyShow lic
++ "' is not a known "
422 ++ "version of that license. The known versions are "
423 ++ commaSep
(map prettyShow known
)
424 ++ ". If this is not a mistake and you think it should be a known "
425 ++ "version then please file a ticket."
426 ppExplanation NoLicenseFile
= "A 'license-file' is not specified."
427 ppExplanation
(UnrecognisedSourceRepo kind
) =
428 quote kind
++ " is not a recognised kind of source-repository. "
429 ++ "The repo kind is usually 'head' or 'this'"
430 ppExplanation MissingType
=
431 "The source-repository 'type' is a required field."
432 ppExplanation MissingLocation
=
433 "The source-repository 'location' is a required field."
434 ppExplanation MissingModule
=
435 "For a CVS source-repository, the 'module' is a required field."
436 ppExplanation MissingTag
=
437 "For the 'this' kind of source-repository, the 'tag' is a required "
438 ++ "field. It should specify the tag corresponding to this version "
439 ++ "or release of the package."
440 ppExplanation SubdirRelPath
=
441 "The 'subdir' field of a source-repository must be a relative path."
442 ppExplanation
(SubdirGoodRelPath err
) =
443 "The 'subdir' field of a source-repository is not a good relative path: "
445 ppExplanation
(OptFasm fieldName
) =
446 "'" ++ fieldName
++ ": -fasm' is unnecessary and will not work on CPU "
447 ++ "architectures other than x86, x86-64, ppc or sparc."
448 ppExplanation
(OptViaC fieldName
) =
449 "'" ++ fieldName
++": -fvia-C' is usually unnecessary. If your package "
450 ++ "needs -via-C for correctness rather than performance then it "
451 ++ "is using the FFI incorrectly and will probably not work with GHC "
453 ppExplanation
(OptHpc fieldName
) =
454 "'" ++ fieldName
++ ": -fhpc' is not necessary. Use the configure flag "
455 ++ " --enable-coverage instead."
456 ppExplanation
(OptProf fieldName
) =
457 "'" ++ fieldName
++ ": -prof' is not necessary and will lead to problems "
458 ++ "when used on a library. Use the configure flag "
459 ++ "--enable-library-profiling and/or --enable-profiling."
460 ppExplanation
(OptO fieldName
) =
461 "'" ++ fieldName
++ ": -o' is not needed. "
462 ++ "The output files are named automatically."
463 ppExplanation
(OptHide fieldName
) =
464 "'" ++ fieldName
++ ": -hide-package' is never needed. "
465 ++ "Cabal hides all packages."
466 ppExplanation
(OptMake fieldName
) =
468 ++ ": --make' is never needed. Cabal uses this automatically."
469 ppExplanation
(OptMain fieldName
) =
470 "'" ++ fieldName
++ ": -main-is' is not portable."
471 ppExplanation
(OptONot fieldName
) =
472 "'" ++ fieldName
++ ": -O0' is not needed. "
473 ++ "Use the --disable-optimization configure flag."
474 ppExplanation
(OptOOne fieldName
) =
475 "'" ++ fieldName
++ ": -O' is not needed. "
476 ++ "Cabal automatically adds the '-O' flag. "
477 ++ "Setting it yourself interferes with the --disable-optimization flag."
478 ppExplanation
(OptOTwo fieldName
) =
479 "'" ++ fieldName
++ ": -O2' is rarely needed. "
480 ++ "Check that it is giving a real benefit "
481 ++ "and not just imposing longer compile times on your users."
482 ppExplanation
(OptSplitSections fieldName
) =
483 "'" ++ fieldName
++ ": -split-sections' is not needed. "
484 ++ "Use the --enable-split-sections configure flag."
485 ppExplanation
(OptSplitObjs fieldName
) =
486 "'" ++ fieldName
++ ": -split-objs' is not needed. "
487 ++ "Use the --enable-split-objs configure flag."
488 ppExplanation
(OptWls fieldName
) =
489 "'" ++ fieldName
++ ": -optl-Wl,-s' is not needed and is not portable to"
490 ++ " all operating systems. Cabal 1.4 and later automatically strip"
491 ++ " executables. Cabal also has a flag --disable-executable-stripping"
492 ++ " which is necessary when building packages for some Linux"
493 ++ " distributions and using '-optl-Wl,-s' prevents that from working."
494 ppExplanation
(OptExts fieldName
) =
495 "Instead of '" ++ fieldName
++ ": -fglasgow-exts' it is preferable to use "
496 ++ "the 'extensions' field."
497 ppExplanation
(OptThreaded fieldName
) =
498 "'" ++ fieldName
++ ": -threaded' has no effect for libraries. It should "
499 ++ "only be used for executables."
500 ppExplanation
(OptRts fieldName
) =
501 "'" ++ fieldName
++ ": -rtsopts' has no effect for libraries. It should "
502 ++ "only be used for executables."
503 ppExplanation
(OptWithRts fieldName
) =
504 "'" ++ fieldName
++ ": -with-rtsopts' has no effect for libraries. It "
505 ++ "should only be used for executables."
506 ppExplanation
(COptONumber prefix label
) =
507 "'" ++ prefix
++": -O[n]' is generally not needed. When building with "
508 ++ " optimisations Cabal automatically adds '-O2' for " ++ label
509 ++ " code. Setting it yourself interferes with the"
510 ++ " --disable-optimization flag."
511 ppExplanation
(COptCPP opt
) =
512 "'cpp-options: " ++ opt
++ "' is not a portable C-preprocessor flag."
513 ppExplanation
(OptAlternatives badField goodField flags
) =
514 "Instead of " ++ quote
(badField
++ ": " ++ unwords badFlags
)
515 ++ " use " ++ quote
(goodField
++ ": " ++ unwords goodFlags
)
516 where (badFlags
, goodFlags
) = unzip flags
517 ppExplanation
(RelativeOutside field path
) =
518 quote
(field
++ ": " ++ path
)
519 ++ " is a relative path outside of the source tree. "
520 ++ "This will not work when generating a tarball with 'sdist'."
521 ppExplanation
(AbsolutePath field path
) =
522 quote
(field
++ ": " ++ path
) ++ " specifies an absolute path, but the "
523 ++ quote field
++ " field must use relative paths."
524 ppExplanation
(BadRelativePAth field path err
) =
525 quote
(field
++ ": " ++ path
)
526 ++ " is not a good relative path: " ++ show err
527 ppExplanation
(DistPoint mfield path
) =
528 incipit
++ " points inside the 'dist' "
529 ++ "directory. This is not reliable because the location of this "
530 ++ "directory is configurable by the user (or package manager). In "
531 ++ "addition the layout of the 'dist' directory is subject to change "
532 ++ "in future versions of Cabal."
533 where -- mfiled Nothing -> the path is inside `ghc-options`
534 incipit
= maybe ("'ghc-options' path " ++ quote path
)
535 (\field
-> quote
(field
++ ": " ++ path
))
537 ppExplanation
(GlobSyntaxError field expl
) =
538 "In the '" ++ field
++ "' field: " ++ expl
539 ppExplanation
(InvalidOnWin paths
) =
540 "The " ++ quotes paths
++ " invalid on Windows, which "
541 ++ "would cause portability problems for this package. Windows file "
542 ++ "names cannot contain any of the characters \":*?<>|\" and there "
543 ++ "a few reserved names including \"aux\", \"nul\", \"con\", "
544 ++ "\"prn\", \"com1-9\", \"lpt1-9\" and \"clock$\"."
545 where quotes
[failed
] = "path " ++ quote failed
++ " is"
546 quotes failed
= "paths " ++ intercalate
", " (map quote failed
)
548 ppExplanation
(FilePathTooLong path
) =
549 "The following file name is too long to store in a portable POSIX "
550 ++ "format tar archive. The maximum length is 255 ASCII characters.\n"
551 ++ "The file in question is:\n " ++ path
552 ppExplanation
(FilePathNameTooLong path
) =
553 "The following file name is too long to store in a portable POSIX "
554 ++ "format tar archive. The maximum length for the name part (including "
555 ++ "extension) is 100 ASCII characters. The maximum length for any "
556 ++ "individual directory component is 155.\n"
557 ++ "The file in question is:\n " ++ path
558 ppExplanation
(FilePathSplitTooLong path
) =
559 "The following file name is too long to store in a portable POSIX "
560 ++ "format tar archive. While the total length is less than 255 ASCII "
561 ++ "characters, there are unfortunately further restrictions. It has to "
562 ++ "be possible to split the file path on a directory separator into "
563 ++ "two parts such that the first part fits in 155 characters or less "
564 ++ "and the second part fits in 100 characters or less. Basically you "
565 ++ "have to make the file name or directory names shorter, or you could "
566 ++ "split a long directory name into nested subdirectories with shorter "
567 ++ "names.\nThe file in question is:\n " ++ path
568 ppExplanation FilePathEmpty
=
569 "Encountered a file with an empty name, something is very wrong! "
570 ++ "Files with an empty name cannot be stored in a tar archive or in "
571 ++ "standard file systems."
572 ppExplanation CVTestSuite
=
573 "The 'test-suite' section is new in Cabal 1.10. "
574 ++ "Unfortunately it messes up the parser in older Cabal versions "
575 ++ "so you must specify at least 'cabal-version: >= 1.8', but note "
576 ++ "that only Cabal 1.10 and later can actually run such test suites."
577 ppExplanation CVDefaultLanguage
=
578 "To use the 'default-language' field the package needs to specify "
579 ++ "at least 'cabal-version: >= 1.10'."
580 ppExplanation CVDefaultLanguageComponent
=
581 "Packages using 'cabal-version: >= 1.10' and before 'cabal-version: 3.4' "
582 ++ "must specify the 'default-language' field for each component (e.g. "
583 ++ "Haskell98 or Haskell2010). If a component uses different languages "
584 ++ "in different modules then list the other ones in the "
585 ++ "'other-languages' field."
586 ppExplanation CVExtraDocFiles
=
587 "To use the 'extra-doc-files' field the package needs to specify "
588 ++ "'cabal-version: 1.18' or higher."
589 ppExplanation CVMultiLib
=
590 "To use multiple 'library' sections or a named library section "
591 ++ "the package needs to specify at least 'cabal-version: 2.0'."
592 ppExplanation CVReexported
=
593 "To use the 'reexported-module' field the package needs to specify "
594 ++ "'cabal-version: 1.22' or higher."
595 ppExplanation CVMixins
=
596 "To use the 'mixins' field the package needs to specify "
597 ++ "at least 'cabal-version: 2.0'."
598 ppExplanation CVExtraFrameworkDirs
=
599 "To use the 'extra-framework-dirs' field the package needs to specify"
600 ++ " 'cabal-version: 1.24' or higher."
601 ppExplanation CVDefaultExtensions
=
602 "To use the 'default-extensions' field the package needs to specify "
603 ++ "at least 'cabal-version: >= 1.10'."
604 ppExplanation CVExtensionsDeprecated
=
605 "For packages using 'cabal-version: >= 1.10' the 'extensions' "
606 ++ "field is deprecated. The new 'default-extensions' field lists "
607 ++ "extensions that are used in all modules in the component, while "
608 ++ "the 'other-extensions' field lists extensions that are used in "
609 ++ "some modules, e.g. via the {-# LANGUAGE #-} pragma."
610 ppExplanation CVSources
=
611 "The use of 'asm-sources', 'cmm-sources', 'extra-bundled-libraries' "
612 ++ " and 'extra-library-flavours' requires the package "
613 ++ " to specify at least 'cabal-version: 3.0'."
614 ppExplanation
(CVExtraDynamic flavs
) =
615 "The use of 'extra-dynamic-library-flavours' requires the package "
616 ++ " to specify at least 'cabal-version: 3.0'. The flavours are: "
617 ++ commaSep
(concat flavs
)
618 ppExplanation CVVirtualModules
=
619 "The use of 'virtual-modules' requires the package "
620 ++ " to specify at least 'cabal-version: 2.2'."
621 ppExplanation CVSourceRepository
=
622 "The 'source-repository' section is new in Cabal 1.6. "
623 ++ "Unfortunately it messes up the parser in earlier Cabal versions "
624 ++ "so you need to specify 'cabal-version: >= 1.6'."
625 ppExplanation
(CVExtensions version extCab12
) =
626 "Unfortunately the language extensions "
627 ++ commaSep
(map (quote
. prettyShow
) extCab12
)
628 ++ " break the parser in earlier Cabal versions so you need to "
629 ++ "specify 'cabal-version: >= " ++ showCabalSpecVersion version
630 ++ "'. Alternatively if you require compatibility with earlier "
631 ++ "Cabal versions then you may be able to use an equivalent "
632 ++ "compiler-specific flag."
633 ppExplanation CVCustomSetup
=
634 "Packages using 'cabal-version: 1.24' or higher with 'build-type: Custom' "
635 ++ "must use a 'custom-setup' section with a 'setup-depends' field "
636 ++ "that specifies the dependencies of the Setup.hs script itself. "
637 ++ "The 'setup-depends' field uses the same syntax as 'build-depends', "
638 ++ "so a simple example would be 'setup-depends: base, Cabal'."
639 ppExplanation CVExpliticDepsCustomSetup
=
640 "From version 1.24 cabal supports specifying explicit dependencies "
641 ++ "for Custom setup scripts. Consider using 'cabal-version: 1.24' or "
642 ++ "higher and adding a 'custom-setup' section with a 'setup-depends' "
643 ++ "field that specifies the dependencies of the Setup.hs script "
644 ++ "itself. The 'setup-depends' field uses the same syntax as "
645 ++ "'build-depends', so a simple example would be 'setup-depends: base, "
647 ppExplanation CVAutogenPaths
=
648 "Packages using 'cabal-version: 2.0' and the autogenerated "
649 ++ "module Paths_* must include it also on the 'autogen-modules' field "
650 ++ "besides 'exposed-modules' and 'other-modules'. This specifies that "
651 ++ "the module does not come with the package and is generated on "
652 ++ "setup. Modules built with a custom Setup.hs script also go here "
653 ++ "to ensure that commands like sdist don't fail."
654 ppExplanation
(GlobNoMatch field glob
) =
655 "In '" ++ field
++ "': the pattern '" ++ glob
++ "' does not"
656 ++ " match any files."
657 ppExplanation
(GlobExactMatch field glob file
) =
658 "In '" ++ field
++ "': the pattern '" ++ glob
++ "' does not"
659 ++ " match the file '" ++ file
++ "' because the extensions do not"
660 ++ " exactly match (e.g., foo.en.html does not exactly match *.html)."
661 ++ " To enable looser suffix-only matching, set 'cabal-version: 2.4' or"
663 ppExplanation
(GlobNoDir field glob dir
) =
664 "In '" ++ field
++ "': the pattern '" ++ glob
++ "' attempts to"
665 ++ " match files in the directory '" ++ dir
++ "', but there is no"
666 ++ " directory by that name."
667 ppExplanation
(UnknownOS unknownOSs
) =
668 "Unknown operating system name " ++ commaSep
(map quote unknownOSs
)
669 ppExplanation
(UnknownArch unknownArches
) =
670 "Unknown architecture name " ++ commaSep
(map quote unknownArches
)
671 ppExplanation
(UnknownCompiler unknownImpls
) =
672 "Unknown compiler name " ++ commaSep
(map quote unknownImpls
)
673 ppExplanation BaseNoUpperBounds
=
674 "The dependency 'build-depends: base' does not specify an upper "
675 ++ "bound on the version number. Each major release of the 'base' "
676 ++ "package changes the API in various ways and most packages will "
677 ++ "need some changes to compile with it. The recommended practice "
678 ++ "is to specify an upper bound on the version of the 'base' "
679 ++ "package. This ensures your package will continue to build when a "
680 ++ "new major version of the 'base' package is released. If you are "
681 ++ "not sure what upper bound to use then use the next major "
682 ++ "version. For example if you have tested your package with 'base' "
683 ++ "version 4.5 and 4.6 then use 'build-depends: base >= 4.5 && < 4.7'."
684 ppExplanation
(SuspiciousFlagName invalidFlagNames
) =
685 "Suspicious flag names: " ++ unwords invalidFlagNames
++ ". "
686 ++ "To avoid ambiguity in command line interfaces, flag shouldn't "
687 ++ "start with a dash. Also for better compatibility, flag names "
688 ++ "shouldn't contain non-ascii characters."
689 ppExplanation
(DeclaredUsedFlags declared used
) =
690 "Declared and used flag sets differ: "
691 ++ s declared
++ " /= " ++ s used
++ ". "
692 where s
:: Set
.Set FlagName
-> String
693 s
= commaSep
. map unFlagName
. Set
.toList
694 ppExplanation
(NonASCIICustomField nonAsciiXFields
) =
695 "Non ascii custom fields: " ++ unwords nonAsciiXFields
++ ". "
696 ++ "For better compatibility, custom field names "
697 ++ "shouldn't contain non-ascii characters."
698 ppExplanation RebindableClash
=
699 "Packages using RebindableSyntax with OverloadedStrings or"
700 ++ " OverloadedLists in default-extensions, in conjunction with the"
701 ++ " autogenerated module Paths_*, are known to cause compile failures"
702 ++ " with Cabal < 2.2. To use these default-extensions with a Paths_*"
703 ++ " autogen module, specify at least 'cabal-version: 2.2'."
704 ppExplanation
(WErrorUnneeded fieldName
) = addConditionalExp
$
705 "'" ++ fieldName
++ ": -Werror' makes the package easy to "
706 ++ "break with future GHC versions because new GHC versions often "
707 ++ "add new warnings."
708 ppExplanation
(JUnneeded fieldName
) = addConditionalExp
$
709 "'" ++ fieldName
++ ": -j[N]' can make sense for specific user's setup,"
710 ++ " but it is not appropriate for a distributed package."
711 ppExplanation
(FDeferTypeErrorsUnneeded fieldName
) = addConditionalExp
$
712 "'" ++ fieldName
++ ": -fdefer-type-errors' is fine during development "
713 ++ "but is not appropriate for a distributed package."
714 ppExplanation
(DynamicUnneeded fieldName
) = addConditionalExp
$
715 "'" ++ fieldName
++ ": -d*' debug flags are not appropriate "
716 ++ "for a distributed package."
717 ppExplanation
(ProfilingUnneeded fieldName
) = addConditionalExp
$
718 "'" ++ fieldName
++ ": -fprof*' profiling flags are typically not "
719 ++ "appropriate for a distributed library package. These flags are "
720 ++ "useful to profile this package, but when profiling other packages "
721 ++ "that use this one these flags clutter the profile output with "
722 ++ "excessive detail. If you think other packages really want to see "
723 ++ "cost centres from this package then use '-fprof-auto-exported' "
724 ++ "which puts cost centres only on exported functions."
725 ppExplanation
(UpperBoundSetup nm
) =
726 "The dependency 'setup-depends: '"++nm
++"' does not specify an "
727 ++ "upper bound on the version number. Each major release of the "
728 ++ "'"++nm
++"' package changes the API in various ways and most "
729 ++ "packages will need some changes to compile with it. If you are "
730 ++ "not sure what upper bound to use then use the next major "
732 ppExplanation
(DuplicateModule s dupLibsLax
) =
733 "Duplicate modules in " ++ s
++ ": "
734 ++ commaSep
(map prettyShow dupLibsLax
)
735 ppExplanation
(PotentialDupModule s dupLibsStrict
) =
736 "Potential duplicate modules (subject to conditionals) in " ++ s
737 ++ ": " ++ commaSep
(map prettyShow dupLibsStrict
)
738 ppExplanation
(BOMStart pdfile
) =
739 pdfile
++ " starts with an Unicode byte order mark (BOM)."
740 ++ " This may cause problems with older cabal versions."
741 ppExplanation
(NotPackageName pdfile expectedCabalname
) =
742 "The filename " ++ quote pdfile
++ " does not match package name "
743 ++ "(expected: " ++ quote expectedCabalname
++ ")"
744 ppExplanation NoDesc
=
745 "No cabal file found.\n"
746 ++ "Please create a package description file <pkgname>.cabal"
747 ppExplanation
(MultiDesc multiple
) =
748 "Multiple cabal files found while checking.\n"
749 ++ "Please use only one of: "
750 ++ intercalate
", " multiple
751 ppExplanation
(UnknownFile fieldname file
) =
752 "The '" ++ fieldname
++ "' field refers to the file "
753 ++ quote
(getSymbolicPath file
) ++ " which does not exist."
754 ppExplanation MissingSetupFile
=
755 "The package is missing a Setup.hs or Setup.lhs script."
756 ppExplanation MissingConfigureScript
=
757 "The 'build-type' is 'Configure' but there is no 'configure' script. "
758 ++ "You probably need to run 'autoreconf -i' to generate it."
759 ppExplanation
(UnknownDirectory kind dir
) =
760 quote
(kind
++ ": " ++ dir
)
761 ++ " specifies a directory which does not exist."
762 ppExplanation MissingSourceControl
=
763 "When distributing packages it is encouraged to specify source "
764 ++ "control information in the .cabal file using one or more "
765 ++ "'source-repository' sections. See the Cabal user guide for "
769 -- | Results of some kind of failed package check.
771 -- There are a range of severities, from merely dubious to totally insane.
772 -- All of them come with a human readable explanation. In future we may augment
773 -- them with more machine readable explanations, for example to help an IDE
774 -- suggest automatic corrections.
778 -- | This package description is no good. There's no way it's going to
779 -- build sensibly. This should give an error at configure time.
780 PackageBuildImpossible
{ explanation
:: CheckExplanation
}
782 -- | A problem that is likely to affect building the package, or an
783 -- issue that we'd like every package author to be aware of, even if
784 -- the package is never distributed.
785 | PackageBuildWarning
{ explanation
:: CheckExplanation
}
787 -- | An issue that might not be a problem for the package author but
788 -- might be annoying or detrimental when the package is distributed to
789 -- users. We should encourage distributed packages to be free from these
790 -- issues, but occasionally there are justifiable reasons so we cannot
791 -- ban them entirely.
792 | PackageDistSuspicious
{ explanation
:: CheckExplanation
}
794 -- | Like PackageDistSuspicious but will only display warnings
795 -- rather than causing abnormal exit when you run 'cabal check'.
796 | PackageDistSuspiciousWarn
{ explanation
:: CheckExplanation
}
798 -- | An issue that is OK in the author's environment but is almost
799 -- certain to be a portability problem for other environments. We can
800 -- quite legitimately refuse to publicly distribute packages with these
802 | PackageDistInexcusable
{ explanation
:: CheckExplanation
}
805 -- | Pretty printing 'PackageCheck'.
807 ppPackageCheck
:: PackageCheck
-> String
808 ppPackageCheck e
= ppExplanation
(explanation e
)
810 instance Show PackageCheck
where
811 show notice
= ppPackageCheck notice
813 check
:: Bool -> PackageCheck
-> Maybe PackageCheck
814 check
False _
= Nothing
815 check
True pc
= Just pc
817 checkSpecVersion
:: PackageDescription
-> CabalSpecVersion
-> Bool -> PackageCheck
818 -> Maybe PackageCheck
819 checkSpecVersion pkg specver cond pc
820 | specVersion pkg
>= specver
= Nothing
821 |
otherwise = check cond pc
823 -- ------------------------------------------------------------
825 -- ------------------------------------------------------------
827 -- | Check for common mistakes and problems in package descriptions.
829 -- This is the standard collection of checks covering all aspects except
830 -- for checks that require looking at files within the package. For those
831 -- see 'checkPackageFiles'.
833 -- It requires the 'GenericPackageDescription' and optionally a particular
834 -- configuration of that package. If you pass 'Nothing' then we just check
835 -- a version of the generic description using 'flattenPackageDescription'.
837 checkPackage
:: GenericPackageDescription
838 -> Maybe PackageDescription
840 checkPackage gpkg mpkg
=
841 checkConfiguredPackage pkg
842 ++ checkConditionals gpkg
843 ++ checkPackageVersions gpkg
844 ++ checkDevelopmentOnlyFlags gpkg
845 ++ checkFlagNames gpkg
846 ++ checkUnusedFlags gpkg
847 ++ checkUnicodeXFields gpkg
848 ++ checkPathsModuleExtensions pkg
849 ++ checkSetupVersions gpkg
850 ++ checkDuplicateModules gpkg
852 pkg
= fromMaybe (flattenPackageDescription gpkg
) mpkg
854 --TODO: make this variant go away
855 -- we should always know the GenericPackageDescription
856 checkConfiguredPackage
:: PackageDescription
-> [PackageCheck
]
857 checkConfiguredPackage pkg
=
861 ++ checkSourceRepos pkg
862 ++ checkAllGhcOptions pkg
863 ++ checkCCOptions pkg
864 ++ checkCxxOptions pkg
865 ++ checkCPPOptions pkg
867 ++ checkCabalVersion pkg
870 -- ------------------------------------------------------------
871 -- * Basic sanity checks
872 -- ------------------------------------------------------------
874 -- | Check that this package description is sane.
876 checkSanity
:: PackageDescription
-> [PackageCheck
]
880 check
(null . unPackageName
. packageName
$ pkg
) $
881 PackageBuildImpossible NoNameField
883 , check
(nullVersion
== packageVersion pkg
) $
884 PackageBuildImpossible NoVersionField
886 , check
(all ($ pkg
) [ null . executables
889 , null . allLibraries
890 , null . foreignLibs
]) $
891 PackageBuildImpossible NoTarget
893 , check
(any (== LMainLibName
) (map libName
$ subLibraries pkg
)) $
894 PackageBuildImpossible UnnamedInternal
896 , check
(not (null duplicateNames
)) $
897 PackageBuildImpossible
(DuplicateSections duplicateNames
)
899 -- NB: but it's OK for executables to have the same name!
900 -- TODO shouldn't need to compare on the string level
901 , check
(any (== prettyShow
(packageName pkg
))
902 (prettyShow
<$> subLibNames
)) $
903 PackageBuildImpossible
(IllegalLibraryName pkg
)
905 --TODO: check for name clashes case insensitively: windows file systems cannot
908 ++ concatMap (checkLibrary pkg
) (allLibraries pkg
)
909 ++ concatMap (checkExecutable pkg
) (executables pkg
)
910 ++ concatMap (checkTestSuite pkg
) (testSuites pkg
)
911 ++ concatMap (checkBenchmark pkg
) (benchmarks pkg
)
914 -- The public 'library' gets special dispensation, because it
915 -- is common practice to export a library and name the executable
916 -- the same as the package.
917 subLibNames
= mapMaybe (libraryNameString
. libName
) $ subLibraries pkg
918 exeNames
= map exeName
$ executables pkg
919 testNames
= map testName
$ testSuites pkg
920 bmNames
= map benchmarkName
$ benchmarks pkg
921 duplicateNames
= dups
$ subLibNames
++ exeNames
++ testNames
++ bmNames
923 checkLibrary
:: PackageDescription
-> Library
-> [PackageCheck
]
924 checkLibrary pkg lib
=
927 -- TODO: This check is bogus if a required-signature was passed through
928 check
(null (explicitLibModules lib
) && null (reexportedModules lib
)) $
929 PackageDistSuspiciousWarn
(NoModulesExposed lib
)
931 -- check use of signatures sections
932 , checkVersion CabalSpecV2_0
(not (null (signatures lib
))) $
933 PackageDistInexcusable SignaturesCabal2
935 -- check that all autogen-modules appear on other-modules or exposed-modules
937 (not $ and $ map (flip elem (explicitLibModules lib
)) (libModulesAutogen lib
)) $
938 PackageBuildImpossible AutogenNotExposed
940 -- check that all autogen-includes appear on includes or install-includes
942 (not $ and $ map (flip elem (allExplicitIncludes lib
)) (view L
.autogenIncludes lib
)) $
943 PackageBuildImpossible AutogenIncludesNotIncluded
947 checkVersion
:: CabalSpecVersion
-> Bool -> PackageCheck
-> Maybe PackageCheck
948 checkVersion ver cond pc
949 | specVersion pkg
>= ver
= Nothing
950 |
otherwise = check cond pc
952 allExplicitIncludes
:: L
.HasBuildInfo a
=> a
-> [FilePath]
953 allExplicitIncludes x
= view L
.includes x
++ view L
.installIncludes x
955 checkExecutable
:: PackageDescription
-> Executable
-> [PackageCheck
]
956 checkExecutable pkg exe
=
959 check
(null (modulePath exe
)) $
960 PackageBuildImpossible
(NoMainIs exe
)
962 -- This check does not apply to scripts.
963 , check
(package pkg
/= fakePackageId
964 && not (null (modulePath exe
))
965 && not (fileExtensionSupportedLanguage
$ modulePath exe
)) $
966 PackageBuildImpossible NoHsLhsMain
968 , checkSpecVersion pkg CabalSpecV1_18
969 (fileExtensionSupportedLanguage
(modulePath exe
)
970 && takeExtension
(modulePath exe
) `
notElem`
[".hs", ".lhs"]) $
971 PackageDistInexcusable MainCCabal1_18
973 -- check that all autogen-modules appear on other-modules
975 (not $ and $ map (flip elem (exeModules exe
)) (exeModulesAutogen exe
)) $
976 PackageBuildImpossible
(AutogenNoOther CETExecutable
(exeName exe
))
978 -- check that all autogen-includes appear on includes
980 (not $ and $ map (flip elem (view L
.includes exe
)) (view L
.autogenIncludes exe
)) $
981 PackageBuildImpossible AutogenIncludesNotIncludedExe
984 checkTestSuite
:: PackageDescription
-> TestSuite
-> [PackageCheck
]
985 checkTestSuite pkg test
=
988 case testInterface test
of
989 TestSuiteUnsupported tt
@(TestTypeUnknown _ _
) -> Just
$
990 PackageBuildWarning
(TestsuiteTypeNotKnown tt
)
992 TestSuiteUnsupported tt
-> Just
$
993 PackageBuildWarning
(TestsuiteNotSupported tt
)
996 , check mainIsWrongExt
$
997 PackageBuildImpossible NoHsLhsMain
999 , checkSpecVersion pkg CabalSpecV1_18
(mainIsNotHsExt
&& not mainIsWrongExt
) $
1000 PackageDistInexcusable MainCCabal1_18
1002 -- check that all autogen-modules appear on other-modules
1004 (not $ and $ map (flip elem (testModules test
)) (testModulesAutogen test
)) $
1005 PackageBuildImpossible
(AutogenNoOther CETTest
(testName test
))
1007 -- check that all autogen-includes appear on includes
1009 (not $ and $ map (flip elem (view L
.includes test
)) (view L
.autogenIncludes test
)) $
1010 PackageBuildImpossible AutogenIncludesNotIncludedExe
1013 mainIsWrongExt
= case testInterface test
of
1014 TestSuiteExeV10 _ f
-> not $ fileExtensionSupportedLanguage f
1017 mainIsNotHsExt
= case testInterface test
of
1018 TestSuiteExeV10 _ f
-> takeExtension f `
notElem`
[".hs", ".lhs"]
1021 checkBenchmark
:: PackageDescription
-> Benchmark
-> [PackageCheck
]
1022 checkBenchmark _pkg bm
=
1025 case benchmarkInterface bm
of
1026 BenchmarkUnsupported tt
@(BenchmarkTypeUnknown _ _
) -> Just
$
1027 PackageBuildWarning
(BenchmarkTypeNotKnown tt
)
1029 BenchmarkUnsupported tt
-> Just
$
1030 PackageBuildWarning
(BenchmarkNotSupported tt
)
1033 , check mainIsWrongExt
$
1034 PackageBuildImpossible NoHsLhsMainBench
1036 -- check that all autogen-modules appear on other-modules
1038 (not $ and $ map (flip elem (benchmarkModules bm
)) (benchmarkModulesAutogen bm
)) $
1039 PackageBuildImpossible
(AutogenNoOther CETBenchmark
(benchmarkName bm
))
1041 -- check that all autogen-includes appear on includes
1043 (not $ and $ map (flip elem (view L
.includes bm
)) (view L
.autogenIncludes bm
)) $
1044 PackageBuildImpossible AutogenIncludesNotIncludedExe
1047 mainIsWrongExt
= case benchmarkInterface bm
of
1048 BenchmarkExeV10 _ f
-> takeExtension f `
notElem`
[".hs", ".lhs"]
1051 -- ------------------------------------------------------------
1052 -- * Additional pure checks
1053 -- ------------------------------------------------------------
1055 checkFields
:: PackageDescription
-> [PackageCheck
]
1059 check
(not . FilePath.Windows
.isValid
. prettyShow
. packageName
$ pkg
) $
1060 PackageDistInexcusable
(InvalidNameWin pkg
)
1062 , check
(isPrefixOf "z-" . prettyShow
. packageName
$ pkg
) $
1063 PackageDistInexcusable ZPrefix
1065 , check
(isNothing (buildTypeRaw pkg
) && specVersion pkg
< CabalSpecV2_2
) $
1066 PackageBuildWarning NoBuildType
1068 , check
(isJust (setupBuildInfo pkg
) && buildType pkg
/= Custom
) $
1069 PackageBuildWarning NoCustomSetup
1071 , check
(not (null unknownCompilers
)) $
1072 PackageBuildWarning
(UnknownCompilers unknownCompilers
)
1074 , check
(not (null unknownLanguages
)) $
1075 PackageBuildWarning
(UnknownLanguages unknownLanguages
)
1077 , check
(not (null unknownExtensions
)) $
1078 PackageBuildWarning
(UnknownExtensions unknownExtensions
)
1080 , check
(not (null languagesUsedAsExtensions
)) $
1081 PackageBuildWarning
(LanguagesAsExtension languagesUsedAsExtensions
)
1083 , check
(not (null ourDeprecatedExtensions
)) $
1084 PackageDistSuspicious
(DeprecatedExtensions ourDeprecatedExtensions
)
1086 , check
(ShortText
.null (category pkg
)) $
1087 PackageDistSuspicious
(MissingField CEFCategory
)
1089 , check
(ShortText
.null (maintainer pkg
)) $
1090 PackageDistSuspicious
(MissingField CEFMaintainer
)
1092 , check
(ShortText
.null (synopsis pkg
) && ShortText
.null (description pkg
)) $
1093 PackageDistInexcusable
(MissingField CEFSynOrDesc
)
1095 , check
(ShortText
.null (description pkg
) && not (ShortText
.null (synopsis pkg
))) $
1096 PackageDistSuspicious
(MissingField CEFDescription
)
1098 , check
(ShortText
.null (synopsis pkg
) && not (ShortText
.null (description pkg
))) $
1099 PackageDistSuspicious
(MissingField CEFSynopsis
)
1101 --TODO: recommend the bug reports URL, author and homepage fields
1102 --TODO: recommend not using the stability field
1103 --TODO: recommend specifying a source repo
1105 , check
(ShortText
.length (synopsis pkg
) > 80) $
1106 PackageDistSuspicious SynopsisTooLong
1108 -- See also https://github.com/haskell/cabal/pull/3479
1109 , check
(not (ShortText
.null (description pkg
))
1110 && ShortText
.length (description pkg
) <= ShortText
.length (synopsis pkg
)) $
1111 PackageDistSuspicious ShortDesc
1113 -- check use of impossible constraints "tested-with: GHC== 6.10 && ==6.12"
1114 , check
(not (null testedWithImpossibleRanges
)) $
1115 PackageDistInexcusable
(InvalidTestWith testedWithImpossibleRanges
)
1117 -- for more details on why the following was commented out,
1118 -- check https://github.com/haskell/cabal/pull/7470#issuecomment-875878507
1119 -- , check (not (null depInternalLibraryWithExtraVersion)) $
1120 -- PackageBuildWarning $
1121 -- "The package has an extraneous version range for a dependency on an "
1122 -- ++ "internal library: "
1123 -- ++ commaSep (map prettyShow depInternalLibraryWithExtraVersion)
1124 -- ++ ". This version range includes the current package but isn't needed "
1125 -- ++ "as the current package's library will always be used."
1127 , check
(not (null depInternalLibraryWithImpossibleVersion
)) $
1128 PackageBuildImpossible
1129 (ImpossibleInternalDep depInternalLibraryWithImpossibleVersion
)
1131 -- , check (not (null depInternalExecutableWithExtraVersion)) $
1132 -- PackageBuildWarning $
1133 -- "The package has an extraneous version range for a dependency on an "
1134 -- ++ "internal executable: "
1135 -- ++ commaSep (map prettyShow depInternalExecutableWithExtraVersion)
1136 -- ++ ". This version range includes the current package but isn't needed "
1137 -- ++ "as the current package's executable will always be used."
1139 , check
(not (null depInternalExecutableWithImpossibleVersion
)) $
1140 PackageBuildImpossible
1141 (ImpossibleInternalExe depInternalExecutableWithImpossibleVersion
)
1143 , check
(not (null depMissingInternalExecutable
)) $
1144 PackageBuildImpossible
(MissingInternalExe depMissingInternalExecutable
)
1147 unknownCompilers
= [ name |
(OtherCompiler name
, _
) <- testedWith pkg
]
1148 unknownLanguages
= [ name | bi
<- allBuildInfo pkg
1149 , UnknownLanguage name
<- allLanguages bi
]
1150 unknownExtensions
= [ name | bi
<- allBuildInfo pkg
1151 , UnknownExtension name
<- allExtensions bi
1152 , name `
notElem`
map prettyShow knownLanguages
]
1153 ourDeprecatedExtensions
= nub $ catMaybes
1154 [ find ((==ext
) . fst) deprecatedExtensions
1155 | bi
<- allBuildInfo pkg
1156 , ext
<- allExtensions bi
]
1157 languagesUsedAsExtensions
=
1158 [ name | bi
<- allBuildInfo pkg
1159 , UnknownExtension name
<- allExtensions bi
1160 , name `
elem`
map prettyShow knownLanguages
]
1162 testedWithImpossibleRanges
=
1163 [ Dependency
(mkPackageName
(prettyShow compiler
)) vr mainLibSet
1164 |
(compiler
, vr
) <- testedWith pkg
1168 map (maybe (packageName pkg
) unqualComponentNameToPackageName
. libraryNameString
. libName
)
1171 internalExecutables
= map exeName
$ executables pkg
1175 | bi
<- allBuildInfo pkg
1176 , dep
@(Dependency name _ _
) <- targetBuildDepends bi
1177 , name `
elem` internalLibraries
1182 | bi
<- allBuildInfo pkg
1183 , dep
<- getAllToolDependencies pkg bi
1184 , isInternal pkg dep
1187 -- depInternalLibraryWithExtraVersion =
1189 -- | dep@(Dependency _ versionRange _) <- internalLibDeps
1190 -- , not $ isAnyVersion versionRange
1191 -- , packageVersion pkg `withinRange` versionRange
1194 depInternalLibraryWithImpossibleVersion
=
1196 | dep
@(Dependency _ versionRange _
) <- internalLibDeps
1197 , not $ packageVersion pkg `withinRange` versionRange
1200 -- depInternalExecutableWithExtraVersion =
1202 -- | dep@(ExeDependency _ _ versionRange) <- internalExeDeps
1203 -- , not $ isAnyVersion versionRange
1204 -- , packageVersion pkg `withinRange` versionRange
1207 depInternalExecutableWithImpossibleVersion
=
1209 | dep
@(ExeDependency _ _ versionRange
) <- internalExeDeps
1210 , not $ packageVersion pkg `withinRange` versionRange
1213 depMissingInternalExecutable
=
1215 | dep
@(ExeDependency _ eName _
) <- internalExeDeps
1216 , not $ eName `
elem` internalExecutables
1219 checkLicense
:: PackageDescription
-> [PackageCheck
]
1220 checkLicense pkg
= case licenseRaw pkg
of
1221 Right l
-> checkOldLicense pkg l
1222 Left l
-> checkNewLicense pkg l
1224 checkNewLicense
:: PackageDescription
-> SPDX
.License
-> [PackageCheck
]
1225 checkNewLicense _pkg lic
= catMaybes
1226 [ check
(lic
== SPDX
.NONE
) $
1227 PackageDistInexcusable NONELicense
]
1229 checkOldLicense
:: PackageDescription
-> License
-> [PackageCheck
]
1230 checkOldLicense pkg lic
= catMaybes
1231 [ check
(lic
== UnspecifiedLicense
) $
1232 PackageDistInexcusable NoLicense
1234 , check
(lic
== AllRightsReserved
) $
1235 PackageDistSuspicious AllRightsReservedLicense
1237 , checkVersion CabalSpecV1_4
(lic `
notElem` compatLicenses
) $
1238 PackageDistInexcusable
(LicenseMessParse pkg
)
1241 UnknownLicense l
-> Just
$ PackageBuildWarning
(UnrecognisedLicense l
)
1244 , check
(lic
== BSD4
) $
1245 PackageDistSuspicious UncommonBSD4
1247 , case unknownLicenseVersion lic
of
1248 Just knownVersions
-> Just
$
1249 PackageDistSuspicious
(UnknownLicenseVersion lic knownVersions
)
1252 , check
(lic `
notElem`
[ AllRightsReserved
1253 , UnspecifiedLicense
, PublicDomain
]
1254 -- AllRightsReserved and PublicDomain are not strictly
1255 -- licenses so don't need license files.
1256 && null (licenseFiles pkg
)) $
1257 PackageDistSuspicious NoLicenseFile
1260 unknownLicenseVersion
(GPL
(Just v
))
1261 | v `
notElem` knownVersions
= Just knownVersions
1262 where knownVersions
= [ v
' | GPL
(Just v
') <- knownLicenses
]
1263 unknownLicenseVersion
(LGPL
(Just v
))
1264 | v `
notElem` knownVersions
= Just knownVersions
1265 where knownVersions
= [ v
' | LGPL
(Just v
') <- knownLicenses
]
1266 unknownLicenseVersion
(AGPL
(Just v
))
1267 | v `
notElem` knownVersions
= Just knownVersions
1268 where knownVersions
= [ v
' | AGPL
(Just v
') <- knownLicenses
]
1269 unknownLicenseVersion
(Apache
(Just v
))
1270 | v `
notElem` knownVersions
= Just knownVersions
1271 where knownVersions
= [ v
' | Apache
(Just v
') <- knownLicenses
]
1272 unknownLicenseVersion _
= Nothing
1274 checkVersion
:: CabalSpecVersion
-> Bool -> PackageCheck
-> Maybe PackageCheck
1275 checkVersion ver cond pc
1276 | specVersion pkg
>= ver
= Nothing
1277 |
otherwise = check cond pc
1279 compatLicenses
= [ GPL Nothing
, LGPL Nothing
, AGPL Nothing
, BSD3
, BSD4
1280 , PublicDomain
, AllRightsReserved
1281 , UnspecifiedLicense
, OtherLicense
]
1283 checkSourceRepos
:: PackageDescription
-> [PackageCheck
]
1284 checkSourceRepos pkg
=
1285 catMaybes $ concat [[
1287 case repoKind repo
of
1288 RepoKindUnknown kind
-> Just
$ PackageDistInexcusable
$
1289 UnrecognisedSourceRepo kind
1292 , check
(isNothing (repoType repo
)) $
1293 PackageDistInexcusable MissingType
1295 , check
(isNothing (repoLocation repo
)) $
1296 PackageDistInexcusable MissingLocation
1298 , check
(repoType repo
== Just
(KnownRepoType CVS
) && isNothing (repoModule repo
)) $
1299 PackageDistInexcusable MissingModule
1301 , check
(repoKind repo
== RepoThis
&& isNothing (repoTag repo
)) $
1302 PackageDistInexcusable MissingTag
1304 , check
(maybe False isAbsoluteOnAnyPlatform
(repoSubdir repo
)) $
1305 PackageDistInexcusable SubdirRelPath
1308 subdir
<- repoSubdir repo
1309 err
<- isGoodRelativeDirectoryPath subdir
1310 return $ PackageDistInexcusable
(SubdirGoodRelPath err
)
1312 | repo
<- sourceRepos pkg
]
1314 --TODO: check location looks like a URL for some repo types.
1316 -- | Checks GHC options from all ghc-*-options fields in the given
1317 -- PackageDescription and reports commonly misused or non-portable flags
1318 checkAllGhcOptions
:: PackageDescription
-> [PackageCheck
]
1319 checkAllGhcOptions pkg
=
1320 checkGhcOptions
"ghc-options" (hcOptions GHC
) pkg
1321 ++ checkGhcOptions
"ghc-prof-options" (hcProfOptions GHC
) pkg
1322 ++ checkGhcOptions
"ghc-shared-options" (hcSharedOptions GHC
) pkg
1324 -- | Extracts GHC options belonging to the given field from the given
1325 -- PackageDescription using given function and checks them for commonly misused
1326 -- or non-portable flags
1327 checkGhcOptions
:: String -> (BuildInfo
-> [String]) -> PackageDescription
-> [PackageCheck
]
1328 checkGhcOptions fieldName getOptions pkg
=
1331 checkFlags
["-fasm"] $
1332 PackageDistInexcusable
(OptFasm fieldName
)
1334 , checkFlags
["-fvia-C"] $
1335 PackageDistSuspicious
(OptViaC fieldName
)
1337 , checkFlags
["-fhpc"] $
1338 PackageDistInexcusable
(OptHpc fieldName
)
1340 , checkFlags
["-prof"] $
1341 PackageBuildWarning
(OptProf fieldName
)
1343 , checkFlags
["-o"] $
1344 PackageBuildWarning
(OptO fieldName
)
1346 , checkFlags
["-hide-package"] $
1347 PackageBuildWarning
(OptHide fieldName
)
1349 , checkFlags
["--make"] $
1350 PackageBuildWarning
(OptMake fieldName
)
1352 , checkFlags
["-main-is"] $
1353 PackageDistSuspicious
(OptMain fieldName
)
1355 , checkNonTestAndBenchmarkFlags
["-O0", "-Onot"] $
1356 PackageDistSuspicious
(OptONot fieldName
)
1358 , checkTestAndBenchmarkFlags
["-O0", "-Onot"] $
1359 PackageDistSuspiciousWarn
(OptONot fieldName
)
1361 , checkFlags
[ "-O", "-O1"] $
1362 PackageDistInexcusable
(OptOOne fieldName
)
1364 , checkFlags
["-O2"] $
1365 PackageDistSuspiciousWarn
(OptOTwo fieldName
)
1367 , checkFlags
["-split-sections"] $
1368 PackageBuildWarning
(OptSplitSections fieldName
)
1370 , checkFlags
["-split-objs"] $
1371 PackageBuildWarning
(OptSplitObjs fieldName
)
1373 , checkFlags
["-optl-Wl,-s", "-optl-s"] $
1374 PackageDistInexcusable
(OptWls fieldName
)
1376 , checkFlags
["-fglasgow-exts"] $
1377 PackageDistSuspicious
(OptExts fieldName
)
1379 , check
("-threaded" `
elem` lib_ghc_options
) $
1380 PackageBuildWarning
(OptThreaded fieldName
)
1382 , check
("-rtsopts" `
elem` lib_ghc_options
) $
1383 PackageBuildWarning
(OptRts fieldName
)
1385 , check
(any (\opt
-> "-with-rtsopts" `
isPrefixOf` opt
) lib_ghc_options
) $
1386 PackageBuildWarning
(OptWithRts fieldName
)
1388 , checkAlternatives fieldName
"extensions"
1389 [ (flag
, prettyShow extension
) | flag
<- ghc_options_no_rtsopts
1390 , Just extension
<- [ghcExtension flag
] ]
1392 , checkAlternatives fieldName
"extensions"
1393 [ (flag
, extension
) | flag
@('-':'X
':extension
) <- ghc_options_no_rtsopts
]
1395 , checkAlternatives fieldName
"cpp-options" $
1396 [ (flag
, flag
) | flag
@('-':'D
':_
) <- ghc_options_no_rtsopts
]
1397 ++ [ (flag
, flag
) | flag
@('-':'U
':_
) <- ghc_options_no_rtsopts
]
1399 , checkAlternatives fieldName
"include-dirs"
1400 [ (flag
, dir
) | flag
@('-':'I
':dir
) <- ghc_options_no_rtsopts
]
1402 , checkAlternatives fieldName
"extra-libraries"
1403 [ (flag
, lib
) | flag
@('-':'l
':lib
) <- ghc_options_no_rtsopts
]
1405 , checkAlternatives fieldName
"extra-libraries-static"
1406 [ (flag
, lib
) | flag
@('-':'l
':lib
) <- ghc_options_no_rtsopts
]
1408 , checkAlternatives fieldName
"extra-lib-dirs"
1409 [ (flag
, dir
) | flag
@('-':'L
':dir
) <- ghc_options_no_rtsopts
]
1411 , checkAlternatives fieldName
"extra-lib-dirs-static"
1412 [ (flag
, dir
) | flag
@('-':'L
':dir
) <- ghc_options_no_rtsopts
]
1414 , checkAlternatives fieldName
"frameworks"
1415 [ (flag
, fmwk
) |
(flag
@"-framework", fmwk
) <-
1416 zip ghc_options_no_rtsopts
(safeTail ghc_options_no_rtsopts
) ]
1418 , checkAlternatives fieldName
"extra-framework-dirs"
1419 [ (flag
, dir
) |
(flag
@"-framework-path", dir
) <-
1420 zip ghc_options_no_rtsopts
(safeTail ghc_options_no_rtsopts
) ]
1424 all_ghc_options
= concatMap getOptions
(allBuildInfo pkg
)
1425 ghc_options_no_rtsopts
= rmRtsOpts all_ghc_options
1426 lib_ghc_options
= concatMap (getOptions
. libBuildInfo
)
1428 test_ghc_options
= concatMap (getOptions
. testBuildInfo
)
1430 benchmark_ghc_options
= concatMap (getOptions
. benchmarkBuildInfo
)
1432 test_and_benchmark_ghc_options
= test_ghc_options
++
1433 benchmark_ghc_options
1434 non_test_and_benchmark_ghc_options
= concatMap getOptions
1435 (allBuildInfo
(pkg
{ testSuites
= []
1439 checkFlags
:: [String] -> PackageCheck
-> Maybe PackageCheck
1440 checkFlags flags
= check
(any (`
elem` flags
) all_ghc_options
)
1442 checkTestAndBenchmarkFlags
:: [String] -> PackageCheck
-> Maybe PackageCheck
1443 checkTestAndBenchmarkFlags flags
= check
(any (`
elem` flags
) test_and_benchmark_ghc_options
)
1445 checkNonTestAndBenchmarkFlags
:: [String] -> PackageCheck
-> Maybe PackageCheck
1446 checkNonTestAndBenchmarkFlags flags
= check
(any (`
elem` flags
) non_test_and_benchmark_ghc_options
)
1448 ghcExtension
('-':'f
':name
) = case name
of
1449 "allow-overlapping-instances" -> enable OverlappingInstances
1450 "no-allow-overlapping-instances" -> disable OverlappingInstances
1451 "th" -> enable TemplateHaskell
1452 "no-th" -> disable TemplateHaskell
1453 "ffi" -> enable ForeignFunctionInterface
1454 "no-ffi" -> disable ForeignFunctionInterface
1455 "fi" -> enable ForeignFunctionInterface
1456 "no-fi" -> disable ForeignFunctionInterface
1457 "monomorphism-restriction" -> enable MonomorphismRestriction
1458 "no-monomorphism-restriction" -> disable MonomorphismRestriction
1459 "mono-pat-binds" -> enable MonoPatBinds
1460 "no-mono-pat-binds" -> disable MonoPatBinds
1461 "allow-undecidable-instances" -> enable UndecidableInstances
1462 "no-allow-undecidable-instances" -> disable UndecidableInstances
1463 "allow-incoherent-instances" -> enable IncoherentInstances
1464 "no-allow-incoherent-instances" -> disable IncoherentInstances
1465 "arrows" -> enable Arrows
1466 "no-arrows" -> disable Arrows
1467 "generics" -> enable Generics
1468 "no-generics" -> disable Generics
1469 "implicit-prelude" -> enable ImplicitPrelude
1470 "no-implicit-prelude" -> disable ImplicitPrelude
1471 "implicit-params" -> enable ImplicitParams
1472 "no-implicit-params" -> disable ImplicitParams
1473 "bang-patterns" -> enable BangPatterns
1474 "no-bang-patterns" -> disable BangPatterns
1475 "scoped-type-variables" -> enable ScopedTypeVariables
1476 "no-scoped-type-variables" -> disable ScopedTypeVariables
1477 "extended-default-rules" -> enable ExtendedDefaultRules
1478 "no-extended-default-rules" -> disable ExtendedDefaultRules
1480 ghcExtension
"-cpp" = enable CPP
1481 ghcExtension _
= Nothing
1483 enable e
= Just
(EnableExtension e
)
1484 disable e
= Just
(DisableExtension e
)
1486 rmRtsOpts
:: [String] -> [String]
1487 rmRtsOpts
("-with-rtsopts":_
:xs
) = rmRtsOpts xs
1488 rmRtsOpts
(x
:xs
) = x
: rmRtsOpts xs
1492 checkCCOptions
:: PackageDescription
-> [PackageCheck
]
1493 checkCCOptions
= checkCLikeOptions
"C" "cc-options" ccOptions
1495 checkCxxOptions
:: PackageDescription
-> [PackageCheck
]
1496 checkCxxOptions
= checkCLikeOptions
"C++" "cxx-options" cxxOptions
1498 checkCLikeOptions
:: String -> String -> (BuildInfo
-> [String]) -> PackageDescription
-> [PackageCheck
]
1499 checkCLikeOptions label prefix accessor pkg
=
1502 checkAlternatives prefix
"include-dirs"
1503 [ (flag
, dir
) | flag
@('-':'I
':dir
) <- all_cLikeOptions
]
1505 , checkAlternatives prefix
"extra-libraries"
1506 [ (flag
, lib
) | flag
@('-':'l
':lib
) <- all_cLikeOptions
]
1508 , checkAlternatives prefix
"extra-lib-dirs"
1509 [ (flag
, dir
) | flag
@('-':'L
':dir
) <- all_cLikeOptions
]
1511 , checkAlternatives
"ld-options" "extra-libraries"
1512 [ (flag
, lib
) | flag
@('-':'l
':lib
) <- all_ldOptions
]
1514 , checkAlternatives
"ld-options" "extra-lib-dirs"
1515 [ (flag
, dir
) | flag
@('-':'L
':dir
) <- all_ldOptions
]
1517 , checkCCFlags
[ "-O", "-Os", "-O0", "-O1", "-O2", "-O3" ] $
1518 PackageDistSuspicious
(COptONumber prefix label
)
1521 where all_cLikeOptions
= [ opts | bi
<- allBuildInfo pkg
1522 , opts
<- accessor bi
]
1523 all_ldOptions
= [ opts | bi
<- allBuildInfo pkg
1524 , opts
<- ldOptions bi
]
1526 checkCCFlags
:: [String] -> PackageCheck
-> Maybe PackageCheck
1527 checkCCFlags flags
= check
(any (`
elem` flags
) all_cLikeOptions
)
1529 checkCPPOptions
:: PackageDescription
-> [PackageCheck
]
1530 checkCPPOptions pkg
= catMaybes
1531 [ checkAlternatives
"cpp-options" "include-dirs"
1532 [ (flag
, dir
) | flag
@('-':'I
':dir
) <- all_cppOptions
]
1535 [ PackageBuildWarning
(COptCPP opt
)
1536 | opt
<- all_cppOptions
1537 -- "-I" is handled above, we allow only -DNEWSTUFF and -UOLDSTUFF
1538 , not $ any (`
isPrefixOf` opt
) ["-D", "-U", "-I" ]
1541 all_cppOptions
= [ opts | bi
<- allBuildInfo pkg
, opts
<- cppOptions bi
]
1543 checkAlternatives
:: String -> String -> [(String, String)]
1544 -> Maybe PackageCheck
1545 checkAlternatives badField goodField flags
=
1546 check
(not (null badFlags
)) $
1547 PackageBuildWarning
(OptAlternatives badField goodField flags
)
1548 where (badFlags
, _
) = unzip flags
1556 checkPaths
:: PackageDescription
-> [PackageCheck
]
1558 checkPackageFileNamesWithGlob
1559 [ (kind
== PathKindGlob
, path
)
1560 |
(path
, _
, kind
) <- relPaths
++ absPaths
1563 [ PackageBuildWarning
(RelativeOutside field path
)
1564 |
(path
, field
, _
) <- relPaths
++ absPaths
1565 , isOutsideTree path
]
1567 [ PackageDistInexcusable
(AbsolutePath field path
)
1568 |
(path
, field
, _
) <- relPaths
1569 , isAbsoluteOnAnyPlatform path
]
1571 [ PackageDistInexcusable
(BadRelativePAth field path err
)
1572 |
(path
, field
, kind
) <- relPaths
1573 -- these are not paths, but globs...
1574 , err
<- maybeToList $ case kind
of
1575 PathKindFile
-> isGoodRelativeFilePath path
1576 PathKindGlob
-> isGoodRelativeGlob path
1577 PathKindDirectory
-> isGoodRelativeDirectoryPath path
1580 [ PackageDistInexcusable
$ DistPoint
(Just field
) path
1581 |
(path
, field
, _
) <- relPaths
++ absPaths
1582 , isInsideDist path
]
1584 [ PackageDistInexcusable
(DistPoint Nothing path
)
1585 | bi
<- allBuildInfo pkg
1586 , (GHC
, flags
) <- perCompilerFlavorToList
$ options bi
1588 , isInsideDist path
]
1590 [ PackageDistInexcusable
$
1591 GlobSyntaxError
"data-files" (explainGlobSyntaxError pat err
)
1592 | pat
<- dataFiles pkg
1593 , Left err
<- [parseFileGlob
(specVersion pkg
) pat
]
1596 [ PackageDistInexcusable
1597 (GlobSyntaxError
"extra-source-files" (explainGlobSyntaxError pat err
))
1598 | pat
<- extraSrcFiles pkg
1599 , Left err
<- [parseFileGlob
(specVersion pkg
) pat
]
1602 [ PackageDistInexcusable
$
1603 GlobSyntaxError
"extra-doc-files" (explainGlobSyntaxError pat err
)
1604 | pat
<- extraDocFiles pkg
1605 , Left err
<- [parseFileGlob
(specVersion pkg
) pat
]
1608 isOutsideTree path
= case splitDirectories path
of
1612 isInsideDist path
= case map lowercase
(splitDirectories path
) of
1614 ".":"dist":_
-> True
1617 -- paths that must be relative
1618 relPaths
:: [(FilePath, String, PathKind
)]
1620 [ (path
, "extra-source-files", PathKindGlob
) | path
<- extraSrcFiles pkg
] ++
1621 [ (path
, "extra-tmp-files", PathKindFile
) | path
<- extraTmpFiles pkg
] ++
1622 [ (path
, "extra-doc-files", PathKindGlob
) | path
<- extraDocFiles pkg
] ++
1623 [ (path
, "data-files", PathKindGlob
) | path
<- dataFiles pkg
] ++
1624 [ (path
, "data-dir", PathKindDirectory
) | path
<- [dataDir pkg
]] ++
1625 [ (path
, "license-file", PathKindFile
) | path
<- map getSymbolicPath
$ licenseFiles pkg
] ++
1627 [ [ (path
, "asm-sources", PathKindFile
) | path
<- asmSources bi
] ++
1628 [ (path
, "cmm-sources", PathKindFile
) | path
<- cmmSources bi
] ++
1629 [ (path
, "c-sources", PathKindFile
) | path
<- cSources bi
] ++
1630 [ (path
, "cxx-sources", PathKindFile
) | path
<- cxxSources bi
] ++
1631 [ (path
, "js-sources", PathKindFile
) | path
<- jsSources bi
] ++
1632 [ (path
, "install-includes", PathKindFile
) | path
<- installIncludes bi
] ++
1633 [ (path
, "hs-source-dirs", PathKindDirectory
) | path
<- map getSymbolicPath
$ hsSourceDirs bi
]
1634 | bi
<- allBuildInfo pkg
1637 -- paths that are allowed to be absolute
1638 absPaths
:: [(FilePath, String, PathKind
)]
1640 [ [ (path
, "includes", PathKindFile
) | path
<- includes bi
] ++
1641 [ (path
, "include-dirs", PathKindDirectory
) | path
<- includeDirs bi
] ++
1642 [ (path
, "extra-lib-dirs", PathKindDirectory
) | path
<- extraLibDirs bi
] ++
1643 [ (path
, "extra-lib-dirs-static", PathKindDirectory
) | path
<- extraLibDirsStatic bi
]
1644 | bi
<- allBuildInfo pkg
1647 --TODO: check sets of paths that would be interpreted differently between Unix
1648 -- and windows, ie case-sensitive or insensitive. Things that might clash, or
1649 -- conversely be distinguished.
1651 --TODO: use the tar path checks on all the above paths
1653 -- | Check that the package declares the version in the @\"cabal-version\"@
1656 checkCabalVersion
:: PackageDescription
-> [PackageCheck
]
1657 checkCabalVersion pkg
=
1660 -- check use of test suite sections
1661 checkVersion CabalSpecV1_8
(not (null $ testSuites pkg
)) $
1662 PackageDistInexcusable CVTestSuite
1664 -- check use of default-language field
1665 -- note that we do not need to do an equivalent check for the
1666 -- other-language field since that one does not change behaviour
1667 , checkVersion CabalSpecV1_10
(any isJust (buildInfoField defaultLanguage
)) $
1668 PackageBuildWarning CVDefaultLanguage
1670 , check
(specVersion pkg
>= CabalSpecV1_10
&& specVersion pkg
< CabalSpecV3_4
1671 && any isNothing (buildInfoField defaultLanguage
)) $
1672 PackageBuildWarning CVDefaultLanguageComponent
1674 , checkVersion CabalSpecV1_18
1675 (not . null $ extraDocFiles pkg
) $
1676 PackageDistInexcusable CVExtraDocFiles
1678 , checkVersion CabalSpecV2_0
1679 (not (null (subLibraries pkg
))) $
1680 PackageDistInexcusable CVMultiLib
1682 -- check use of reexported-modules sections
1683 , checkVersion CabalSpecV1_22
1684 (any (not.null.reexportedModules
) (allLibraries pkg
)) $
1685 PackageDistInexcusable CVReexported
1687 -- check use of thinning and renaming
1688 , checkVersion CabalSpecV2_0 usesBackpackIncludes
$
1689 PackageDistInexcusable CVMixins
1691 -- check use of 'extra-framework-dirs' field
1692 , checkVersion CabalSpecV1_24
(any (not . null) (buildInfoField extraFrameworkDirs
)) $
1693 -- Just a warning, because this won't break on old Cabal versions.
1694 PackageDistSuspiciousWarn CVExtraFrameworkDirs
1696 -- check use of default-extensions field
1697 -- don't need to do the equivalent check for other-extensions
1698 , checkVersion CabalSpecV1_10
(any (not . null) (buildInfoField defaultExtensions
)) $
1699 PackageBuildWarning CVDefaultExtensions
1701 -- check use of extensions field
1702 , check
(specVersion pkg
>= CabalSpecV1_10
1703 && any (not . null) (buildInfoField oldExtensions
)) $
1704 PackageBuildWarning CVExtensionsDeprecated
1706 , checkVersion CabalSpecV3_0
(any (not . null)
1707 (concatMap buildInfoField
1711 , extraLibFlavours
])) $
1712 PackageDistInexcusable CVSources
1714 , checkVersion CabalSpecV3_0
(any (not . null) $ buildInfoField extraDynLibFlavours
) $
1715 PackageDistInexcusable
1716 (CVExtraDynamic
$ buildInfoField extraDynLibFlavours
)
1718 , checkVersion CabalSpecV2_2
(any (not . null)
1719 (buildInfoField virtualModules
)) $
1720 PackageDistInexcusable CVVirtualModules
1722 -- check use of "source-repository" section
1723 , checkVersion CabalSpecV1_6
(not (null (sourceRepos pkg
))) $
1724 PackageDistInexcusable CVSourceRepository
1726 -- check for new language extensions
1727 , checkVersion CabalSpecV1_2
(not (null mentionedExtensionsThatNeedCabal12
)) $
1728 PackageDistInexcusable
1729 (CVExtensions CabalSpecV1_2 mentionedExtensionsThatNeedCabal12
)
1731 , checkVersion CabalSpecV1_4
(not (null mentionedExtensionsThatNeedCabal14
)) $
1732 PackageDistInexcusable
1733 (CVExtensions CabalSpecV1_4 mentionedExtensionsThatNeedCabal14
)
1735 , check
(specVersion pkg
>= CabalSpecV1_24
1736 && isNothing (setupBuildInfo pkg
)
1737 && buildType pkg
== Custom
) $
1738 PackageBuildWarning CVCustomSetup
1740 , check
(specVersion pkg
< CabalSpecV1_24
1741 && isNothing (setupBuildInfo pkg
)
1742 && buildType pkg
== Custom
) $
1743 PackageDistSuspiciousWarn CVExpliticDepsCustomSetup
1745 , check
(specVersion pkg
>= CabalSpecV2_0
1746 && elem (autogenPathsModuleName pkg
) allModuleNames
1747 && not (elem (autogenPathsModuleName pkg
) allModuleNamesAutogen
) ) $
1748 PackageDistInexcusable CVAutogenPaths
1752 -- Perform a check on packages that use a version of the spec less than
1753 -- the version given. This is for cases where a new Cabal version adds
1754 -- a new feature and we want to check that it is not used prior to that
1756 checkVersion
:: CabalSpecVersion
-> Bool -> PackageCheck
-> Maybe PackageCheck
1757 checkVersion ver cond pc
1758 | specVersion pkg
>= ver
= Nothing
1759 |
otherwise = check cond pc
1761 buildInfoField field
= map field
(allBuildInfo pkg
)
1763 usesBackpackIncludes
= any (not . null . mixins
) (allBuildInfo pkg
)
1765 mentionedExtensions
= [ ext | bi
<- allBuildInfo pkg
1766 , ext
<- allExtensions bi
]
1767 mentionedExtensionsThatNeedCabal12
=
1768 nub (filter (`
elem` compatExtensionsExtra
) mentionedExtensions
)
1770 -- As of Cabal-1.4 we can add new extensions without worrying about
1771 -- breaking old versions of cabal.
1772 mentionedExtensionsThatNeedCabal14
=
1773 nub (filter (`
notElem` compatExtensions
) mentionedExtensions
)
1775 -- The known extensions in Cabal-1.2.3
1778 [ OverlappingInstances
, UndecidableInstances
, IncoherentInstances
1779 , RecursiveDo
, ParallelListComp
, MultiParamTypeClasses
1780 , FunctionalDependencies
, Rank2Types
1781 , RankNTypes
, PolymorphicComponents
, ExistentialQuantification
1782 , ScopedTypeVariables
, ImplicitParams
, FlexibleContexts
1783 , FlexibleInstances
, EmptyDataDecls
, CPP
, BangPatterns
1784 , TypeSynonymInstances
, TemplateHaskell
, ForeignFunctionInterface
1785 , Arrows
, Generics
, NamedFieldPuns
, PatternGuards
1786 , GeneralizedNewtypeDeriving
, ExtensibleRecords
, RestrictedTypeSynonyms
1788 map DisableExtension
1789 [MonomorphismRestriction
, ImplicitPrelude
] ++
1790 compatExtensionsExtra
1792 -- The extra known extensions in Cabal-1.2.3 vs Cabal-1.1.6
1793 -- (Cabal-1.1.6 came with ghc-6.6. Cabal-1.2 came with ghc-6.8)
1794 compatExtensionsExtra
=
1796 [ KindSignatures
, MagicHash
, TypeFamilies
, StandaloneDeriving
1797 , UnicodeSyntax
, PatternSignatures
, UnliftedFFITypes
, LiberalTypeSynonyms
1798 , TypeOperators
, RecordWildCards
, RecordPuns
, DisambiguateRecordFields
1799 , OverloadedStrings
, GADTs
, RelaxedPolyRec
1800 , ExtendedDefaultRules
, UnboxedTuples
, DeriveDataTypeable
1801 , ConstrainedClassMethods
1803 map DisableExtension
1807 (case library pkg
of
1809 (Just lib
) -> explicitLibModules lib
1811 ++ concatMap otherModules
(allBuildInfo pkg
)
1813 allModuleNamesAutogen
= concatMap autogenModules
(allBuildInfo pkg
)
1815 -- ------------------------------------------------------------
1816 -- * Checks on the GenericPackageDescription
1817 -- ------------------------------------------------------------
1819 -- | Check the build-depends fields for any weirdness or bad practice.
1821 checkPackageVersions
:: GenericPackageDescription
-> [PackageCheck
]
1822 checkPackageVersions pkg
=
1825 -- Check that the version of base is bounded above.
1826 -- For example this bans "build-depends: base >= 3".
1827 -- It should probably be "build-depends: base >= 3 && < 4"
1828 -- which is the same as "build-depends: base == 3.*"
1829 check
(not (hasUpperBound baseDependency
)) $
1830 PackageDistInexcusable BaseNoUpperBounds
1834 baseDependency
= case typicalPkg pkg
of
1835 Right
(pkg
', _
) |
not (null baseDeps
) ->
1836 foldr intersectVersionRanges anyVersion baseDeps
1839 [ vr | Dependency pname vr _
<- allBuildDepends pkg
'
1840 , pname
== mkPackageName
"base" ]
1842 -- Just in case finalizePD fails for any reason,
1843 -- or if the package doesn't depend on the base package at all,
1844 -- then we will just skip the check, since hasUpperBound noVersion = True
1847 checkConditionals
:: GenericPackageDescription
-> [PackageCheck
]
1848 checkConditionals pkg
=
1851 check
(not $ null unknownOSs
) $
1852 PackageDistInexcusable
(UnknownOS unknownOSs
)
1854 , check
(not $ null unknownArches
) $
1855 PackageDistInexcusable
(UnknownArch unknownArches
)
1857 , check
(not $ null unknownImpls
) $
1858 PackageDistInexcusable
(UnknownCompiler unknownImpls
)
1861 unknownOSs
= [ os | OS
(OtherOS os
) <- conditions
]
1862 unknownArches
= [ arch | Arch
(OtherArch arch
) <- conditions
]
1863 unknownImpls
= [ impl | Impl
(OtherCompiler impl
) _
<- conditions
]
1864 conditions
= concatMap fvs
(maybeToList (condLibrary pkg
))
1865 ++ concatMap (fvs
. snd) (condSubLibraries pkg
)
1866 ++ concatMap (fvs
. snd) (condForeignLibs pkg
)
1867 ++ concatMap (fvs
. snd) (condExecutables pkg
)
1868 ++ concatMap (fvs
. snd) (condTestSuites pkg
)
1869 ++ concatMap (fvs
. snd) (condBenchmarks pkg
)
1870 fvs
(CondNode _ _ ifs
) = concatMap compfv ifs
-- free variables
1871 compfv
(CondBranch c ct mct
) = condfv c
++ fvs ct
++ maybe [] fvs mct
1872 condfv c
= case c
of
1875 CNot c1
-> condfv c1
1876 COr c1 c2
-> condfv c1
++ condfv c2
1877 CAnd c1 c2
-> condfv c1
++ condfv c2
1879 checkFlagNames
:: GenericPackageDescription
-> [PackageCheck
]
1881 |
null invalidFlagNames
= []
1883 [ PackageDistInexcusable
(SuspiciousFlagName invalidFlagNames
) ]
1887 | flag
<- genPackageFlags gpd
1888 , let fn
= unFlagName
(flagName flag
)
1889 , invalidFlagName fn
1892 invalidFlagName
('-':_
) = True
1894 invalidFlagName cs
= any (not . isAscii) cs
1896 checkUnusedFlags
:: GenericPackageDescription
-> [PackageCheck
]
1897 checkUnusedFlags gpd
1898 | declared
== used
= []
1900 [ PackageDistSuspicious
(DeclaredUsedFlags declared used
) ]
1902 declared
:: Set
.Set FlagName
1903 declared
= toSetOf
(L
.genPackageFlags
. traverse
. L
.flagName
) gpd
1905 used
:: Set
.Set FlagName
1907 [ toSetOf
(L
.condLibrary
. traverse
. traverseCondTreeV
. L
._PackageFlag
) gpd
1908 , toSetOf
(L
.condSubLibraries
. traverse
. _2
. traverseCondTreeV
. L
._PackageFlag
) gpd
1909 , toSetOf
(L
.condForeignLibs
. traverse
. _2
. traverseCondTreeV
. L
._PackageFlag
) gpd
1910 , toSetOf
(L
.condExecutables
. traverse
. _2
. traverseCondTreeV
. L
._PackageFlag
) gpd
1911 , toSetOf
(L
.condTestSuites
. traverse
. _2
. traverseCondTreeV
. L
._PackageFlag
) gpd
1912 , toSetOf
(L
.condBenchmarks
. traverse
. _2
. traverseCondTreeV
. L
._PackageFlag
) gpd
1915 checkUnicodeXFields
:: GenericPackageDescription
-> [PackageCheck
]
1916 checkUnicodeXFields gpd
1917 |
null nonAsciiXFields
= []
1919 [ PackageDistInexcusable
(NonASCIICustomField nonAsciiXFields
) ]
1921 nonAsciiXFields
:: [String]
1922 nonAsciiXFields
= [ n |
(n
, _
) <- xfields
, any (not . isAscii) n
]
1924 xfields
:: [(String,String)]
1925 xfields
= DList
.runDList
$ mconcat
1926 [ toDListOf
(L
.packageDescription
. L
.customFieldsPD
. traverse
) gpd
1927 , toDListOf
(L
.traverseBuildInfos
. L
.customFieldsBI
. traverse
) gpd
1930 -- | cabal-version <2.2 + Paths_module + default-extensions: doesn't build.
1931 checkPathsModuleExtensions
:: PackageDescription
-> [PackageCheck
]
1932 checkPathsModuleExtensions pd
1933 | specVersion pd
>= CabalSpecV2_2
= []
1934 |
any checkBI
(allBuildInfo pd
) ||
any checkLib
(allLibraries pd
)
1935 = return (PackageBuildImpossible RebindableClash
)
1938 mn
= autogenPathsModuleName pd
1940 checkLib
:: Library
-> Bool
1941 checkLib l
= mn `
elem` exposedModules l
&& checkExts
(l ^
. L
.defaultExtensions
)
1943 checkBI
:: BuildInfo
-> Bool
1945 (mn `
elem` otherModules bi || mn `
elem` autogenModules bi
) &&
1946 checkExts
(bi ^
. L
.defaultExtensions
)
1948 checkExts exts
= rebind `
elem` exts
&& (strings `
elem` exts || lists `
elem` exts
)
1950 rebind
= EnableExtension RebindableSyntax
1951 strings
= EnableExtension OverloadedStrings
1952 lists
= EnableExtension OverloadedLists
1954 -- | Checks GHC options from all ghc-*-options fields from the given BuildInfo
1955 -- and reports flags that are OK during development process, but are
1956 -- unacceptable in a distributed package
1957 checkDevelopmentOnlyFlagsBuildInfo
:: BuildInfo
-> [PackageCheck
]
1958 checkDevelopmentOnlyFlagsBuildInfo bi
=
1959 checkDevelopmentOnlyFlagsOptions
"ghc-options" (hcOptions GHC bi
)
1960 ++ checkDevelopmentOnlyFlagsOptions
"ghc-prof-options" (hcProfOptions GHC bi
)
1961 ++ checkDevelopmentOnlyFlagsOptions
"ghc-shared-options" (hcSharedOptions GHC bi
)
1963 -- | Checks the given list of flags belonging to the given field and reports
1964 -- flags that are OK during development process, but are unacceptable in a
1965 -- distributed package
1966 checkDevelopmentOnlyFlagsOptions
:: String -> [String] -> [PackageCheck
]
1967 checkDevelopmentOnlyFlagsOptions fieldName ghcOptions
=
1971 PackageDistInexcusable
(WErrorUnneeded fieldName
)
1974 PackageDistInexcusable
(JUnneeded fieldName
)
1976 , checkFlags
["-fdefer-type-errors"] $
1977 PackageDistInexcusable
(FDeferTypeErrorsUnneeded fieldName
)
1979 -- -dynamic is not a debug flag
1980 , check
(any (\opt
-> "-d" `
isPrefixOf` opt
&& opt
/= "-dynamic")
1982 PackageDistInexcusable
(DynamicUnneeded fieldName
)
1984 , checkFlags
["-fprof-auto", "-fprof-auto-top", "-fprof-auto-calls",
1985 "-fprof-cafs", "-fno-prof-count-entries",
1986 "-auto-all", "-auto", "-caf-all"] $
1987 PackageDistSuspicious
(ProfilingUnneeded fieldName
)
1991 has_Werror
= "-Werror" `
elem` ghcOptions
1995 ('-' : 'j
' : d
: _
) -> isDigit d
1999 checkFlags
:: [String] -> PackageCheck
-> Maybe PackageCheck
2000 checkFlags flags
= check
(any (`
elem` flags
) ghcOptions
)
2002 checkDevelopmentOnlyFlags
:: GenericPackageDescription
-> [PackageCheck
]
2003 checkDevelopmentOnlyFlags pkg
=
2004 concatMap checkDevelopmentOnlyFlagsBuildInfo
2006 |
(conditions
, bi
) <- allConditionalBuildInfo
2007 , not (any guardedByManualFlag conditions
) ]
2009 guardedByManualFlag
= definitelyFalse
2011 -- We've basically got three-values logic here: True, False or unknown
2012 -- hence this pattern to propagate the unknown cases properly.
2013 definitelyFalse
(Var
(PackageFlag n
)) = maybe False not (Map
.lookup n manualFlags
)
2014 definitelyFalse
(Var _
) = False
2015 definitelyFalse
(Lit b
) = not b
2016 definitelyFalse
(CNot c
) = definitelyTrue c
2017 definitelyFalse
(COr c1 c2
) = definitelyFalse c1
&& definitelyFalse c2
2018 definitelyFalse
(CAnd c1 c2
) = definitelyFalse c1 || definitelyFalse c2
2020 definitelyTrue
(Var
(PackageFlag n
)) = fromMaybe False (Map
.lookup n manualFlags
)
2021 definitelyTrue
(Var _
) = False
2022 definitelyTrue
(Lit b
) = b
2023 definitelyTrue
(CNot c
) = definitelyFalse c
2024 definitelyTrue
(COr c1 c2
) = definitelyTrue c1 || definitelyTrue c2
2025 definitelyTrue
(CAnd c1 c2
) = definitelyTrue c1
&& definitelyTrue c2
2027 manualFlags
= Map
.fromList
2028 [ (flagName flag
, flagDefault flag
)
2029 | flag
<- genPackageFlags pkg
2032 allConditionalBuildInfo
:: [([Condition ConfVar
], BuildInfo
)]
2033 allConditionalBuildInfo
=
2034 concatMap (collectCondTreePaths libBuildInfo
)
2035 (maybeToList (condLibrary pkg
))
2037 ++ concatMap (collectCondTreePaths libBuildInfo
. snd)
2038 (condSubLibraries pkg
)
2040 ++ concatMap (collectCondTreePaths buildInfo
. snd)
2041 (condExecutables pkg
)
2043 ++ concatMap (collectCondTreePaths testBuildInfo
. snd)
2044 (condTestSuites pkg
)
2046 ++ concatMap (collectCondTreePaths benchmarkBuildInfo
. snd)
2047 (condBenchmarks pkg
)
2049 -- get all the leaf BuildInfo, paired up with the path (in the tree sense)
2050 -- of if-conditions that guard it
2051 collectCondTreePaths
:: (a
-> b
)
2053 -> [([Condition v
], b
)]
2054 collectCondTreePaths mapData
= go
[]
2056 go conditions condNode
=
2057 -- the data at this level in the tree:
2058 (reverse conditions
, mapData
(condTreeData condNode
))
2061 [ go
(condition
:conditions
) ifThen
2062 |
(CondBranch condition ifThen _
) <- condTreeComponents condNode
]
2065 [ go
(condition
:conditions
) elseThen
2066 |
(CondBranch condition _
(Just elseThen
)) <- condTreeComponents condNode
]
2069 -- ------------------------------------------------------------
2070 -- * Checks involving files in the package
2071 -- ------------------------------------------------------------
2073 -- | Sanity check things that requires IO. It looks at the files in the
2074 -- package and expects to find the package unpacked in at the given file path.
2076 checkPackageFiles
:: Verbosity
-> PackageDescription
-> FilePath -> IO [PackageCheck
]
2077 checkPackageFiles verbosity pkg root
= do
2078 contentChecks
<- checkPackageContent checkFilesIO pkg
2079 preDistributionChecks
<- checkPackageFilesPreDistribution verbosity pkg root
2080 -- Sort because different platforms will provide files from
2081 -- `getDirectoryContents` in different orders, and we'd like to be
2082 -- stable for test output.
2083 return (sort contentChecks
++ sort preDistributionChecks
)
2085 checkFilesIO
= CheckPackageContentOps
{
2086 doesFileExist = System
.doesFileExist . relative
,
2087 doesDirectoryExist = System
.doesDirectoryExist . relative
,
2088 getDirectoryContents = System
.Directory
.getDirectoryContents . relative
,
2089 getFileContents
= BS
.readFile . relative
2091 relative path
= root
</> path
2093 -- | A record of operations needed to check the contents of packages.
2094 -- Used by 'checkPackageContent'.
2096 data CheckPackageContentOps m
= CheckPackageContentOps
{
2097 doesFileExist :: FilePath -> m
Bool,
2098 doesDirectoryExist :: FilePath -> m
Bool,
2099 getDirectoryContents :: FilePath -> m
[FilePath],
2100 getFileContents
:: FilePath -> m BS
.ByteString
2103 -- | Sanity check things that requires looking at files in the package.
2104 -- This is a generalised version of 'checkPackageFiles' that can work in any
2105 -- monad for which you can provide 'CheckPackageContentOps' operations.
2107 -- The point of this extra generality is to allow doing checks in some virtual
2108 -- file system, for example a tarball in memory.
2110 checkPackageContent
:: (Monad m
, Applicative m
)
2111 => CheckPackageContentOps m
2112 -> PackageDescription
2114 checkPackageContent ops pkg
= do
2115 cabalBomError
<- checkCabalFileBOM ops
2116 cabalNameError
<- checkCabalFileName ops pkg
2117 licenseErrors
<- checkLicensesExist ops pkg
2118 setupError
<- checkSetupExists ops pkg
2119 configureError
<- checkConfigureExists ops pkg
2120 localPathErrors
<- checkLocalPathsExist ops pkg
2121 vcsLocation
<- checkMissingVcsInfo ops pkg
2123 return $ licenseErrors
2124 ++ catMaybes [cabalBomError
, cabalNameError
, setupError
, configureError
]
2128 checkCabalFileBOM
:: Monad m
=> CheckPackageContentOps m
2129 -> m
(Maybe PackageCheck
)
2130 checkCabalFileBOM ops
= do
2131 epdfile
<- findPackageDesc ops
2133 -- MASSIVE HACK. If the Cabal file doesn't exist, that is
2134 -- a very strange situation to be in, because the driver code
2135 -- in 'Distribution.Setup' ought to have noticed already!
2136 -- But this can be an issue, see #3552 and also when
2137 -- --cabal-file is specified. So if you can't find the file,
2138 -- just don't bother with this check.
2139 Left _
-> return Nothing
2140 Right pdfile
-> (flip check pc
. BS
.isPrefixOf bomUtf8
)
2141 `
liftM` getFileContents ops pdfile
2142 where pc
= PackageDistInexcusable
(BOMStart pdfile
)
2145 bomUtf8
:: BS
.ByteString
2146 bomUtf8
= BS
.pack
[0xef,0xbb,0xbf] -- U+FEFF encoded as UTF8
2148 checkCabalFileName
:: Monad m
=> CheckPackageContentOps m
2149 -> PackageDescription
2150 -> m
(Maybe PackageCheck
)
2151 checkCabalFileName ops pkg
= do
2152 -- findPackageDesc already takes care to detect missing/multiple
2153 -- .cabal files; we don't include this check in 'findPackageDesc' in
2154 -- order not to short-cut other checks which call 'findPackageDesc'
2155 epdfile
<- findPackageDesc ops
2157 -- see "MASSIVE HACK" note in 'checkCabalFileBOM'
2158 Left _
-> return Nothing
2160 | takeFileName pdfile
== expectedCabalname
-> return Nothing
2161 |
otherwise -> return $ Just
$ PackageDistInexcusable
2162 (NotPackageName pdfile expectedCabalname
)
2164 pkgname
= unPackageName
. packageName
$ pkg
2165 expectedCabalname
= pkgname
<.> "cabal"
2168 -- |Find a package description file in the given directory. Looks for
2169 -- @.cabal@ files. Like 'Distribution.Simple.Utils.findPackageDesc',
2170 -- but generalized over monads.
2171 findPackageDesc
:: Monad m
=> CheckPackageContentOps m
2172 -> m
(Either PackageCheck
FilePath) -- ^<pkgname>.cabal
2175 files
<- getDirectoryContents ops dir
2176 -- to make sure we do not mistake a ~/.cabal/ dir for a <pkgname>.cabal
2177 -- file we filter to exclude dirs and null base file names:
2178 cabalFiles
<- filterM (doesFileExist ops
)
2181 , let (name
, ext
) = splitExtension file
2182 , not (null name
) && ext
== ".cabal" ]
2184 [] -> return (Left
$ PackageBuildImpossible NoDesc
)
2185 [cabalFile
] -> return (Right cabalFile
)
2186 multiple
-> return (Left
$ PackageBuildImpossible
2187 (MultiDesc multiple
))
2189 checkLicensesExist
:: (Monad m
, Applicative m
)
2190 => CheckPackageContentOps m
2191 -> PackageDescription
2193 checkLicensesExist ops pkg
= do
2194 exists
<- traverse
(doesFileExist ops
. getSymbolicPath
) (licenseFiles pkg
)
2196 [ PackageBuildWarning
(UnknownFile fieldname file
)
2197 |
(file
, False) <- zip (licenseFiles pkg
) exists
]
2199 fieldname |
length (licenseFiles pkg
) == 1 = "license-file"
2200 |
otherwise = "license-files"
2202 checkSetupExists
:: Monad m
=> CheckPackageContentOps m
2203 -> PackageDescription
2204 -> m
(Maybe PackageCheck
)
2205 checkSetupExists ops pkg
= do
2206 let simpleBuild
= buildType pkg
== Simple
2207 hsexists
<- doesFileExist ops
"Setup.hs"
2208 lhsexists
<- doesFileExist ops
"Setup.lhs"
2209 return $ check
(not simpleBuild
&& not hsexists
&& not lhsexists
) $
2210 PackageDistInexcusable MissingSetupFile
2212 checkConfigureExists
:: Monad m
=> CheckPackageContentOps m
2213 -> PackageDescription
2214 -> m
(Maybe PackageCheck
)
2215 checkConfigureExists ops pd
2216 | buildType pd
== Configure
= do
2217 exists
<- doesFileExist ops
"configure"
2218 return $ check
(not exists
) $
2219 PackageBuildWarning MissingConfigureScript
2220 |
otherwise = return Nothing
2222 checkLocalPathsExist
:: Monad m
=> CheckPackageContentOps m
2223 -> PackageDescription
2225 checkLocalPathsExist ops pkg
= do
2226 let dirs
= [ (dir
, kind
)
2227 | bi
<- allBuildInfo pkg
2229 [ (dir
, "extra-lib-dirs") | dir
<- extraLibDirs bi
]
2230 ++ [ (dir
, "extra-lib-dirs-static") | dir
<- extraLibDirsStatic bi
]
2231 ++ [ (dir
, "extra-framework-dirs")
2232 | dir
<- extraFrameworkDirs bi
]
2233 ++ [ (dir
, "include-dirs") | dir
<- includeDirs bi
]
2234 ++ [ (getSymbolicPath dir
, "hs-source-dirs") | dir
<- hsSourceDirs bi
]
2235 , isRelativeOnAnyPlatform dir
]
2236 missing
<- filterM (liftM not . doesDirectoryExist ops
. fst) dirs
2237 return [ PackageBuildWarning
(UnknownDirectory kind dir
)
2238 |
(dir
, kind
) <- missing
]
2240 checkMissingVcsInfo
:: (Monad m
, Applicative m
)
2241 => CheckPackageContentOps m
2242 -> PackageDescription
2244 checkMissingVcsInfo ops pkg |
null (sourceRepos pkg
) = do
2245 vcsInUse
<- liftM or $ traverse
(doesDirectoryExist ops
) repoDirnames
2247 then return [ PackageDistSuspicious MissingSourceControl
]
2250 repoDirnames
= [ dirname | repo
<- knownRepoTypes
2251 , dirname
<- repoTypeDirname repo
]
2253 checkMissingVcsInfo _ _
= return []
2255 repoTypeDirname
:: KnownRepoType
-> [FilePath]
2256 repoTypeDirname Darcs
= ["_darcs"]
2257 repoTypeDirname Git
= [".git"]
2258 repoTypeDirname SVN
= [".svn"]
2259 repoTypeDirname CVS
= ["CVS"]
2260 repoTypeDirname Mercurial
= [".hg"]
2261 repoTypeDirname GnuArch
= [".arch-params"]
2262 repoTypeDirname Bazaar
= [".bzr"]
2263 repoTypeDirname Monotone
= ["_MTN"]
2264 repoTypeDirname Pijul
= [".pijul"]
2266 -- ------------------------------------------------------------
2267 -- * Checks involving files in the package
2268 -- ------------------------------------------------------------
2270 -- | Check the names of all files in a package for portability problems. This
2271 -- should be done for example when creating or validating a package tarball.
2273 checkPackageFileNames
:: [FilePath] -> [PackageCheck
]
2274 checkPackageFileNames
= checkPackageFileNamesWithGlob
. zip (repeat True)
2276 checkPackageFileNamesWithGlob
:: [(Bool, FilePath)] -> [PackageCheck
]
2277 checkPackageFileNamesWithGlob files
=
2279 checkWindowsPaths files
2282 |
(_
, file
) <- files
2285 checkWindowsPaths
:: [(Bool, FilePath)] -> Maybe PackageCheck
2286 checkWindowsPaths paths
=
2287 case filter (not . FilePath.Windows
.isValid
. escape
) paths
of
2290 PackageDistInexcusable
(InvalidOnWin
$ map snd ps
)
2292 -- force a relative name to catch invalid file names like "f:oo" which
2293 -- otherwise parse as file "oo" in the current directory on the 'f' drive.
2294 escape
(isGlob
, path
) = (".\\" ++)
2295 -- glob paths will be expanded before being dereferenced, so asterisks
2296 -- shouldn't count against them.
2297 $ map (\c
-> if c
== '*' && isGlob
then 'x
' else c
) path
2299 -- | Check a file name is valid for the portable POSIX tar format.
2301 -- The POSIX tar format has a restriction on the length of file names. It is
2302 -- unfortunately not a simple restriction like a maximum length. The exact
2303 -- restriction is that either the whole path be 100 characters or less, or it
2304 -- be possible to split the path on a directory separator such that the first
2305 -- part is 155 characters or less and the second part 100 characters or less.
2307 checkTarPath
:: FilePath -> Maybe PackageCheck
2309 |
length path
> 255 = Just longPath
2310 |
otherwise = case pack nameMax
(reverse (splitPath path
)) of
2311 Left err
-> Just err
2313 Right
(h
:rest
) -> case pack prefixMax remainder
of
2314 Left err
-> Just err
2316 Right
(_
:_
) -> Just noSplit
2318 -- drop the '/' between the name and prefix:
2319 remainder
= safeInit h
: rest
2322 nameMax
, prefixMax
:: Int
2326 pack _
[] = Left emptyName
2328 | n
> maxLen
= Left longName
2329 |
otherwise = Right
(pack
' maxLen n cs
)
2332 pack
' maxLen n
(c
:cs
)
2333 | n
' <= maxLen
= pack
' maxLen n
' cs
2334 where n
' = n
+ length c
2337 longPath
= PackageDistInexcusable
(FilePathTooLong path
)
2338 longName
= PackageDistInexcusable
(FilePathNameTooLong path
)
2339 noSplit
= PackageDistInexcusable
(FilePathSplitTooLong path
)
2340 emptyName
= PackageDistInexcusable FilePathEmpty
2342 -- --------------------------------------------------------------
2343 -- * Checks for missing content and other pre-distribution checks
2344 -- --------------------------------------------------------------
2346 -- | Similar to 'checkPackageContent', 'checkPackageFilesPreDistribution'
2347 -- inspects the files included in the package, but is primarily looking for
2348 -- files in the working tree that may have been missed or other similar
2349 -- problems that can only be detected pre-distribution.
2351 -- Because Hackage necessarily checks the uploaded tarball, it is too late to
2352 -- check these on the server; these checks only make sense in the development
2353 -- and package-creation environment. Hence we can use IO, rather than needing
2354 -- to pass a 'CheckPackageContentOps' dictionary around.
2355 checkPackageFilesPreDistribution
:: Verbosity
-> PackageDescription
-> FilePath -> IO [PackageCheck
]
2356 -- Note: this really shouldn't return any 'Inexcusable' warnings,
2357 -- because that will make us say that Hackage would reject the package.
2358 -- But, because Hackage doesn't run these tests, that will be a lie!
2359 checkPackageFilesPreDistribution
= checkGlobFiles
2361 -- | Discover problems with the package's wildcards.
2362 checkGlobFiles
:: Verbosity
2363 -> PackageDescription
2365 -> IO [PackageCheck
]
2366 checkGlobFiles verbosity pkg root
=
2367 fmap concat $ for allGlobs
$ \(field
, dir
, glob
) ->
2368 -- Note: we just skip over parse errors here; they're reported elsewhere.
2369 case parseFileGlob
(specVersion pkg
) glob
of
2371 Right parsedGlob
-> do
2372 results
<- runDirFileGlob verbosity
(root
</> dir
) parsedGlob
2373 let individualWarnings
= results
>>= getWarning field glob
2375 [ PackageDistSuspiciousWarn
(GlobNoMatch field glob
)
2376 |
all (not . suppressesNoMatchesWarning
) results
2378 return (noMatchesWarning
++ individualWarnings
)
2380 adjustedDataDir
= if null (dataDir pkg
) then "." else dataDir pkg
2382 [ (,,) "extra-source-files" "." <$> extraSrcFiles pkg
2383 , (,,) "extra-doc-files" "." <$> extraDocFiles pkg
2384 , (,,) "data-files" adjustedDataDir
<$> dataFiles pkg
2387 -- If there's a missing directory in play, since our globs don't
2388 -- (currently) support disjunction, that will always mean there are no
2389 -- matches. The no matches error in this case is strictly less informative
2390 -- than the missing directory error, so sit on it.
2391 suppressesNoMatchesWarning
(GlobMatch _
) = True
2392 suppressesNoMatchesWarning
(GlobWarnMultiDot _
) = False
2393 suppressesNoMatchesWarning
(GlobMissingDirectory _
) = True
2395 getWarning
:: String -> FilePath -> GlobResult
FilePath -> [PackageCheck
]
2396 getWarning _ _
(GlobMatch _
) =
2398 -- Before Cabal 2.4, the extensions of globs had to match the file
2399 -- exactly. This has been relaxed in 2.4 to allow matching only the
2400 -- suffix. This warning detects when pre-2.4 package descriptions are
2401 -- omitting files purely because of the stricter check.
2402 getWarning field glob
(GlobWarnMultiDot file
) =
2403 [ PackageDistSuspiciousWarn
(GlobExactMatch field glob file
) ]
2404 getWarning field glob
(GlobMissingDirectory dir
) =
2405 [ PackageDistSuspiciousWarn
(GlobNoDir field glob dir
) ]
2407 -- | Check that setup dependencies, have proper bounds.
2408 -- In particular, @base@ and @Cabal@ upper bounds are mandatory.
2409 checkSetupVersions
:: GenericPackageDescription
-> [PackageCheck
]
2410 checkSetupVersions pkg
=
2412 |
(name
, vr
) <- Map
.toList deps
2413 , not (hasUpperBound vr
)
2414 , let nameStr
= unPackageName name
2415 , nameStr `
elem` criticalPkgs
2418 criticalPkgs
= ["Cabal", "base"]
2419 deps
= case typicalPkg pkg
of
2421 Map
.fromListWith intersectVersionRanges
2423 | sbi
<- maybeToList $ setupBuildInfo pkgs
'
2424 , Dependency pname vr _
<- setupDepends sbi
2428 PackageDistInexcusable
(UpperBoundSetup nm
)
2430 checkDuplicateModules
:: GenericPackageDescription
-> [PackageCheck
]
2431 checkDuplicateModules pkg
=
2432 concatMap checkLib
(maybe id (:) (condLibrary pkg
) . map snd $ condSubLibraries pkg
)
2433 ++ concatMap checkExe
(map snd $ condExecutables pkg
)
2434 ++ concatMap checkTest
(map snd $ condTestSuites pkg
)
2435 ++ concatMap checkBench
(map snd $ condBenchmarks pkg
)
2437 -- the duplicate modules check is has not been thoroughly vetted for backpack
2438 checkLib
= checkDups
"library" (\l
-> explicitLibModules l
++ map moduleReexportName
(reexportedModules l
))
2439 checkExe
= checkDups
"executable" exeModules
2440 checkTest
= checkDups
"test suite" testModules
2441 checkBench
= checkDups
"benchmark" benchmarkModules
2442 checkDups s getModules t
=
2443 let sumPair
(x
,x
') (y
,y
') = (x
+ x
' :: Int, y
+ y
' :: Int)
2444 mergePair
(x
, x
') (y
, y
') = (x
+ x
', max y y
')
2445 maxPair
(x
, x
') (y
, y
') = (max x x
', max y y
')
2446 libMap
= foldCondTree Map
.empty
2447 (\(_
,v
) -> Map
.fromListWith sumPair
. map (\x
-> (x
,(1, 1))) $ getModules v
)
2448 (Map
.unionWith mergePair
) -- if a module may occur in nonexclusive branches count it twice strictly and once loosely.
2449 (Map
.unionWith maxPair
) -- a module occurs the max of times it might appear in exclusive branches
2451 dupLibsStrict
= Map
.keys
$ Map
.filter ((>1) . fst) libMap
2452 dupLibsLax
= Map
.keys
$ Map
.filter ((>1) . snd) libMap
2453 in if not (null dupLibsLax
)
2454 then [PackageBuildImpossible
2455 (DuplicateModule s dupLibsLax
)]
2456 else if not (null dupLibsStrict
)
2457 then [PackageDistSuspicious
2458 (PotentialDupModule s dupLibsStrict
)]
2461 -- ------------------------------------------------------------
2463 -- ------------------------------------------------------------
2465 quote
:: String -> String
2466 quote s
= "'" ++ s
++ "'"
2468 commaSep
:: [String] -> String
2469 commaSep
= intercalate
", "
2471 dups
:: Ord a
=> [a
] -> [a
]
2472 dups xs
= [ x |
(x
:_
:_
) <- group (sort xs
) ]
2474 fileExtensionSupportedLanguage
:: FilePath -> Bool
2475 fileExtensionSupportedLanguage path
=
2478 extension
= takeExtension path
2479 isHaskell
= extension `
elem`
[".hs", ".lhs"]
2480 isC
= isJust (filenameCDialect extension
)
2482 -- | Whether a path is a good relative path. We aren't worried about perfect
2483 -- cross-platform compatibility here; this function just checks the paths in
2484 -- the (local) @.cabal@ file, while only Hackage needs the portability.
2486 -- >>> let test fp = putStrLn $ show (isGoodRelativeDirectoryPath fp) ++ "; " ++ show (isGoodRelativeFilePath fp)
2488 -- Note that "foo./bar.hs" would be invalid on Windows.
2490 -- >>> traverse_ test ["foo/bar/quu", "a/b.hs", "foo./bar.hs"]
2495 -- Trailing slash is not allowed for files, for directories it is ok.
2498 -- Nothing; Just "trailing slash"
2500 -- Leading @./@ is fine, but @.@ and @./@ are not valid files.
2502 -- >>> traverse_ test [".", "./", "./foo/bar"]
2503 -- Nothing; Just "trailing dot segment"
2504 -- Nothing; Just "trailing slash"
2507 -- Lastly, not good file nor directory cases:
2509 -- >>> traverse_ test ["", "/tmp/src", "foo//bar", "foo/.", "foo/./bar", "foo/../bar"]
2510 -- Just "empty path"; Just "empty path"
2511 -- Just "posix absolute path"; Just "posix absolute path"
2512 -- Just "empty path segment"; Just "empty path segment"
2513 -- Just "trailing same directory segment: ."; Just "trailing same directory segment: ."
2514 -- Just "same directory segment: ."; Just "same directory segment: ."
2515 -- Just "parent directory segment: .."; Just "parent directory segment: .."
2517 -- For the last case, 'isGoodRelativeGlob' doesn't warn:
2519 -- >>> traverse_ (print . isGoodRelativeGlob) ["foo/../bar"]
2520 -- Just "parent directory segment: .."
2522 isGoodRelativeFilePath
:: FilePath -> Maybe String
2523 isGoodRelativeFilePath
= state0
2526 state0
[] = Just
"empty path"
2527 state0
(c
:cs
) | c
== '.' = state1 cs
2528 | c
== '/' = Just
"posix absolute path"
2529 |
otherwise = state5 cs
2532 state1
[] = Just
"trailing dot segment"
2533 state1
(c
:cs
) | c
== '.' = state4 cs
2534 | c
== '/' = state2 cs
2535 |
otherwise = state5 cs
2537 -- after ./ or after / between segments
2538 state2
[] = Just
"trailing slash"
2539 state2
(c
:cs
) | c
== '.' = state3 cs
2540 | c
== '/' = Just
"empty path segment"
2541 |
otherwise = state5 cs
2543 -- after non-first segment's .
2544 state3
[] = Just
"trailing same directory segment: ."
2545 state3
(c
:cs
) | c
== '.' = state4 cs
2546 | c
== '/' = Just
"same directory segment: ."
2547 |
otherwise = state5 cs
2550 state4
[] = Just
"trailing parent directory segment: .."
2551 state4
(c
:cs
) | c
== '.' = state5 cs
2552 | c
== '/' = Just
"parent directory segment: .."
2553 |
otherwise = state5 cs
2555 -- in a segment which is ok.
2557 state5
(c
:cs
) | c
== '.' = state5 cs
2558 | c
== '/' = state2 cs
2559 |
otherwise = state5 cs
2561 -- | See 'isGoodRelativeFilePath'.
2563 -- This is barebones function. We check whether the glob is a valid file
2564 -- by replacing stars @*@ with @x@ses.
2565 isGoodRelativeGlob
:: FilePath -> Maybe String
2566 isGoodRelativeGlob
= isGoodRelativeFilePath
. map f
where
2570 -- | See 'isGoodRelativeFilePath'.
2571 isGoodRelativeDirectoryPath
:: FilePath -> Maybe String
2572 isGoodRelativeDirectoryPath
= state0
2575 state0
[] = Just
"empty path"
2576 state0
(c
:cs
) | c
== '.' = state5 cs
2577 | c
== '/' = Just
"posix absolute path"
2578 |
otherwise = state4 cs
2580 -- after initial ./ or after / between segments
2582 state1
(c
:cs
) | c
== '.' = state2 cs
2583 | c
== '/' = Just
"empty path segment"
2584 |
otherwise = state4 cs
2586 -- after non-first setgment's .
2587 state2
[] = Just
"trailing same directory segment: ."
2588 state2
(c
:cs
) | c
== '.' = state3 cs
2589 | c
== '/' = Just
"same directory segment: ."
2590 |
otherwise = state4 cs
2593 state3
[] = Just
"trailing parent directory segment: .."
2594 state3
(c
:cs
) | c
== '.' = state4 cs
2595 | c
== '/' = Just
"parent directory segment: .."
2596 |
otherwise = state4 cs
2598 -- in a segment which is ok.
2600 state4
(c
:cs
) | c
== '.' = state4 cs
2601 | c
== '/' = state1 cs
2602 |
otherwise = state4 cs
2605 state5
[] = Nothing
-- "."
2606 state5
(c
:cs
) | c
== '.' = state3 cs
2607 | c
== '/' = state1 cs
2608 |
otherwise = state4 cs
2610 -- [Note: Good relative paths]
2612 -- Using @kleene@ we can define an extended regex:
2615 -- import Algebra.Lattice
2617 -- import Kleene.ERE (ERE (..), intersections)
2619 -- data C = CDot | CSlash | CChar
2620 -- deriving (Eq, Ord, Enum, Bounded, Show)
2622 -- reservedR :: ERE C
2623 -- reservedR = notChar CSlash
2625 -- pathPieceR :: ERE C
2626 -- pathPieceR = intersections
2628 -- , ERENot (string [CDot])
2629 -- , ERENot (string [CDot,CDot])
2632 -- filePathR :: ERE C
2633 -- filePathR = optional (string [CDot, CSlash]) <> pathPieceR <> star (char CSlash <> pathPieceR)
2635 -- dirPathR :: ERE C
2636 -- dirPathR = (char CDot \/ filePathR) <> optional (char CSlash)
2638 -- plus :: ERE C -> ERE C
2639 -- plus r = r <> star r
2641 -- optional :: ERE C -> ERE C
2642 -- optional r = mempty \/ r
2645 -- Results in following state machine for @filePathR@
2653 -- | x <= CSlash -> 2
2666 -- | x <= CSlash -> 2
2687 -- | x <= CSlash -> 1
2691 -- | x <= CSlash -> 1
2696 -- TODO: What we really want to do is test if there exists any
2697 -- configuration in which the base version is unbounded above.
2698 -- However that's a bit tricky because there are many possible
2699 -- configurations. As a cheap easy and safe approximation we will
2700 -- pick a single "typical" configuration and check if that has an
2701 -- open upper bound. To get a typical configuration we finalise
2702 -- using no package index and the current platform.
2703 typicalPkg
:: GenericPackageDescription
2704 -> Either [Dependency
] (PackageDescription
, FlagAssignment
)
2705 typicalPkg
= finalizePD
2706 mempty defaultComponentRequestedSpec
(const True)
2708 (unknownCompilerInfo
2709 (CompilerId buildCompilerFlavor nullVersion
)
2713 addConditionalExp
:: String -> String
2714 addConditionalExp expl
= expl
++
2715 " Alternatively, if you want to use this, make it conditional based "
2716 ++ "on a Cabal configuration flag (with 'manual: True' and 'default: "
2717 ++ "False') and enable that flag during development."