Skip to content

Test failure on complex pkgdb setup #856

@hseg

Description

@hseg

It was my expectation that a bare cabal test would run the full testsuite, that at least on released versions, these would all pass, and that running them through cabal test would make them agnostic as to my particular configuration.

However, the following tests fail with on a clean build of v0.19.8:

EDIT: I was going to break these down by type, but the failures have been inconsistent through my investigations. I'm out of energy to try and figure out what's going on with them.

builtinOverride
config
digest
docs
files
forward
journal
ninja
rebuild
self
selfmake

One notable class of failures (deeply investigated re docs) are cases where shake seems to be manually calling ghc or running a Setup.hs, in which case it fails to find its dependencies on my system.

The test environment is an Arch Linux system with no system ghc, with all tools instead provisioned by ghcup:

✓  ghc   8.6.5       base-4.12.0.0
✔✔ ghc   9.8.4       base-4.19.2.0             2024-11-27
✓  ghc   9.10.2      base-4.20.1.0
✓  ghc   9.10.3      base-4.20.1.0
✓  ghc   9.12.2      latest,base-4.21.0.0      2025-03-12
✔✔ cabal 3.16.0.0    latest
✔✔ ghcup 0.1.50.2    latest,recommended

and using nonstandard cabal paths (following the XDG Base Directory spec):

repository hackage.haskell.org
  url: http://hackage.haskell.org/
remote-repo-cache: /home/gesh/.local/var/cache/cabal/packages
extra-prog-path: /home/gesh/.local/bin
build-summary: /home/gesh/.local/var/cache/cabal/logs/build.log
installdir: /home/gesh/.local/bin
remote-repo-cache: /home/gesh/.local/var/cache/cabal/packages
logs-dir: /home/gesh/.local/var/cache/cabal/logs
store-dir: /home/gesh/.local/var/state/cabal/store
installdir: /home/gesh/.local/bin

The only way I've found of getting somewhere near progress on this is to run the relevant tests using cabal exec path/to/shake-test to populate $GHC_ENVIRONMENT, then picking up the package-db values from that file. One needs to not clear the default package-db, as cabal does not seem to list the boot package db shipped with ghcup.

With that done, setup.exe configure does go through, but setup.exe haddock still exhibits many failures.

A patch adding `GHC_ENVIRONMENT` support
diff --git a/src/Test/Docs.hs b/src/Test/Docs.hs
index 61a6d7d4..83cd6dda 100644
--- a/src/Test/Docs.hs
+++ b/src/Test/Docs.hs
@@ -8,6 +8,8 @@ import qualified System.FilePattern.Directory as IO
 import System.Directory
 import Test.Type
 import Data.Char
+import Control.Monad
+import Control.Monad.Trans.Maybe
 import Data.List.Extra
 
 
@@ -40,14 +43,18 @@ main = testBuild (notCI . defaultTest) $ do
         cmd_ (Cwd shakeRoot) "ghc -package=Cabal Setup.hs -o" [setup] "-outputdir" [curdir]
 
     config %> \_ -> do
-        path <- getEnv "GHC_PACKAGE_PATH"
+        -- Emulate GHC's logic -- GHC_PACKAGE_PATH overrides GHC_ENVIRONMENT
+        pkgdb <- firstJustM (return []) [
+                     MaybeT (getEnv "GHC_PACKAGE_PATH")
+                        >>= return . pkgPathToPkgdb
+                    ,MaybeT (getEnv "GHC_ENVIRONMENT")
+                        >>= MaybeT . fmap Just . readFileLines
+                        >>= return . envToPkgdb
+                    ]
+
         dist <- liftIO $ canonicalizePath "dist" -- make sure it works even if we cwd
         need [shakeRoot </> "shake.cabal"]
-        runSetup $
-            ["configure","--builddir=" ++ dist,"--user"] ++
-            -- package-db is very sensitive, see #267
-            -- note that the reverse ensures the behaviour is consistent between the flags and the env variable
-            ["--package-db=" ++ x | x <- maybe [] (reverse . filter (`notElem` [".",""]) . splitSearchPath) path]
+        runSetup $ ["configure","--builddir=" ++ dist,"--user"] ++ pkgdb
 
         -- Paths_shake is only created by "Setup build" (which we want to skip), and required by "Setup haddock", so we fake it
         copyFile' (shakeRoot </> "src/Paths.hs") "dist/build/autogen/Paths_shake.hs"
@@ -180,6 +187,28 @@ main = testBuild (notCI . defaultTest) $ do
         cmd_ "ghc -fno-code -ignore-package=hashmap" ["-idist/build/autogen","-i" ++ shakeRoot </> "src","Main.hs"]
         writeFile' out ""
 
+firstJustM :: Monad m => a -> [MaybeT m a] -> m a
+firstJustM d xs = fmap (maybe d id) $ runMaybeT $ msum $ xs
+
+pkgPathToPkgdb path =
+    -- package-db is very sensitive, see #267
+    -- note that the reverse ensures the behaviour is consistent between the flags and the env variable
+    ["--package-db=" ++ x | x <- (reverse . filter (`notElem` [".",""]) . splitSearchPath) path]
+
+envToPkgdb :: [String] -> [String]
+envToPkgdb = filter (/="") . map transLine
+    where
+        transLine l = case words l of
+            ("--":_) -> ""
+            -- ["clear-package-db"] -> "--package-db=clear"
+            ["clear-package-db"] -> ""
+            ["global-package-db"] -> "--global"
+            ["package-db", db] -> "--package-db=" ++ db
+            -- ["package-id", ipid] -> "--dependency=" ++ ipid
+            ["package-id", _] -> ""
+            e -> fail $
+                   "envToPkgdb: Unexpected environment file line: " ++ unwords e
+
 checkBlacklist :: String -> String
 checkBlacklist xs = if null bad then xs else error $ show ("Blacklist", bad)
     where bad = [(w, x) | x <- map lower $ lines xs, w <- blacklist, w `isInfixOf` x]

Logfile makes this too long, attached to next post.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions