cabal-install: stage-qualified package configuration (package build:*)#378
cabal-install: stage-qualified package configuration (package build:*)#378andreabedini wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for stage-qualified per-package configuration in cabal.project (e.g. package build:* / package host:*) so options can be applied independently to build-stage vs host-stage packages during staged builds. This is enabled by extending the Cabal fields parser to accept colon-joined section arguments, and then plumbing stage-aware package config through cabal-install’s project parsing and planning.
Changes:
- Cabal-syntax: allow
:inside section header arguments by joining adjacent arg tokens with colons. - cabal-install: introduce
projectConfigStagePackagesand apply stage-qualified config during per-package option lookup and shared/profiling closure computation. - Tests + cleanup: add parser test coverage for stage-qualified stanzas and fix a few validate-only
-Werrorwarnings.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Cabal-syntax/src/Distribution/Fields/Parser.hs | Permits colon-joined section arguments (enables package build:* without quoting). |
| cabal-install/src/Distribution/Client/ProjectPlanning.hs | Makes per-package option lookup and shared/profiling closure stage-aware. |
| cabal-install/src/Distribution/Client/ProjectConfig/Types.hs | Adds projectConfigStagePackages :: MapMappend Stage PackageConfig. |
| cabal-install/src/Distribution/Client/ProjectConfig/Parsec.hs | Parses package <stage>:* stanzas and stores config per stage. |
| cabal-install/src/Distribution/Client/ProjectConfig/Lens.hs | Adds lens for projectConfigStagePackages. |
| cabal-install/src/Distribution/Client/ProjectConfig/Legacy.hs | Initializes projectConfigStagePackages = mempty (legacy parser unsupported). |
| cabal-install/src/Distribution/Client/ProjectConfig/FieldGrammar.hs | Extends ProjectConfig grammar construction with a default for stage packages. |
| cabal-install/parser-tests/Tests/ParserTests.hs | Adds parsec-only helper and a test asserting stage-qualified stanza parsing. |
| cabal-install/parser-tests/Tests/files/project-config-stage-packages/cabal.project | New golden test input for package build:* / package host:*. |
| cabal-install-solver/src/Distribution/Solver/Types/PackagePath.hs | Covers QualBase in pretty-printing/qualifier display. |
| cabal-install-solver/src/Distribution/Solver/Types/PackageConstraint.hs | Ensures constraint scope matching doesn’t accidentally match base-qualified deps. |
| cabal-install-solver/src/Distribution/Solver/Modular/Validate.hs | Removes unused binding to satisfy -Werror under validate. |
| cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs | Removes unused state read to satisfy -Werror under validate. |
| cabal-install-solver/src/Distribution/Solver/Modular/Builder.hs | Avoids unused pattern binding to satisfy -Werror under validate. |
| cabal-install-solver/src/Distribution/Solver/Modular.hs | Drops unused verbosity imports to satisfy -Werror under validate. |
| Cabal-described/src/Distribution/Described.hs | Drops unused verbosity import to satisfy -Werror under validate. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| Nothing -> do | ||
| lift $ parseWarning pos PWTUnknownSection "target package name or * required" | ||
| return () |
| parseName secName = case runParsecParser parser "<parsePackageName>" (fieldLineStreamFromBS secName) of | ||
| Left _ -> do | ||
| parseFailure pos ("Invalid package name" ++ fromUTF8BS secName) | ||
| return Nothing | ||
| Right cfgTarget -> return $ pure cfgTarget |
| -- This is where we merge the options from the project config that | ||
| -- apply to all packages, all project local packages, and to specific | ||
| -- named packages | ||
| global `mappend` local `mappend` perpkg | ||
| -- apply to all packages, all packages of a given stage, all project | ||
| -- local packages, and to specific named packages. Later (more specific) | ||
| -- entries override earlier ones. | ||
| global `mappend` local `mappend` stagecfg `mappend` perpkg |
| <*> blurFieldGrammar L.projectConfigLocalPackages (packageConfigFieldGrammar knownPrograms) | ||
| -- \^ PackageConfig to be applied to locally built packages, specified not inside a stanza | ||
| <*> pure mempty | ||
| where | ||
| -- \^ PackageConfig applied to explicitly named packages | ||
| <*> pure mempty | ||
| where | ||
| -- \^ PackageConfig applied to all packages of a given stage ('package build:*' etc.) | ||
| provenance = Set.singleton (Explicit source) |
These warnings are promoted to errors under validate's -Werror but were masked behind the earlier SolverInstallPlan failure. Clean them up so the build proceeds: - drop unused imports across Dependency, ProjectPlanning(.Types), InLibrary, SetupWrapper, ProjectBuilding.UnpackedPackage, CmdRepl and the InstallPlan and DSL unit-test modules - bind the discarded result of runBuild explicitly (-Wunused-do-bind) - underscore the unused indepGoals parameter in the solver DSL - remove the dead internalSetupMethod, buildTypeAction and selfExecSetupMethod (unexported, unreferenced, not dispatched by runSetupMethod) along with the imports they alone used (Distribution.Make, withEnv/withEnvOverrides/ withExtraPathEnv, System.Environment)
The field parser rejected ':' in a section argument, so a section header such as `package build:pkg` was a parse error. Combine colon-joined argument tokens into a single SectionArg, which lets stage-qualified package stanzas be written unquoted. A colon in this position was previously always an error, so this accepts strictly more input; all Cabal-tests golden parser tests still pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| , -- The legacy parser does not support stage-qualified package stanzas. | ||
| projectConfigStagePackages = mempty |
There was a problem hiding this comment.
For the legacy configuration, the current parse would be qualified as host packages I believe.
There was a problem hiding this comment.
Yes, it should. I will make sure of it.
| package build:* | ||
| shared: False | ||
| executable-dynamic: False | ||
|
|
||
| package host:* | ||
| shared: True |
There was a problem hiding this comment.
Should we test
package *
...
as well? I would assume that applies to build + host?
033b9c3 to
dc184ee
Compare
843fceb to
01d053a
Compare
|
@angerman I think any unqualified name should be "host: + build:". Then |
Add `package <stage>:*` project-file stanzas (e.g. `package build:*`, `package host:*`) so per-package configuration can target a single build stage. The same package can be built in both the build and host stages, so `package *`, top-level fields and `package <name>` cannot distinguish them; a stage qualifier can. - ProjectConfig gains projectConfigStagePackages :: MapMappend Stage PackageConfig (+ lens, parsec parser and field grammar). The legacy parser does not support the new syntax. - Per-package option lookup and the shared/profiling-lib downward-closed property in ProjectPlanning are made stage-aware, so e.g. `package build:* shared: False` keeps the build stage static even when the host stage is built dynamic. - Add a parser test (project-config-stage-packages). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These are latent warnings that -Wincomplete-patterns / -Wunused-imports promote to errors only under validate's -Werror; they predate and are unrelated to the stage-qualified package configuration work below. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
I can kinda see the reasoning. Still wonder if |
dc184ee to
e1b10cc
Compare
…e default stage (validate -Werror) - TestCaseUtils.toQPN: add missing QualIndep case (incomplete-patterns -Werror), mirroring QualIndepSetup which already ignores its independence argument. - PackagePath: render the stage prefix only for Build (new dispStage helper); Host stays invisible as the old DefaultNamespace did. Both Pretty instances. - Package.showI / Message.showOption: revert to the original stage-agnostic format; the stage now lives solely on the QPN. - TestCaseUtils: compare the install plan as a set (sort both sides), since the stage-aware UnitId reshuffled the topological order. Fixes the validate build (unit-tests, mem-use-tests) and reduces /Modular/ failures 89 -> 32. Remaining 32 are pre-existing solver-semantics regressions (independent goals, base shims, reinstall protection, setup-dep merging, build-tool exe staging), not rendering. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds
package <stage>:*project-file stanzas so per-package configuration can target a single build stage.Commits
Cabal-syntax: allow colons in section header arguments — the field parser rejected
:in a section argument, so a header such aspackage build:pkgwas a parse error. Colon-joined argument tokens are now combined into a singleSectionArg, letting stage-qualified package stanzas be written unquoted. This accepts strictly more input; all golden parser tests still pass.cabal-install: stage-qualified package configuration (package build:*) — adds
package build:*/package host:*stanzas. The same package can be built in both the build and host stages, sopackage *, top-level fields andpackage <name>cannot distinguish them; a stage qualifier can.ProjectConfiggainsprojectConfigStagePackages :: MapMappend Stage PackageConfig(+ lens, parsec parser, field grammar). The legacy parser does not support the new syntax.ProjectPlanningare made stage-aware, e.g.package build:* shared: Falsekeeps the build stage static even when the host stage is built dynamic.project-config-stage-packages).fix: cover QualBase and drop redundant import for -Werror (validate) — latent
-Wincomplete-patterns/-Wunused-importswarnings that-Werrorpromotes to errors only under validate; unrelated to the feature above.🤖 Generated with Claude Code