Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions cabal-install/src/Distribution/Client/ProjectPlanning.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4647,6 +4647,11 @@ determineCoverageFor configuredPkg plan =

-- | Look up and merge the options from the project config that apply to all
-- packages, all project local packages, and to specific named packages.
--
-- Options are combined as @all-packages <> specific-package <> local@ so
-- that, for local packages, the top-level (and @program-options@) options
-- take precedence over the @package@ stanza, as documented. See
-- <https://github.com/haskell/cabal/issues/8900>.
lookupPerPkgOption
:: (Package pkg, Monoid m)
=> (pkg -> Bool)
Expand All @@ -4657,10 +4662,10 @@ lookupPerPkgOption
-> (PackageConfig -> m)
-> m
lookupPerPkgOption isLocalPkg allPackagesConfig localPackagesConfig perPackageConfig pkg f =
global `mappend` local `mappend` perpkg
global `mappend` perpkg `mappend` local
where
global = f allPackagesConfig
perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig)
local
| isLocalPkg pkg = f localPackagesConfig
| otherwise = mempty
perpkg = maybe mempty f (Map.lookup (packageName pkg) perPackageConfig)
40 changes: 40 additions & 0 deletions cabal-install/tests/IntegrationTests2.hs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ tests config =
, testCase "program options scope all" (testProgramOptionsAll config)
, testCase "program options scope local" (testProgramOptionsLocal config)
, testCase "program options scope specific" (testProgramOptionsSpecific config)
, testCase "program options scope combined" (testProgramOptionsCombined config)
]
, dependentTestGroup
"Flag tests"
Expand Down Expand Up @@ -2112,6 +2113,45 @@ testProgramOptionsSpecific config0 = do
{ packageConfigProgramArgs = programArgs
}

-- | Test that program options specified at the top level (via the
-- @program-options@ stanza) are applied *after* the ones specified for a
-- specific package, so that they can override them (see #8900).
testProgramOptionsCombined :: ProjectConfig -> Assertion
testProgramOptionsCombined config0 = do
(_, elaboratedPlan, _) <- planProject testdir config
let packages = filterConfiguredPackages $ InstallPlan.toList elaboratedPlan

assertEqual
"q"
(Just [ghcSpecificFlag, ghcLocalFlag])
(getProgArgs packages "q")
assertEqual
"p"
Nothing
(getProgArgs packages "p")
where
testdir = "regression/program-options"
ghcLocalFlag = "-fno-full-laziness"
ghcSpecificFlag = "-fno-float-in"

localArgs = MapMappend (Map.fromList [("ghc", [ghcLocalFlag])])
specificConfig =
mempty
{ packageConfigProgramArgs = MapMappend (Map.fromList [("ghc", [ghcSpecificFlag])])
}

-- Insert a flag into the local config and a different one into the
-- specific package "q" config.
config =
config0
{ projectConfigLocalPackages =
(projectConfigLocalPackages config0)
{ packageConfigProgramArgs = localArgs
}
, projectConfigSpecificPackage =
MapMappend (Map.fromList [(mkPackageName "q", specificConfig)])
}

filterConfiguredPackages :: [ElaboratedPlanPackage] -> [ElaboratedConfiguredPackage]
filterConfiguredPackages [] = []
filterConfiguredPackages (InstallPlan.PreExisting _ : pkgs) = filterConfiguredPackages pkgs
Expand Down
6 changes: 6 additions & 0 deletions cabal-testsuite/PackageTests/ProgramOptions/Main.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module Main where

main :: IO ()
main = do
let unused = 42
putStrLn "hello"
10 changes: 10 additions & 0 deletions cabal-testsuite/PackageTests/ProgramOptions/T8900.cabal
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
cabal-version: 2.4
name: T8900
version: 0.1.0.0
build-type: Simple

executable T8900
main-is: Main.hs
build-depends: base
default-language: Haskell2010
ghc-options: -Wall
4 changes: 4 additions & 0 deletions cabal-testsuite/PackageTests/ProgramOptions/cabal.project
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
packages: .

package T8900
ghc-options: -Werror
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
program-options
ghc-options: -Wwarn
10 changes: 10 additions & 0 deletions cabal-testsuite/PackageTests/ProgramOptions/cabal.test.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Test.Cabal.Prelude

-- Test for issue #8900: `ghc-options` order when combining multiple
-- configuration files. The `program-options` stanza in `cabal.project.local`
-- must be applied after `package <name> ghc-options` in `cabal.project`, so
-- that `-Wwarn` can override `-Werror`.
main = cabalTest $ recordMode DoNotRecord $ do
skipUnlessGhcVersion ">= 8.8"
r <- cabal' "v2-build" ["all"]
assertOutputContains "warning:" r
20 changes: 20 additions & 0 deletions cabal-testsuite/static/Main.hs
Original file line number Diff line number Diff line change
@@ -1,4 +1,24 @@
{-# LANGUAGE CPP #-}
module Main where

import Control.Monad.Catch ()
import Control.Monad.Trans.Class ()
import Data.ByteString ()
import Data.Set ()
import Data.Time ()
import Distribution.Simple ()
import Distribution.Simple.SetupHooks ()
import Distribution.Types.Version ()
import System.Directory ()
import System.FilePath ()
import System.Process ()
import Test.Cabal.Run ()

#ifdef mingw32_HOST_OS
import System.Win32 ()
#else
import System.Posix ()
#endif

main :: IO ()
main = return ()
13 changes: 13 additions & 0 deletions changelog.d/12263.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
synopsis: Fix ghc-options order when combining multiple configuration files
packages: [cabal-install]
prs: 12263
issues: 8900
---

Options specified at the top level of a project (including the
`program-options` stanza) now take precedence over options specified in a
`package <name>` stanza for local packages, matching the documented behavior.
Previously the `package <name>` options were applied last, so e.g.
`program-options ghc-options: -Wwarn` in `cabal.project.local` could not
override `-Werror` set via `package <name> ghc-options` in `cabal.project`.
Loading