diff --git a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs index 8a369a6d57a..dcf12ec9815 100644 --- a/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs +++ b/cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs @@ -198,7 +198,7 @@ commandLineFlagsToProjectConfig globalFlags NixStyleFlags {..} clientInstallFlag -- split the package config (from command line arguments) into -- those applied to all packages and those to local only. -- - -- for now we will just copy over the ProgramPaths/Args/Extra into + -- for now we will just copy over the ProgramPaths/Extra into -- the AllPackages. The LocalPackages do not inherit them from -- AllPackages, and as such need to retain them. -- @@ -215,7 +215,6 @@ commandLineFlagsToProjectConfig globalFlags NixStyleFlags {..} clientInstallFlag splitConfig :: PackageConfig -> (PackageConfig, PackageConfig) splitConfig pc = (pc , mempty { packageConfigProgramPaths = packageConfigProgramPaths pc - , packageConfigProgramArgs = packageConfigProgramArgs pc , packageConfigProgramPathExtra = packageConfigProgramPathExtra pc , packageConfigDocumentation = packageConfigDocumentation pc }) diff --git a/cabal-install/src/Distribution/Client/ProjectPlanning.hs b/cabal-install/src/Distribution/Client/ProjectPlanning.hs index 10f0120fc92..744ab9fdf85 100644 --- a/cabal-install/src/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/src/Distribution/Client/ProjectPlanning.hs @@ -476,7 +476,6 @@ rebuildInstallPlan verbosity }, projectConfigLocalPackages = PackageConfig { packageConfigProgramPaths, - packageConfigProgramArgs, packageConfigProgramPathExtra } } = do @@ -484,7 +483,6 @@ rebuildInstallPlan verbosity rerunIfChanged verbosity fileMonitorCompiler (hcFlavor, hcPath, hcPkg, progsearchpath, packageConfigProgramPaths, - packageConfigProgramArgs, packageConfigProgramPathExtra) $ do liftIO $ info verbosity "Compiler settings changed, reconfiguring..." @@ -508,7 +506,6 @@ rebuildInstallPlan verbosity hcPkg = flagToMaybe projectConfigHcPkg progdb = userSpecifyPaths (Map.toList (getMapLast packageConfigProgramPaths)) - . userSpecifyArgss (Map.toList (getMapMappend packageConfigProgramArgs)) . modifyProgramSearchPath (++ [ ProgramSearchPathDir dir | dir <- fromNubList packageConfigProgramPathExtra ]) diff --git a/cabal-install/tests/IntegrationTests2.hs b/cabal-install/tests/IntegrationTests2.hs index cb7b7ddfeb1..6403f14fbf3 100644 --- a/cabal-install/tests/IntegrationTests2.hs +++ b/cabal-install/tests/IntegrationTests2.hs @@ -135,6 +135,9 @@ tests config = , testGroup "Regression tests" $ [ testCase "issue #3324" (testRegressionIssue3324 config) + , testCase "program options scope all" (testProgramOptionsAll config) + , testCase "program options scope local" (testProgramOptionsLocal config) + , testCase "program options scope specific" (testProgramOptionsSpecific config) ] ] @@ -1540,6 +1543,96 @@ testRegressionIssue3324 config = when (buildOS /= Windows) $ do where testdir = "regression/3324" +-- | Test global program options are propagated correctly +-- from ProjectConfig to ElaboratedInstallPlan +testProgramOptionsAll :: ProjectConfig -> Assertion +testProgramOptionsAll config0 = do + -- P is a tarball package, Q is a local dir package that depends on it. + (_, elaboratedPlan, _) <- planProject testdir config + let packages = filterConfiguredPackages $ InstallPlan.toList elaboratedPlan + + assertEqual "q" + (Just [ghcFlag]) + (getProgArgs packages "q") + assertEqual "p" + (Just [ghcFlag]) + (getProgArgs packages "p") + where + testdir = "regression/program-options" + programArgs = MapMappend (Map.fromList [("ghc", [ghcFlag])]) + ghcFlag = "-fno-full-laziness" + + -- Insert flag into global config + config = config0 { + projectConfigAllPackages = (projectConfigAllPackages config0) { + packageConfigProgramArgs = programArgs + } + } + +-- | Test local program options are propagated correctly +-- from ProjectConfig to ElaboratedInstallPlan +testProgramOptionsLocal :: ProjectConfig -> Assertion +testProgramOptionsLocal config0 = do + (_, elaboratedPlan, _) <- planProject testdir config + let localPackages = filterConfiguredPackages $ InstallPlan.toList elaboratedPlan + + assertEqual "q" + (Just [ghcFlag]) + (getProgArgs localPackages "q") + assertEqual "p" + Nothing + (getProgArgs localPackages "p") + where + testdir = "regression/program-options" + programArgs = MapMappend (Map.fromList [("ghc", [ghcFlag])]) + ghcFlag = "-fno-full-laziness" + + -- Insert flag into local config + config = config0 { + projectConfigLocalPackages = (projectConfigLocalPackages config0) { + packageConfigProgramArgs = programArgs + } + } + +-- | Test package specific program options are propagated correctly +-- from ProjectConfig to ElaboratedInstallPlan +testProgramOptionsSpecific :: ProjectConfig -> Assertion +testProgramOptionsSpecific config0 = do + (_, elaboratedPlan, _) <- planProject testdir config + let packages = filterConfiguredPackages $ InstallPlan.toList elaboratedPlan + + assertEqual "q" + (Nothing) + (getProgArgs packages "q") + assertEqual "p" + (Just [ghcFlag]) + (getProgArgs packages "p") + where + testdir = "regression/program-options" + programArgs = MapMappend (Map.fromList [("ghc", [ghcFlag])]) + ghcFlag = "-fno-full-laziness" + + -- Insert flag into package "p" config + config = config0 { + projectConfigSpecificPackage = MapMappend (Map.fromList [(mkPackageName "p", configArgs)]) + } + configArgs = mempty { + packageConfigProgramArgs = programArgs + } + +filterConfiguredPackages :: [ElaboratedPlanPackage] -> [ElaboratedConfiguredPackage] +filterConfiguredPackages [] = [] +filterConfiguredPackages (InstallPlan.PreExisting _ : pkgs) = filterConfiguredPackages pkgs +filterConfiguredPackages (InstallPlan.Installed elab : pkgs) = elab : filterConfiguredPackages pkgs +filterConfiguredPackages (InstallPlan.Configured elab : pkgs) = elab : filterConfiguredPackages pkgs + +getProgArgs :: [ElaboratedConfiguredPackage] -> String -> Maybe [String] +getProgArgs [] _ = Nothing +getProgArgs (elab : pkgs) name + | pkgName (elabPkgSourceId elab) == mkPackageName name + = Map.lookup "ghc" (elabProgramArgs elab) + | otherwise + = getProgArgs pkgs name --------------------------------- -- Test utils to plan and build diff --git a/cabal-install/tests/IntegrationTests2/regression/program-options/cabal.project b/cabal-install/tests/IntegrationTests2/regression/program-options/cabal.project new file mode 100644 index 00000000000..f1295f0e625 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/regression/program-options/cabal.project @@ -0,0 +1,2 @@ +packages: p-0.1.tar.gz + q/ diff --git a/cabal-install/tests/IntegrationTests2/regression/program-options/p-0.1.tar.gz b/cabal-install/tests/IntegrationTests2/regression/program-options/p-0.1.tar.gz new file mode 100644 index 00000000000..ba8b45a9cb2 Binary files /dev/null and b/cabal-install/tests/IntegrationTests2/regression/program-options/p-0.1.tar.gz differ diff --git a/cabal-install/tests/IntegrationTests2/regression/program-options/q/Q.hs b/cabal-install/tests/IntegrationTests2/regression/program-options/q/Q.hs new file mode 100644 index 00000000000..d144e58c7cb --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/regression/program-options/q/Q.hs @@ -0,0 +1,5 @@ +module Q where + +import P + +q = p ++ " world" diff --git a/cabal-install/tests/IntegrationTests2/regression/program-options/q/q.cabal b/cabal-install/tests/IntegrationTests2/regression/program-options/q/q.cabal new file mode 100644 index 00000000000..6021a0be186 --- /dev/null +++ b/cabal-install/tests/IntegrationTests2/regression/program-options/q/q.cabal @@ -0,0 +1,8 @@ +name: q +version: 0.1 +build-type: Simple +cabal-version: >= 1.2 + +library + exposed-modules: Q + build-depends: base, p diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Configure.hs b/cabal-install/tests/UnitTests/Distribution/Client/Configure.hs index db90a8d72d4..d131860a4aa 100644 --- a/cabal-install/tests/UnitTests/Distribution/Client/Configure.hs +++ b/cabal-install/tests/UnitTests/Distribution/Client/Configure.hs @@ -6,6 +6,7 @@ import Distribution.Client.CmdConfigure import Test.Tasty import Test.Tasty.HUnit import Control.Monad +import qualified Data.Map as Map import System.Directory import System.FilePath import Distribution.Verbosity @@ -94,6 +95,27 @@ configureTests = testGroup "Configure tests" doesFileExist backup >>= assertBool ("No file found, expected: " ++ backup) + + , testCase "Local program options" $ do + let ghcFlags = ["-fno-full-laziness"] + flags = (defaultNixStyleFlags ()) + { configFlags = mempty + { configVerbosity = Flag silent + , configProgramArgs = [("ghc", ghcFlags)] + } + , projectFlags = mempty + { flagProjectFileName = Flag projectFile } + } + (_, ProjectConfig {..}) <- configureAction' flags [] defaultGlobalFlags + + + assertEqual "global" + Nothing + (Map.lookup "ghc" (getMapMappend (packageConfigProgramArgs projectConfigAllPackages))) + + assertEqual "local" + (Just ghcFlags) + (Map.lookup "ghc" (getMapMappend (packageConfigProgramArgs projectConfigLocalPackages))) ] projectFile :: FilePath diff --git a/changelog.d/pr-7973 b/changelog.d/pr-7973 new file mode 100644 index 00000000000..e6b2e620188 --- /dev/null +++ b/changelog.d/pr-7973 @@ -0,0 +1,9 @@ +synopsis: Apply local options only to local packages +packages: cabal-install +prs: #7973 +issues: #7998 + +description: { +- Command-line `ghc-options` only applies to local packages +- `program-options` stanza only applies to local packages +} diff --git a/doc/cabal-project.rst b/doc/cabal-project.rst index 908dd9e9309..d48f32cca52 100644 --- a/doc/cabal-project.rst +++ b/doc/cabal-project.rst @@ -643,16 +643,13 @@ an external dependency) should be built with ``-fno-state-hack``:: package bytestring ghc-options: -fno-state-hack -``ghc-options`` is not specifically described in this documentation, -but is one of many fields for configuring programs. They take the form -``progname-options`` and ``progname-location``, and -can only be set inside package stanzas. (TODO: They are not supported -at top-level, see :issue:`3579`.) - -At the moment, there is no way to specify an option to apply to all -external packages or all inplace packages. Additionally, it is only -possible to specify these options on the command line for all local -packages (there is no per-package command line interface.) +``ghc-options`` is not specifically described in this documentation, but is one +of many fields for configuring programs. They take the form +``progname-options`` and ``progname-location``, and can be set for all local +packages in a ``program-options`` stanza or under a package stanza. + +On the command line, these options are applied to all local packages. +There is no per-package command line interface. Some flags were added by more recent versions of the Cabal library. This means that they are NOT supported by packages which use Custom setup