diff --git a/cabal-install/src/Distribution/Client/CmdInstall.hs b/cabal-install/src/Distribution/Client/CmdInstall.hs index 0adeca99446..bf51def80da 100644 --- a/cabal-install/src/Distribution/Client/CmdInstall.hs +++ b/cabal-install/src/Distribution/Client/CmdInstall.hs @@ -2,6 +2,7 @@ {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} -- | cabal-install CLI command: build module Distribution.Client.CmdInstall @@ -104,6 +105,7 @@ import Distribution.Client.Types , PackageSpecifier (..) , SourcePackageDb (..) , UnresolvedSourcePackage + , pkgSpecifierTarget ) import Distribution.Client.Types.OverwritePolicy ( OverwritePolicy (..) @@ -371,7 +373,7 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt -- First, we need to learn about what's available to be installed. localBaseCtx <- - establishProjectBaseContext reducedVerbosity cliConfig InstallCommand + establishProjectBaseContext reducedVerbosity baseCliConfig InstallCommand let localDistDirLayout = distDirLayout localBaseCtx pkgDb <- projectConfigWithBuilderRepoContext @@ -432,7 +434,7 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt withoutProject globalConfig = do tss <- traverse (parseWithoutProjectTargetSelector verbosity) targetStrings' let - projectConfig = globalConfig <> cliConfig + projectConfig = globalConfig <> baseCliConfig ProjectConfigBuildOnly { projectConfigLogsDir @@ -478,10 +480,17 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt return (packageSpecifiers, uris, packageTargets, projectConfig) - (specs, uris, targetSelectors, config) <- + (specs, uris, targetSelectors, baseConfig) <- withProjectOrGlobalConfig verbosity ignoreProject globalConfigFlag withProject withoutProject + -- We compute the base context again to determine packages available in the + -- project to be installed, so we can list the available package names when + -- the "all:..." variants of the target selectors are used. + localPkgs <- localPackages <$> establishProjectBaseContext verbosity baseConfig InstallCommand + let + config = addLocalConfigToPkgs baseConfig (map pkgSpecifierTarget specs ++ concatMap (targetPkgNames localPkgs) targetSelectors) + ProjectConfig { projectConfigBuildOnly = ProjectConfigBuildOnly @@ -631,8 +640,7 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt globalFlags flags{configFlags = configFlags'} clientInstallFlags' - cliConfig = addLocalConfigToTargets baseCliConfig targetStrings - globalConfigFlag = projectConfigConfigFile (projectConfigShared cliConfig) + globalConfigFlag = projectConfigConfigFile (projectConfigShared baseCliConfig) -- Do the install action for each executable in the install configuration. traverseInstall :: InstallAction -> InstallCfg -> IO () @@ -641,9 +649,9 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt actionOnExe <- action v overwritePolicy <$> prepareExeInstall cfg traverse_ actionOnExe . Map.toList $ targetsMap buildCtx --- | Treat all direct targets of install command as local packages: #8637 -addLocalConfigToTargets :: ProjectConfig -> [String] -> ProjectConfig -addLocalConfigToTargets config targetStrings = +-- | Treat all direct targets of install command as local packages: #8637 and later #7297, #8909, #7236. +addLocalConfigToPkgs :: ProjectConfig -> [PackageName] -> ProjectConfig +addLocalConfigToPkgs config pkgs = config { projectConfigSpecificPackage = projectConfigSpecificPackage config @@ -651,7 +659,25 @@ addLocalConfigToTargets config targetStrings = } where localConfig = projectConfigLocalPackages config - targetPackageConfigs = map (\x -> (mkPackageName x, localConfig)) targetStrings + targetPackageConfigs = map (,localConfig) pkgs + +targetPkgNames + :: [PackageSpecifier UnresolvedSourcePackage] + -- ^ The local packages, to resolve 'TargetAllPackages' selectors + -> TargetSelector + -> [PackageName] +targetPkgNames localPkgs = \case + TargetPackage _ pkgIds _ -> map pkgName pkgIds + TargetPackageNamed name _ -> [name] + TargetAllPackages _ -> map pkgSpecifierTarget localPkgs + -- Note how the target may select a component only, but we will always apply + -- the local flags to the whole package in which that component is contained. + -- The reason is that our finest level of configuration is per-package, so + -- there is no interface to configure options to a component only. It is not + -- trivial to say whether we could indeed support per-component configuration + -- because of legacy packages which we may always have to build whole. + TargetComponent pkgId _ -> [pkgName pkgId] + TargetComponentUnknown name _ -> [name] -- | Verify that invalid config options were not passed to the install command. -- diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/Main.hs b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/Main.hs new file mode 100644 index 00000000000..38bfcb0221f --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/Main.hs @@ -0,0 +1,25 @@ +{-# LANGUAGE CPP #-} + +#ifdef TEST1 +main = putStrLn "hi1" +#endif + +#ifdef TEST2 +main = putStrLn "hi2" +#endif + +#ifdef TEST3 +main = putStrLn "hi3" +#endif + +#ifdef TEST4 +main = putStrLn "hi4" +#endif + +#ifdef TEST5 +main = putStrLn "hi5" +#endif + +#ifdef TEST6 +main = putStrLn "hi6" +#endif diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.project b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.test.hs b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.test.hs new file mode 100644 index 00000000000..2583cdac2e3 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/cabal.test.hs @@ -0,0 +1,28 @@ +import Test.Cabal.Prelude + +main = cabalTest $ do + env <- getTestEnv + recordMode DoNotRecord $ do + let + installdir = testPrefixDir env "bin" + commonOpts v = ["--ghc-options=-DTEST" ++ show v, "--overwrite-policy=always", "--installdir=" ++ installdir] + installWithTgt tgt v = do + cabal "install" (tgt:commonOpts v) + runInstalledExe' "my-exe" [] + >>= assertOutputContains ("hi" ++ show v) + + installExternalWithTgt tgt v = withRepo "repo" (installWithTgt tgt v) + + + cabal "install" (commonOpts 1) -- no target + runInstalledExe' "my-exe" [] + >>= assertOutputContains "hi1" + + installWithTgt "t7297-89097236a" 2 + installWithTgt "exe:my-exe" 3 + installWithTgt "my-exe" 4 + installWithTgt "all" 5 + installWithTgt "all:exes" 6 + + -- And test it works when installing from an external repo (think Hackage) + installExternalWithTgt "external-lib" 2 diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/CHANGELOG.md b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/CHANGELOG.md new file mode 100644 index 00000000000..fbf078ff958 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/CHANGELOG.md @@ -0,0 +1,5 @@ +# Revision history for external-lib0100 + +## 0.1.0.0 -- YYYY-mm-dd + +* First version. Released on an unsuspecting world. diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/Main.hs b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/Main.hs new file mode 100644 index 00000000000..38bfcb0221f --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/Main.hs @@ -0,0 +1,25 @@ +{-# LANGUAGE CPP #-} + +#ifdef TEST1 +main = putStrLn "hi1" +#endif + +#ifdef TEST2 +main = putStrLn "hi2" +#endif + +#ifdef TEST3 +main = putStrLn "hi3" +#endif + +#ifdef TEST4 +main = putStrLn "hi4" +#endif + +#ifdef TEST5 +main = putStrLn "hi5" +#endif + +#ifdef TEST6 +main = putStrLn "hi6" +#endif diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/external-lib.cabal b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/external-lib.cabal new file mode 100644 index 00000000000..bc501812d3b --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/repo/external-lib-0.1.0.0/external-lib.cabal @@ -0,0 +1,18 @@ +cabal-version: 3.0 +name: external-lib +version: 0.1.0.0 +license: NONE +author: matthewtpickering@gmail.com +maintainer: Matthew Pickering +build-type: Simple +extra-doc-files: CHANGELOG.md + +common warnings + ghc-options: -Wall + +executable my-exe + import: warnings + main-is: Main.hs + build-depends: base + hs-source-dirs: . + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/Install/T7297-8909-7236/t7297-89097236a.cabal b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/t7297-89097236a.cabal new file mode 100644 index 00000000000..84ca78363c7 --- /dev/null +++ b/cabal-testsuite/PackageTests/Install/T7297-8909-7236/t7297-89097236a.cabal @@ -0,0 +1,8 @@ +name: t7297-89097236a +version: 1.0 +build-type: Simple +cabal-version: >= 1.2 + +executable my-exe + main-is: Main.hs + build-depends: base