-
Notifications
You must be signed in to change notification settings - Fork 697
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
build pkgconfig db individually when bulk fails #8496
Conversation
case exitCode of | ||
ExitSuccess -> (return . pkgConfigDbFromList . zip pkgNames) (lines pkgVersions) | ||
-- if there's a single broken pc file the above fails, so we fall back into calling it individually | ||
_ -> pkgConfigDbFromList . catMaybes <$> mapM (getIndividualVersion pkgConfig) pkgNames |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just always use this code path? Is it that much slower than getting all packages in one call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Depends on the size of the database :-)
cabal-install-solver/src/Distribution/Solver/Types/PkgConfigDb.hs
Outdated
Show resolved
Hide resolved
@gbaz : Not sure how to test this PR without too much effort, because I only experience the
It seems that However, I cannot reproduce the problem on my own Mac. I think it is good if this PR is tested on a macOS Virtual Environment to make sure it fixes the problem I describe, and if successful, a patch should be released as |
The issue you'll see is if any package in Alternately, do you have a way to run your test using a branch of cabal-install? |
With regards to a workaround: I note btw that text-icu with its current cabal file will always fail if there is no pkg-config present on the system, or if icu-uc, or icu-i18n are not registered in it. It would be better to have an auto flag that switches between a build using pkgconfig-depends and a build explicitly enumerating extra-libraries. This is what the pr that started this all was intended to enable :-) #7621 In such a case if the CI busted on pkgconfig-depends, then it will fallback to the explicit extra-libraries etc. This also makes the package somewhat more resilient for end-users. |
I could port your Haskell code to shell land and add it to my CI script. Should be doable (just my shell skills are always rusty or rather chronically underdeveloped...). Maybe |
functional programmers do it with (to be honest i had to google to remember the details)
|
Gotcha: Unfortunately, this means that Such (upstream) blunder also suggests we should have some test involving the P.S.: |
@@ -65,9 +67,14 @@ readPkgConfigDb verbosity progdb = handle ioErrorHandler $ do | |||
-- The output of @pkg-config --list-all@ also includes a description | |||
-- for each package, which we do not need. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As witnessed by
pkg-config
might be present but pkg-config --list-all
might segfault. What is the strategy in such situations? (Maybe building a pkg-config database eagerly isn't so great after all, one could fill it lazily by demand in the solver, could one?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like cabal treats an error in pkg-config --list-all
similarly to the inability to find pkg-config, so the solver would only fail in the case where all potential solutions require at least one pkg-config package.
The solver is currently pure, so querying packages on demand would be a big change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I acknowledge the problem that the solver would not be pure anymore, although it could be made almost pure by placing it into a service monad that only provides a method to resolve a package version via pkg-config (rather than placing it flatly into IO
). Something like:
class Monad m => MonadPkgConfig m where
pkgConfigModVersion :: PackageName -> m PackageVersion
solver :: MonadPkgConfig m => Inputs -> m Output
Lazy querying pkg-config
would solve the problem where pkg-config --modversion
is available but not pkg-config --list-all
.
There are numerous packages out there that unconditionally declare a pkgconfig-depends
(not the least, text-icu
), and these all break (in certain circumstances) in the current approach with pkgconfig --list-all
.
Note also that the contract given to --list-all
is minimal, e.g., my man pkg-config
tells me:
--list-all List all modules found in the pkg-config path.
This does not specify any particular output format, something that cabal
crucially relies on.
In contrast, this is the contract for --modversion
:
--modversion Requests that the version information of the libraries specified on the command line be displayed. If pkg-config can find all the libraries on the command line, each library's version string is printed to stdout, one version per line. In this case pkg-config exits successfully. If one or more libraries is unknown, pkg-con- fig exits with a nonzero code, and the contents of stdout are undefined.
Looks rather more specific (thus, binding) to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Programming around "an external program is segfaulting" seems like its really pushing it, though I do understand a frustration with images being broken. I would again advise that text-icu put in a flag that varies depending on pkg-config being present and working or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, but I'd like to know whether pkg-config --list-all
works at all on macOS-11/12
. Unfortunately, I cannot test it directly as I my machine is still on macOS-10
. Anyone with a recent macOS willing to investigate thie?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, upstream came back with an analysis: Homebrew/homebrew-core#112785
Not that the details matter, but the upshot is that one broken package configuration breaks pkg-config --list-all
and consequently cabal-3.8.1.0
.
So, install imagemagick
or highway
and suddently your haskell packages fail to build with cabal. Nightmare scenario? Yes!
Lesson to learn: stay away from the pkg-config --list-all
path and only query pkg-config
for the packages you are interested in.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another idea is to work around the segfault by not enforcing pkg-config dependencies when pkg-config exists but the --list-all command fails. Not enforcing pkg-config dependencies is the same behavior as before #7621.
I also think that we should merge this PR first, since it already handles one case where a pkg-config command fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a broken pkg-config is the same situation as a missing one -- a hard fail is fine, because the intended user pattern should be that there is an auto flag in the package that can switch to how to handle the case where pkg-config is unavailable (because non-existent or broken).
I am aware that not all packages have that flag that allows this switching. But we should encourage them to add it!
Due to a bug in the highway brew package, pkg-config --list-all segfaults on mac runners (actions/runner-images#6364). In addition, cabal probes pkg-config --list-all despite not needing it (haskell/cabal#8496). Combined, this created an issue where cabal would fail to create a build plan on macOS GitHub Action runners citing a lack of libsodium/pkg-config. The temporary solution is to reinstall the highway brew package since it has now been patched. The long-term solution is to wait for cabal to change its probing behaviour (tracked above), or wait for GitHub Actions runner environments to update so it comes with the patch preinstalled. (side note: I was pursuing this CI bug for over 4 days, unable to find anything relevant on search engines.... until 30 minutes ago, when I hit the jackpot with the right search terms and arrived at the issues above. In fact, the issue was only solved 5 hours ago, and the last comment in the thread was from 22 minutes before I arrived. I felt quite some strong adrenaline flowing through me when I realised how lucky I was today...)
Due to a bug in the highway brew package, pkg-config --list-all segfaults on mac runners (actions/runner-images#6364). In addition, cabal probes pkg-config --list-all despite not needing it (haskell/cabal#8496). Combined, this created an issue where cabal would fail to create a build plan on macOS GitHub Action runners citing a lack of libsodium/pkg-config. The temporary solution is to reinstall the highway brew package since it has now been patched. The long-term solution is to wait for cabal to change its probing behaviour (tracked above), or wait for GitHub Actions runner environments to update so it comes with the patch preinstalled. (side note: I was pursuing this CI bug for over 4 days, unable to find anything relevant on search engines.... until 30 minutes ago, when I hit the jackpot with the right search terms and arrived at the issues above. In fact, the issue was only solved 5 hours ago, and the last comment in the thread was from 22 minutes before I arrived. I felt quite some strong adrenaline flowing through me when I realised how lucky I was today...)
Just checked that this PR fixes the problem for me. |
Could we log that we're taking the fallback path if we do that? Two reasons:
|
Also! Thanks for fixing this! I really appreciate that by the time I found the issue there was already a fix 🙇 |
Added a log on the fallback path, as requested. |
@gbaz: a kind reminder about the label, if you are ready. :) |
@gbaz: I'd set the merge_me label for you, but I don't know if you prefer a squash or not. |
Looks like this needs to be squashed, as intermediate commits have CI failures and some are dubbed fixup. |
@mergify backport 3.8 |
✅ Backports have been created
|
* build pkgconfig db individually when bulk fails * fix typo * changelog, comments * address comments * revert unnecessary extra failure check * fix changelog Co-authored-by: Gershom Bazerman <gershom@arista.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> (cherry picked from commit 338d060)
build pkgconfig db individually when bulk fails (backport #8496)
* build pkgconfig db individually when bulk fails * fix typo * changelog, comments * address comments * revert unnecessary extra failure check * fix changelog Co-authored-by: Gershom Bazerman <gershom@arista.com> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Resolves #8494
We need to check for versions of packages in the pkg-config db, since we have constraints on versions. We also want to be able to use the pkgdb purely, which means we can't push checking for versions to the call-site where we know which packages are required. Further we don't know which packages we need to query until midway in the solver (since that depends on which deps we pick), so we can't first winnow down the list.
So instead I just added a fallback that says if there's a failure to build the versions en masse they get queried one by one. Slower, but reliable.