Skip to content

Add module name validation in cabal check command #10816

New issue

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

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

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 13, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cabal/src/Distribution/PackageDescription/Check/Paths.hs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@
module Distribution.PackageDescription.Check.Paths
( checkGlob
, checkPath
, checkPackageFileNamesWithGlob
, fileExtensionSupportedLanguage
, isGoodRelativeDirectoryPath
, isGoodRelativeFilePath
16 changes: 15 additions & 1 deletion Cabal/src/Distribution/PackageDescription/Check/Target.hs
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ import Prelude ()
import Distribution.CabalSpecVersion
import Distribution.Compat.Lens
import Distribution.Compiler
import Distribution.ModuleName (ModuleName)
import Distribution.ModuleName (ModuleName, toFilePath)
import Distribution.Package
import Distribution.PackageDescription
import Distribution.PackageDescription.Check.Common
@@ -61,6 +61,8 @@ checkLibrary
_libVisibility_
libBuildInfo_
) = do
mapM_ checkModuleName (explicitLibModules lib)

checkP
(libName_ == LMainLibName && isSub)
(PackageBuildImpossible UnnamedInternal)
@@ -144,6 +146,8 @@ checkExecutable
let cet = CETExecutable exeName_
modulePath_ = getSymbolicPath symbolicModulePath_

mapM_ checkModuleName (exeModules exe)

-- § Exe specific checks
checkP
(null modulePath_)
@@ -205,6 +209,9 @@ checkTestSuite
TestSuiteUnsupported tt ->
tellP (PackageBuildWarning $ TestsuiteNotSupported tt)
_ -> return ()

mapM_ checkModuleName (testModules ts)

checkP
mainIsWrongExt
(PackageBuildImpossible NoHsLhsMain)
@@ -257,6 +264,8 @@ checkBenchmark
-- Target type/name (benchmark).
let cet = CETBenchmark benchmarkName_

mapM_ checkModuleName (benchmarkModules bm)

-- § Interface & bm specific tests.
case benchmarkInterface_ of
BenchmarkUnsupported tt@(BenchmarkTypeUnknown _ _) ->
@@ -294,6 +303,11 @@ checkBenchmark
BenchmarkExeV10 _ f -> takeExtension (getSymbolicPath f) `notElem` [".hs", ".lhs"]
_ -> False

-- | Check if a module name is valid on both Windows and Posix systems
checkModuleName :: Monad m => ModuleName -> CheckM m ()
checkModuleName moduleName =
checkPackageFileNamesWithGlob PathKindFile (toFilePath moduleName)

-- ------------------------------------------------------------
-- Build info
-- ------------------------------------------------------------
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: InvalidModuleName
version: 0.1.0.0
license: BSD3
license-file: LICENSE
category: development
author: Foo Bar
maintainer: cabal-dev@haskell.org
build-type: Simple
cabal-version: >=1.10
synopsis: Test for invalid module names
description: Tests that invalid module names are properly rejected by cabal check

library
exposed-modules: Aux
build-depends: base < 5
hs-source-dirs: src
default-language: Haskell2010

executable invalid-exe
main-is: Main.hs
other-modules: Exe.Aux
, Exe.Aux.Test
build-depends: base < 5
hs-source-dirs: exe
default-language: Haskell2010

test-suite invalid-test
type: exitcode-stdio-1.0
main-is: Main.hs
other-modules: Test.Aux
, Test.Aux.Test
build-depends: base < 5
hs-source-dirs: test
default-language: Haskell2010

benchmark invalid-bench
type: exitcode-stdio-1.0
main-is: Main.hs
other-modules: Bench.Aux
, Bench.Aux.Test
build-depends: base < 5
hs-source-dirs: bench
default-language: Haskell2010

Empty file.
Empty file.
10 changes: 10 additions & 0 deletions cabal-testsuite/PackageTests/Check/InvalidModuleName/cabal.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# cabal check
The following errors will cause portability problems on other environments:
Error: [invalid-path-win] The path 'Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Bench/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Bench/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Exe/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Exe/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Test/Aux' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: [invalid-path-win] The path 'Test/Aux/Test' is invalid on Windows, which would cause portability problems for this package. Windows file names cannot contain any of the characters ":*?<>|", and there are a few reserved names including "aux", "nul", "con", "prn", "com{1-9}", "lpt{1-9}" and "clock$".
Error: Hackage would reject this package.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Test.Cabal.Prelude

main = cabalTest $
fails $ cabal "check" []

Empty file.
Empty file.
Empty file.
23 changes: 23 additions & 0 deletions changelog.d/pr-10816.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
synopsis: "Add checks for Windows reserved filenames in module paths"
packages: Cabal cabal-install
prs: #10816
issues: #10295

description: {

On Windows, certain filenames are reserved by the operating system such as
"aux", "con", "prn", "nul", etc. When these names appear in module paths they
can cause build failures on Windows systems.

`cabal check` now properly warns about module paths that contain Windows reserved
filenames, not just filepaths which contain these reserved tokens. These warnings
are controlled by the existing `invalid-win-path` category.

For example, module paths like:
- `Exe.Aux.Test`
- `Test.Aux.Module`
- `Bench.Aux.Helpers`

will now trigger appropriate warnings during `cabal check`.

}