cabal
cabal copied to clipboard
Replace cabal project parsing with Parsec
Implements #6101, #7748. Finally ready for review!
Please include the following checklist in your PR:
- [x] Patches conform to the coding conventions.
- [x] Any changes that could be relevant to users have been recorded in the changelog.
- [x] The documentation has been updated, if necessary. (I don't think it's necessary, correct me if I'm wrong)
- [x] Manual QA notes have been included (not needed as this change is invisible to users)
- [x] Tests have been added. (Ask for help if you don’t know how to write them! Ask for an exemption if tests are too complex for too little coverage!)
In this PR I implemented #6101 to replace the legacy cabal.project parser (module Distribution.Client.ProjectConfig.Legacy
) with an implementation based on Parsec.
My implementation is based heavily on the existing Parsec parser of .cabal files, see module Distribution.PackageDescription.Parsec
.
My goal was to recreate the exact grammar the Legacy Parser parses using the modern Parsec framework with FieldGrammars etc.
This means the Legacy Parser and Parsec Parser should always return the same ProjectConfig value for a file (at least in this PR).
About CI: All of the validation checks of Ubuntu are running, unfortunately windows-latest ghc-9.10.1 fails, but windows ghc-9.8.2 succeeds.
The PR consists of several main parts:
Main Entrypoint Distribution.Client.ProjectConfig.readProjectFileSkeleton
The main entrypoint into the Parsec parser is in function readProjectFileSkeleton
in Distribution.Client.ProjectConfig
and parses a cabal.project file.
Note that the legacy parser can be executed still via readProjectFileSkeletonLegacy
in the same file, I want to remove it but in another ticket because this PR is huge already.
My current implementation of readProjectFileSkeleton
also calls readProjectFileSkeletonLegacy
to compare the Parsec value to the legacy value, throwing errors if they are not equal.
Currently I use it to verify that the parsers' grammars match.
I will delete this functionality when the PR is ready to merge, but for now I will let the functionality stay in the PR so reviewers can try to build other projects to verify the parsers' values to not diverge.
Note that because .project files are parsed by both the Legacy parser and the Parsec parser, all warnings are currently emitted twice - once by each parser.
The function readProjectFileSkeleton
currently uses an old variant of readAndParseFile
from Cabal/src/Distribution/Simple/PackageDescription.hs
(new variant is here) that is not based on SymbolicPaths yet but uses FilePath instead.
If we want to migrate it to use SymbolicPaths I need some help here :) Maybe this should be part of a future ticket too.
readProjectFileSkeleton
calls Distribution.Client.ProjectConfig.Parsec.parseProject
which leads me to the next main part:
Module Distribution.Client.ProjectConfig.Parsec
This module contains the Parsec parser of ProjectConfigs.
Function parseProject
is a copy of function parseProject
of the Legacy parser (Distribution.Client.ProjectConfig.Legacy.parseProject
) but it now calls the Parsec version of parseProjectSkeleton
.
parseProjectSkeleton
parseProjectSkeleton
is a port of function parseProjectSkeleton
of module Distribution.Client.ProjectConfig.Legacy
.
It does not use the deprecated type Field
from Distribution.Deprecated.ParseUtils
anymore but Distribution.Fields.Field
instead.
I tried to change as little as possible here, so we still parse the fields/sections into ProjectConfigs, import and parse other cabal.project files and process the conditional structure.
An interesting bit includes the new processing of imports (Fields with name equaling "import"):
We need to use liftPR
to be able to compose ParseResults
that involve IO
actions (for example downloading imported cabal.project files via HTTP).
Composing two actions involves executing a ParseResult
resulting in a PRState
and executing another ParseResult
passing in the previous PRState
.
Unfortunately the PRState
that is generated when executing a ParseResult
does not contain the file source where the warnings/errors came from.
So we need to print any warnings/errors that came up when parsing an imported file before we return the ParseResult, otherwise we lose the source file of the warnings/errors.
I added the implementation of liftPR for Parsec ParseResults to module Distribution.Fields.ParseResult
because I needed its constructor.
Please pay special attention to reviewing this implementation, as it was quite complex to develop.
It works in the tests :)
Another interesting bit is function fieldsToConfig
in parseProjectSkeleton
. Here we produce ProjectConfig values by parsing the current fields with a FieldGrammar
. Afterwards we parse the sections (such as source-repository-package, ...) with function goSections
.
FieldGrammar
The ProjectConfig
FieldGrammar is defined in module Distribution.Client.ProjectConfig.FieldGrammar
.
It took me some while to reverse engineer all the possible field names and find out their named field equivalents in the ProjectConfig
record, but it should be complete now.
Parsing of sections such as source-repository-package
is not done in here, see the next point below.
There are some fields such as projectConfigDryRun
, projectConfigOnlyDeps
that afaik can not be specified in a cabal.project file and need to be passed in via command line flags.
They are marked by comments in the following form: -- cli flag: projectConfigDryRun
.
I also needed to add some Parsec
instances that I added to the modules defining the respective type.
For example the Parsec instance of OptimisationLevel
is in module Distribution.Simple.Compiler
directly below the type definition.
Parsing of Sections
Parsing of sections happens in a StateT
monad (SectionParser
) modifying the ProjectConfig
we got out of the FieldGrammar.
For the SectionParser I took a lot of inspiration again from the parser of .cabal files in module Distribution.PackageDescription.Parsec
, see type SectionParser
.
Currently I need to implement parsing of repository
sections here as I've missed it until now but I hope it is the last type of section that is missing.
Integration Tests in cabal-testsuite/PackageTests/ProjectConfig/Parsec/cabal.test.hs A suite of integration tests. Parsing values and comparing them to expectations. Note that I also run the legacy parser here to make sure my expected values do not differ from the non-Parsec implementation, this will be removed in the future.
Furthermore, I've tested the implementation by successfully building the following Haskell repositories: http2, cabal, tls, hashable, hspec, ghc-lib-parser, texmath, text, lens, megaparsec.
Future PRs There are also other aspects that I want to address, but I want to do this in future PRs because the current one is too big already:
- Add WarningTests/ErrorTests similar to
Cabal-tests/tests/ParserTests.warningTests
to test the correct output of warnings/errors of the Parsec parser - Use treeDiff in the integration tests to compare the parsed values with expectations for easier identification of differences
- Remove unused code from
Distribution/Client/ProjectConfig/Legacy.hs
@ulysses4ever as announced, here is an early PR of the changes. Still lots of work, but I have a rough outline of the ticket. I would be glad if you would take a look!
Thanks @jgotoh ! Will take a look eventually.
@gbaz you know this code better than anyone currently active, i think. Would you be able to provide guidance?
@grayjay I know you’re more of a solver person, but if you happen to have some time for advising and feel comfortable in this part of the code, your contribution would be priceless.
@jgotoh there's a bi-weekly cabal devs meeting, where, I am sure, people would be delighted to hear your experience so far. The closest one is this Thursday (Apr 20th), 1 PM Eastern Time (US). The link to a Jitsi video call is posted before the meeting on #hackage at libera.chat (can be browsed using Element/Matrix or an IRC client). Are you interested?
@ulysses4ever Thank you very much for you invitation! I've already wondered about the cabal devs main communication channel. I am definitely interested and will be glad to attend :)
@jgotoh cool! let me know if you want me to mail you the jitsi link beforehand.
@grayjay I know you’re more of a solver person, but if you happen to have some time for advising and feel comfortable in this part of the code, your contribution would be priceless.
I'm not familiar with this part of the code, but I tried to answer a couple questions based on my understanding of the parser behavior.
@jgotoh Is there anyway I can help you with this?
@andreabedini many thanks for your offer! I will push some changes this week adding ProjectConfig.projectConfigBuildOnly
. This means around 50% of parsing of ProjectConfigs is done then.
What is missing afterwards is parsing Conditionals into the CondTree structure. I've concentrated more on ProjectConfigs for now, but if you have some spare time you could support me here! Also, I will talk about the current state of the PR in the next dev meeting this thursday, you can join if you want :) see this comment: https://github.com/haskell/cabal/pull/8889#issuecomment-1512301652
Also ongoing small reviews of the code I push are helpful if you spot anything.
Also, I will talk about the current state of the PR in the next dev meeting this thursday, you can join if you want :)
Thank you for the invite, but unfortunately that would be 3:00 am here :smile: :disappointed: I might just go through the PR in my own time and leave some comment (if there's anything I can comment on).
@jgotoh re tests: there is some documentation in cabal-testsuite/README.md
.
It should work like this:
cabal build cabal
cabal run cabal-testsuite:cabal-tests -- --with-cabal=$(cabal list-bin cabal)
you can also use the validate.sh
script
❯ ./validate.sh --help
./validate.sh - build & test
Usage: ./validate.sh [options]
A script which runs all the tests.
Available options:
-j, --jobs JOBS cabal v2-build -j argument (default: 4)
--libonly Test only Cabal-the-library
--cli Test both Cabal-the-library and cabal-install
--(no-)run-lib-tests Run library tests
--(no-)run-cli-tests Run client tests
--(no-)run-lib-suite Run cabal-testsuite with library
--(no-)run-cli-suite Run cabal-testsuite with client
-w, --with-compiler HC With compiler
--with-cabal CABAL With cabal-install
--extra-hc HC Extra compiler to run test-suite with
--(no-)doctest Run doctest on library
--(no-)solver-benchmarks Build and trial run solver-benchmarks
--complete-hackage-tests Run hackage-tests on complete Hackage data
--partial-hackage-tests Run hackage-tests on parts of Hackage data
-v, --verbose Verbose output
-q, --quiet Less output
-s, --step STEP Run only specific step (can be specified multiple times)
--list-steps List steps and build-targets and exit
--help Print this message and exit
or just rely on the CI :) <3
Thanks for your message @andreabedini :) Migrating the tests to cabal-testsuite was easier than I expected. Do you think it is okay like I did it? See cabal-testsuite/PackageTests/ProjectConfig/Parsec/cabal.test.hs
At the cabal call today, people suggested to try using the clc-stackage list of packages to try the new parser out and maybe compare its result to the old parser to find any divergence. Since simply building packages from Hackage doesn't get to exercising project files, Rodrigo noted that using the list of packages one could write a bash script (or alike) to cabal get -s $package
to get a local checkout of the source repository of $package
, which may hold one or several project files. This won't work for every package because not all of them specify the source repository in their package description. But hopefully enough of them do.
You could even scrape all project files available this way and put them in a separate repo with a harness to perform regression testing for the parser going forward, perhaps...
The problem with that is the practical point of Stackage: packages will get dropped if they go unmaintained. This is why you can't jujst scrape Hackage, there's a lot of dead packages on there and no good way to select the maintained ones, whereas Stackage is actively curated.
@geekosaur I'm confused: I totally agree with all that you said and don't believe anything I said contradicts with any of this. By all means, let's try stackage (clc-stackage contains an easier on system dependencies subset of it, I believe). The proposed regression suite may be updated following Stackage updates. Although, I'm not sure that a package falling out of Stackage should also be excluded from a test suite for a parser.
Yes, I suppose if we're only parsing then it shouldn't be a problem. Hopefully.
I think the testing approach described to me by Rodrigo sounds sensible.
- Test all cabal.project files found in stackage packages => if they work then merge the PR
- Keep the legacy codepath until the final release (can be tested in prereleases)
- Disable legacy parsing option at final release.
Introducing a new configuration flag seems quite defensive given the extent of this testing imo.
If I understand correctly this will allow deleting LegacyProjectConfig
and all those legacy types and associated conversion functions, that's great news if so. I will try to review this PR.
Here is a simple executable you can easily use to just test parsing of cabal.project
files.
https://gist.github.com/mpickering/9ac21a3730388d7260e7c0c50a80c290
Using cabal get -s
is not the best workflow as many repo urls on hackage don't work and the timeout is very long so the cloning is slow. However, it seems be the best way to get a lot of cabal.project files to test on. The ones I tested so far all worked perfectly.
I found at least one cabal.project
which is broken:
[nix-shell:~/cabal-bisect]$ cat /home/matt/testing-parser/81ddc2e5bf61c7645d42a39530408292/bin/cabal.project
packages: bin
packages: fin
packages: ral
packages: vec
packages: ral-lens
packages: vec-lens
packages: ral-optics
packages: vec-optics
packages: tests
tests: True
benchmarks: True
package dec
ghc-options: -Wall
package fin
ghc-options: -Wall
package vec
ghc-options: -Wall
-- constraints: vec -distributive
-- constraints: vec -semigroupoids
-- constraints: vec -adjunctions
-- constraints: ral -distributive
-- constraints: ral -semigroupoids
-- constraints: ral -adjunctions
-- allow-newer: parallel-3.2.2.0:base
allow-newer: cassava-0.5.2.0:base
allow-newer: vector-th-unbox-0.2.1.7:base
allow-newer: vector-th-unbox-0.2.1.7:template-haskell
bin_out bin_out_legacy
CondNode {condTreeData = ProjectConfig {projectPackages = ["bin"
CondNode {condTreeData = ProjectConfig {projectPackages = ["bin" CondNode {condTreeData = ProjectConfig {projectPackages = ["bin"
"fin" "fin"
"ral" "ral"
"vec" "vec"
"ral-lens" "ral-lens"
--- ---
projectConfigConstraints = [] projectConfigConstraints = []
projectConfigPreferences = [] projectConfigPreferences = []
projectConfigCabalVersion = NoFlag projectConfigCabalVersion = NoFlag
projectConfigSolver = NoFlag projectConfigSolver = NoFlag
projectConfigAllowOlder = Nothing projectConfigAllowOlder = Nothing
projectConfigAllowNewer = Just (AllowNewer {unAllowNewer = RelaxDepsSome [RelaxedDep (RelaxDepScopePack projectConfigAllowNewer = Just (AllowNewer {unAllowNewer = RelaxDepsSome [RelaxedDep (RelaxDepScopePack
ageId (PackageIdentifier {pkgName = PackageName "vector-th-unbox" ageId (PackageIdentifier {pkgName = PackageName "cassava"
pkgVersion = mkVersion [0
5
2
0]})) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base"))
RelaxedDep (RelaxDepScopePackageId (PackageIdentifier {pkgName = PackageName "vector-th-unbox"
pkgVersion = mkVersion [0
2
1
7]})) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base"))
RelaxedDep (RelaxDepScopePackageId (PackageIdentifier {pkgName = PackageName "vector-th-unbox"
pkgVersion = mkVersion [0 pkgVersion = mkVersion [0
2 2
1 1
7]})) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-haskell"))]}) 7]})) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-haskell"))]})
projectConfigWriteGhcEnvironmentFilesPolicy = NoFlag projectConfigWriteGhcEnvironmentFilesPolicy = NoFlag
Another failure on graphql-engine
.
Clone https://github.com/hasura/graphql-engine
Raw output: https://gist.github.com/mpickering/61262fbf5e38d17a7a4ac43f1edb68d8
- Problem parsing allow-newer
- ghc-options in incorrect order
- ld options have
"-Wl","--gc-sections"
rather than"-Wl,--gc-sections"
Difference:
[nix-shell:~/cabal-bisect]$ icdiff out out_bad
out out_bad
CondNode {condTreeData = CondNode {condTreeData =
ProjectConfig {projectPackages = ProjectConfig {projectPackages =
["server","server/lib/*/*.cabal","server/forks/*/*.cabal"], projectPackagesOptional = ["server","server/lib/*/*.cabal","server/forks/*/*.cabal"], projectPackagesOptional =
[], projectPackagesRepo = [], projectPackagesRepo =
[SourceRepositoryPackage {srpType = [SourceRepositoryPackage {srpType =
--- ---
[], projectConfigCabalVersion = [], projectConfigCabalVersion =
NoFlag, projectConfigSolver = NoFlag, projectConfigSolver =
NoFlag, projectConfigAllowOlder = NoFlag, projectConfigAllowOlder =
Nothing, projectConfigAllowNewer = Nothing, projectConfigAllowNewer =
Just (AllowNewer {unAllowNewer = Just (AllowNewer {unAllowNewer =
RelaxDepsSome [RelaxedDep (RelaxDepScopePackage (PackageName "th-extras")) RelaxDepModNone (RelaxDepSub RelaxDepsSome [RelaxedDep (RelaxDepScopePackage (PackageName "req")) RelaxDepModNone (RelaxDepSubjectPk
jectPkg (PackageName "template-haskell")),RelaxedDep (RelaxDepScopePackage (PackageName "hedgehog-generi g (PackageName "template-haskell")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-core")) RelaxDepM
c")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "hedgehog"))]}), projectConfigWriteGhcEnvironmentF odNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-core
ilesPolicy = ")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "primitive")),RelaxedDep (RelaxDepScopePackage (Pac
kageName "ekg-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "ghc-prim")),RelaxedDep (RelaxDep
ScopePackage (PackageName "ekg-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),R
elaxedDep (RelaxDepScopePackage (PackageName "ekg-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageNa
me "inspection-testing")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-core")) RelaxDepModNone (Re
laxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-json")) RelaxD
epModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-j
son")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (Packa
geName "ekg-json")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "aeson")),RelaxedDep (RelaxDepScope
Package (PackageName "ekg-json")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "vector")),RelaxedDep
(RelaxDepScopePackage (PackageName "ekg-prometheus")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName
"base")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-prometheus")) RelaxDepModNone (RelaxDepSubje
ctPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-prometheus")) RelaxDepMod
None (RelaxDepSubjectPkg (PackageName "bytestring")),RelaxedDep (RelaxDepScopePackage (PackageName "ekg-
prometheus")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "primitive")),RelaxedDep (RelaxDepScopePa
ckage (PackageName "ekg-prometheus")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),Re
laxedDep (RelaxDepScopePackage (PackageName "relude")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName
"base")),RelaxedDep (RelaxDepScopePackage (PackageName "relude")) RelaxDepModNone (RelaxDepSubjectPkg (P
ackageName "ghc-prim")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql")) RelaxDepModNo
ne (RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-gra
phql")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "relude")),RelaxedDep (RelaxDepScopePackage (Pa
ckageName "morpheus-graphql")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "vector")),RelaxedDep (R
elaxDepScopePackage (PackageName "morpheus-graphql")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "
transformers")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-app")) RelaxDepModNone (
RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql
-app")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "vector")),RelaxedDep (RelaxDepScopePackage (Pa
ckageName "morpheus-graphql-app")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")),Rel
axedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-code-gen")) RelaxDepModNone (RelaxDepSubjec
tPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-code-gen")) R
elaxDepModNone (RelaxDepSubjectPkg (PackageName "optparse-applicative")),RelaxedDep (RelaxDepScopePackag
e (PackageName "morpheus-graphql-code-gen-utils")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "tex
t")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-core")) RelaxDepModNone (RelaxDepSu
bjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-core")) R
elaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")),RelaxedDep (RelaxDepScopePackage (Packa
geName "morpheus-graphql-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "vector")),RelaxedDep
(RelaxDepScopePackage (PackageName "morpheus-graphql-server")) RelaxDepModNone (RelaxDepSubjectPkg (Pack
ageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-server")) RelaxDepModNo
ne (RelaxDepSubjectPkg (PackageName "transformers")),RelaxedDep (RelaxDepScopePackage (PackageName "morp
heus-graphql-server")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "vector")),RelaxedDep (RelaxDepS
copePackage (PackageName "morpheus-graphql-client")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "t
ext")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-client")) RelaxDepModNone (RelaxD
epSubjectPkg (PackageName "req")),RelaxedDep (RelaxDepScopePackage (PackageName "req")) RelaxDepModNone
(RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-
graphql-client")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")),RelaxedDep (RelaxDep
ScopePackage (PackageName "morpheus-graphql-client")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "
vector")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-graphql-subscriptions")) RelaxDepModNo
ne (RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "morpheus-gra
phql-subscriptions")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")),RelaxedDep (Rela
xDepScopePackage (PackageName "servant-openapi3")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "bas
e")),RelaxedDep (RelaxDepScopePackage (PackageName "openapi3")) RelaxDepModNone (RelaxDepSubjectPkg (Pac
kageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-client")) RelaxDepModNone (Rela
xDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-client")) Re
laxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageN
ame "servant-client")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")),RelaxedDep (Rel
axDepScopePackage (PackageName "servant-client")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "mtl"
)),RelaxedDep (RelaxDepScopePackage (PackageName "servant-client-core")) RelaxDepModNone (RelaxDepSubjec
tPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-client-core")) RelaxDe
pModNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "
servant-client-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "free")),RelaxedDep (RelaxDepSco
pePackage (PackageName "servant-client-core")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "templat
e-haskell")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-client-core")) RelaxDepModNone (Rela
xDepSubjectPkg (PackageName "transformers")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-serv
er")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (Packag
eName "servant-server")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (Rel
axDepScopePackage (PackageName "servant-server")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "eith
er")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-server")) RelaxDepModNone (RelaxDepSubjectP
kg (PackageName "bytestring")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-server")) RelaxDep
ModNone (RelaxDepSubjectPkg (PackageName "filepath")),RelaxedDep (RelaxDepScopePackage (PackageName "ser
vant-server")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-haskell")),RelaxedDep (RelaxDe
pScopePackage (PackageName "servant-server")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transfor
mers")),RelaxedDep (RelaxDepScopePackage (PackageName "servant-server")) RelaxDepModNone (RelaxDepSubjec
tPkg (PackageName "mtl")),RelaxedDep (RelaxDepScopePackage (PackageName "servant")) RelaxDepModNone (Rel
axDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "servant")) RelaxDep
ModNone (RelaxDepSubjectPkg (PackageName "mtl")),RelaxedDep (RelaxDepScopePackage (PackageName "ghc-heap
-view")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (Pac
kageName "ghc-heap-view")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "Cabal")),RelaxedDep (RelaxD
epScopePackage (PackageName "servant")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "transformers")
),RelaxedDep (RelaxDepScopePackage (PackageName "singleton-bool")) RelaxDepModNone (RelaxDepSubjectPkg (
PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "semigroupoids")) RelaxDepModNone (Re
laxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "http-api-data")) R
elaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "
validation")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "assoc")),RelaxedDep (RelaxDepScopePackag
e (PackageName "aeson")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "th-abstraction")),RelaxedDep
(RelaxDepScopePackage (PackageName "optics-th")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "th-ab
straction")),RelaxedDep (RelaxDepScopePackage (PackageName "generics-sop")) RelaxDepModNone (RelaxDepSub
jectPkg (PackageName "th-abstraction")),RelaxedDep (RelaxDepScopePackage (PackageName "insert-ordered-co
ntainers")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (
PackageName "lucid2")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepSco
pePackage (PackageName "insert-ordered-containers")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "l
ens")),RelaxedDep (RelaxDepScopePackage (PackageName "uuid-types")) RelaxDepModNone (RelaxDepSubjectPkg
(PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName "uuid-types")) RelaxDepModNone (Rela
xDepSubjectPkg (PackageName "template-haskell")),RelaxedDep (RelaxDepScopePackage (PackageName "string-i
nterpolate")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-haskell")),RelaxedDep (RelaxDep
ScopePackage (PackageName "postgresql-simple")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "time")
),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-simple")) RelaxDepModNone (RelaxDepSubjectPk
g (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-simple")) RelaxDepModN
one (RelaxDepSubjectPkg (PackageName "template-haskell")),RelaxedDep (RelaxDepScopePackage (PackageName
"postgresql-simple")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "bytestring")),RelaxedDep (RelaxD
epScopePackage (PackageName "postgresql-simple")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "text
")),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-simple")) RelaxDepModNone (RelaxDepSubject
Pkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-simple")) Rela
xDepModNone (RelaxDepSubjectPkg (PackageName "postgresql-libpq")),RelaxedDep (RelaxDepScopePackage (Pack
ageName "openapi3")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-haskell")),RelaxedDep (R
elaxDepScopePackage (PackageName "superbuffer")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "bytes
tring")),RelaxedDep (RelaxDepScopePackage (PackageName "websockets")) RelaxDepModNone (RelaxDepSubjectPk
g (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "http-api-data")) RelaxDepMo
dNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "stm
-hamt")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "primitive")),RelaxedDep (RelaxDepScopePackage
(PackageName "stm-hamt")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "primitive-extras")),Relaxed
Dep (RelaxDepScopePackage (PackageName "quickcheck-instances")) RelaxDepModNone (RelaxDepSubjectPkg (Pac
kageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "quickcheck-instances")) RelaxDepModNone
(RelaxDepSubjectPkg (PackageName "bytestring")),RelaxedDep (RelaxDepScopePackage (PackageName "uuid"))
RelaxDepModNone (RelaxDepSubjectPkg (PackageName "uuid-types")),RelaxedDep (RelaxDepScopePackage (Packag
eName "connection")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "tls")),RelaxedDep (RelaxDepScopeP
ackage (PackageName "proto-lens")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep
(RelaxDepScopePackage (PackageName "proto-lens-runtime")) RelaxDepModNone (RelaxDepSubjectPkg (PackageNa
me "base")),RelaxedDep (RelaxDepScopePackage (PackageName "launchdarkly-server-sdk")) RelaxDepModNone (R
elaxDepSubjectPkg (PackageName "lens")),RelaxedDep (RelaxDepScopePackage (PackageName "launchdarkly-serv
er-sdk")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "bytestring")),RelaxedDep (RelaxDepScopePacka
ge (PackageName "launchdarkly-server-sdk")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "text")),Re
laxedDep (RelaxDepScopePackage (PackageName "launchdarkly-server-sdk")) RelaxDepModNone (RelaxDepSubject
Pkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "lrucache")) RelaxDepModNo
ne (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePackage (PackageName "kriti-
lang")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "aeson")),RelaxedDep (RelaxDepScopePackage (Pac
kageName "generic-monoid")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxD
epScopePackage (PackageName "aeson-optics")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),R
elaxedDep (RelaxDepScopePackage (PackageName "testcontainers")) RelaxDepModNone (RelaxDepSubjectPkg (Pac
kageName "bytestring")),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-libpq")) RelaxDepModNo
ne (RelaxDepSubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "xml-lens"))
RelaxDepModNone (RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (RelaxDepScopePackage (PackageName
"xml-lens")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (RelaxDepScopePa
ckage (PackageName "config-ini")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "text")),RelaxedDep (
RelaxDepScopePackage (PackageName "hsc2hs")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "base")),R
elaxedDep (RelaxDepScopePackage (PackageName "xml-conduit")) RelaxDepModNone (RelaxDepSubjectPkg (Packag
eName "Cabal")),RelaxedDep (RelaxDepScopePackage (PackageName "cabal-doctest")) RelaxDepModNone (RelaxDe
pSubjectPkg (PackageName "Cabal")),RelaxedDep (RelaxDepScopePackage (PackageName "postgresql-libpq")) Re
laxDepModNone (RelaxDepSubjectPkg (PackageName "Cabal")),RelaxedDep (RelaxDepScopePackage (PackageName "
hsc2hs")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "filepath")),RelaxedDep (RelaxDepScopePackage
(PackageName "hsc2hs")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "containers")),RelaxedDep (Rel
axDepScopePackage (PackageName "th-extras")) RelaxDepModNone (RelaxDepSubjectPkg (PackageName "template-
haskell")),RelaxedDep (RelaxDepScopePackage (PackageName "hedgehog-generic")) RelaxDepModNone (RelaxDepS
ubjectPkg (PackageName "base")),RelaxedDep (RelaxDepScopePackage (PackageName "hedgehog-generic")) Relax
DepModNone (RelaxDepSubjectPkg (PackageName "hedgehog"))]}), projectConfigWriteGhcEnvironmentFilesPolicy
=
NoFlag, projectConfigMaxBackjumps = NoFlag, projectConfigMaxBackjumps =
NoFlag, projectConfigReorderGoals = NoFlag, projectConfigReorderGoals =
NoFlag, projectConfigCountConflicts = NoFlag, projectConfigCountConflicts =
NoFlag, projectConfigFineGrainedConflicts = NoFlag, projectConfigFineGrainedConflicts =
NoFlag, projectConfigMinimizeConflictSet = NoFlag, projectConfigMinimizeConflictSet =
--- ---
fromList [Explicit (ProjectConfigPath ("cabal.project" :| []))], projectConfigAllPackages = fromList [Explicit (ProjectConfigPath ("cabal.project" :| []))], projectConfigAllPackages =
PackageConfig {packageConfigProgramPaths = PackageConfig {packageConfigProgramPaths =
MapLast {getMapLast = MapLast {getMapLast =
fromList []}, packageConfigProgramArgs = fromList []}, packageConfigProgramArgs =
MapMappend {getMapMappend = MapMappend {getMapMappend =
fromList [("ghc",["-fwrite-ide-info","-optc-fno-builtin-malloc","-optc-fno-builtin-calloc","-optc-fno-b fromList [("ghc",["-optc-fno-builtin-malloc","-optc-fno-builtin-calloc","-optc-fno-builtin-realloc","-o
uiltin-realloc","-optc-fno-builtin-free"])]}, packageConfigProgramPathExtra = ptc-fno-builtin-free","-fwrite-ide-info"])]}, packageConfigProgramPathExtra =
[], packageConfigFlagAssignment = [], packageConfigFlagAssignment =
fromList [], packageConfigVanillaLib = fromList [], packageConfigVanillaLib =
NoFlag, packageConfigSharedLib = NoFlag, packageConfigSharedLib =
NoFlag, packageConfigStaticLib = NoFlag, packageConfigStaticLib =
NoFlag, packageConfigDynExe = NoFlag, packageConfigDynExe =
--- ---
fromList [Explicit (ProjectConfigPath ("cabal.project" :| []))], projectConfigAllPackages = fromList [Explicit (ProjectConfigPath ("cabal.project" :| []))], projectConfigAllPackages =
PackageConfig {packageConfigProgramPaths = PackageConfig {packageConfigProgramPaths =
MapLast {getMapLast = MapLast {getMapLast =
fromList []}, packageConfigProgramArgs = fromList []}, packageConfigProgramArgs =
MapMappend {getMapMappend = MapMappend {getMapMappend =
fromList [("ghc",["-split-sections"]),("ld",["-Wl","--gc-sections"])]}, packageConfigProgramPathExtra = fromList [("ghc",["-split-sections"]),("ld",["-Wl,--gc-sections"])]}, packageConfigProgramPathExtra =
[], packageConfigFlagAssignment = [], packageConfigFlagAssignment =
fromList [], packageConfigVanillaLib = fromList [], packageConfigVanillaLib =
NoFlag, packageConfigSharedLib = NoFlag, packageConfigSharedLib =
NoFlag, packageConfigStaticLib = NoFlag, packageConfigStaticLib =
NoFlag, packageConfigDynExe = NoFlag, packageConfigDynExe =
@jgotoh Do you need help finishing this patch and fixing the remaining few bugs?
@jgotoh Do you need help finishing this patch and fixing the remaining few bugs?
Hi @mpickering, thanks a lot for your support and your tests! I did not have the time yet to look into it, but this week it should work out.
Another failure on
graphql-engine
.Clone https://github.com/hasura/graphql-engine
Raw output: https://gist.github.com/mpickering/61262fbf5e38d17a7a4ac43f1edb68d8
* Problem parsing allow-newer * ghc-options in incorrect order * ld options have `"-Wl","--gc-sections"` rather than `"-Wl,--gc-sections"`
...
Both files you provided are now working. I modified the tests to cover these cases.