Skip to content

Commit

Permalink
Fix extra-prog-path propagation in the codebase.
Browse files Browse the repository at this point in the history
This allows finding system executables in:
- `cabal exec`
- `cabal build` (configure steps for example)
- `cabal get`

In particular this fixes PATH issues when running MinGW cabal in
PowerShell.
  • Loading branch information
jasagredo committed Dec 19, 2023
1 parent feaa338 commit cbcfb6b
Show file tree
Hide file tree
Showing 18 changed files with 132 additions and 71 deletions.
3 changes: 3 additions & 0 deletions Cabal/src/Distribution/Simple/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,9 @@ configure (pkg_descr0, pbi) cfg = do
mkPromisedDepsSet :: [GivenComponent] -> Map (PackageName, ComponentName) ComponentId
mkPromisedDepsSet comps = Map.fromList [((pn, CLibName ln), cid) | GivenComponent pn ln cid <- comps]

-- | Adds the extra program paths from the flags provided to @configure@ as
-- well as specified locations for certain known programs and their default
-- arguments.
mkProgramDb :: ConfigFlags -> ProgramDb -> ProgramDb
mkProgramDb cfg initialProgramDb = programDb
where
Expand Down
5 changes: 1 addition & 4 deletions Cabal/src/Distribution/Simple/ConfigureScript.hs
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,7 @@ runConfigureScript verbosity flags lbi = do
maybeHostFlag = if hp == buildPlatform then [] else ["--host=" ++ show (pretty hp)]
args' = configureFile' : args ++ ["CC=" ++ ccProgShort] ++ maybeHostFlag
shProg = simpleProgram "sh"
progDb =
modifyProgramSearchPath
(\p -> map ProgramSearchPathDir extraPath ++ p)
emptyProgramDb
progDb <- appendProgramSearchPath verbosity extraPath emptyProgramDb
shConfiguredProg <-
lookupProgram shProg
`fmap` configureProgram verbosity shProg progDb
Expand Down
15 changes: 15 additions & 0 deletions Cabal/src/Distribution/Simple/Program/Db.hs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module Distribution.Simple.Program.Db
-- ** Query and manipulate the program db
, addKnownProgram
, addKnownPrograms
, appendProgramSearchPath
, lookupKnownProgram
, knownPrograms
, getProgramSearchPath
Expand Down Expand Up @@ -221,6 +222,20 @@ modifyProgramSearchPath
modifyProgramSearchPath f db =
setProgramSearchPath (f $ getProgramSearchPath db) db

-- | Modify the current 'ProgramSearchPath' used by the 'ProgramDb'
-- by appending the provided extra paths. Also logs the added paths
-- in info verbosity.
appendProgramSearchPath
:: Verbosity
-> [FilePath]
-> ProgramDb
-> IO ProgramDb
appendProgramSearchPath verbosity extraPaths db = do
info verbosity . unlines $
"Including the following directories in PATH:"
: map ("- " ++) extraPaths
pure $ modifyProgramSearchPath (map ProgramSearchPathDir extraPaths ++) db

-- | User-specify this path. Basically override any path information
-- for this program in the configuration. If it's not a known
-- program ignore it.
Expand Down
2 changes: 0 additions & 2 deletions Cabal/src/Distribution/Simple/Program/GHC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -554,8 +554,6 @@ data GhcOptions = GhcOptions
, ghcOptExtraPath :: NubListR FilePath
-- ^ Put the extra folders in the PATH environment variable we invoke
-- GHC with
-- | Put the extra folders in the PATH environment variable we invoke
-- GHC with
, ghcOptCabal :: Flag Bool
-- ^ Let GHC know that it is Cabal that's calling it.
-- Modifies some of the GHC error messages.
Expand Down
9 changes: 7 additions & 2 deletions Cabal/src/Distribution/Simple/Program/Run.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ data ProgramInvocation = ProgramInvocation
{ progInvokePath :: FilePath
, progInvokeArgs :: [String]
, progInvokeEnv :: [(String, Maybe String)]
, -- Extra paths to add to PATH
progInvokePathEnv :: [FilePath]
, progInvokePathEnv :: [FilePath]
-- ^ Extra paths to add to PATH.
--
-- NOTE: The only program that sets paths here is GHC. See
-- 'componentGhcOptions' and the value of 'ghcOptExtraPath' there used then in
-- 'ghcInvocation'. Every other program we run doesn't set this but instead
-- provides a @"PATH"@ var in @progInvokeEnv@.
, progInvokeCwd :: Maybe FilePath
, progInvokeInput :: Maybe IOData
, progInvokeInputEncoding :: IOEncoding
Expand Down
35 changes: 20 additions & 15 deletions cabal-install/src/Distribution/Client/CmdExec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ import Distribution.Client.NixStyleOptions
, defaultNixStyleFlags
, nixStyleOptions
)
import Distribution.Client.ProjectConfig.Types
( ProjectConfig (projectConfigShared)
, ProjectConfigShared (projectConfigProgPathExtra)
)
import Distribution.Client.ProjectFlags
( removeIgnoreProjectOption
)
Expand Down Expand Up @@ -66,12 +70,9 @@ import Distribution.Simple.GHC
)
import Distribution.Simple.Program.Db
( configuredPrograms
, modifyProgramSearchPath
, appendProgramSearchPath
, requireProgram
)
import Distribution.Simple.Program.Find
( ProgramSearchPathEntry (..)
)
import Distribution.Simple.Program.Run
( programInvocation
, runProgramInvocation
Expand All @@ -86,11 +87,13 @@ import Distribution.Simple.Program.Types
import Distribution.Simple.Utils
( createDirectoryIfMissingVerbose
, dieWithException
, info
, notice
, withTempDirectory
, wrapText
)
import Distribution.Utils.NubList
( fromNubList
)
import Distribution.Verbosity
( normal
)
Expand Down Expand Up @@ -162,10 +165,11 @@ execAction flags@NixStyleFlags{..} extraArgs globalFlags = do
mempty

-- Some dependencies may have executables. Let's put those on the PATH.
extraPaths <- pathAdditions verbosity baseCtx buildCtx
let programDb =
modifyProgramSearchPath
(map ProgramSearchPathDir extraPaths ++)
let extraPaths = pathAdditions baseCtx buildCtx

programDb <-
appendProgramSearchPath verbosity
extraPaths
. pkgConfigCompilerProgs
. elaboratedShared
$ buildCtx
Expand Down Expand Up @@ -263,13 +267,14 @@ withTempEnvFile verbosity baseCtx buildCtx buildStatus action = do
action envOverrides
)

pathAdditions :: Verbosity -> ProjectBaseContext -> ProjectBuildContext -> IO [FilePath]
pathAdditions verbosity ProjectBaseContext{..} ProjectBuildContext{..} = do
info verbosity . unlines $
"Including the following directories in PATH:"
: paths
return paths
pathAdditions :: ProjectBaseContext -> ProjectBuildContext -> [FilePath]
pathAdditions ProjectBaseContext{..} ProjectBuildContext{..} =
paths ++ cabalConfigPaths
where
cabalConfigPaths = fromNubList
. projectConfigProgPathExtra
. projectConfigShared
$ projectConfig
paths =
S.toList $
binDirectories distDirLayout elaboratedShared elaboratedPlanToExecute
Expand Down
16 changes: 5 additions & 11 deletions cabal-install/src/Distribution/Client/CmdInstall.hs
Original file line number Diff line number Diff line change
Expand Up @@ -151,13 +151,10 @@ import qualified Distribution.Simple.InstallDirs as InstallDirs
import qualified Distribution.Simple.PackageIndex as PI
import Distribution.Simple.Program.Db
( defaultProgramDb
, modifyProgramSearchPath
, appendProgramSearchPath
, userSpecifyArgss
, userSpecifyPaths
)
import Distribution.Simple.Program.Find
( ProgramSearchPathEntry (..)
)
import Distribution.Simple.Setup
( Flag (..)
, installDirsOptions
Expand Down Expand Up @@ -496,6 +493,7 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt
, projectConfigHcPath
, projectConfigHcPkg
, projectConfigStoreDir
, projectConfigProgPathExtra
}
, projectConfigLocalPackages =
PackageConfig
Expand All @@ -509,17 +507,13 @@ installAction flags@NixStyleFlags{extraFlags = clientInstallFlags', ..} targetSt
hcPath = flagToMaybe projectConfigHcPath
hcPkg = flagToMaybe projectConfigHcPkg

configProgDb <- appendProgramSearchPath verbosity ((fromNubList packageConfigProgramPathExtra) ++ (fromNubList projectConfigProgPathExtra)) defaultProgramDb
let
-- ProgramDb with directly user specified paths
preProgDb =
userSpecifyPaths (Map.toList (getMapLast packageConfigProgramPaths))
. userSpecifyArgss (Map.toList (getMapMappend packageConfigProgramArgs))
. modifyProgramSearchPath
( ++
[ ProgramSearchPathDir dir
| dir <- fromNubList packageConfigProgramPathExtra
]
)
$ defaultProgramDb
$ configProgDb

-- progDb is a program database with compiler tools configured properly
( compiler@Compiler
Expand Down
15 changes: 15 additions & 0 deletions cabal-install/src/Distribution/Client/CmdRun.hs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ import Distribution.Client.NixStyleOptions
, defaultNixStyleFlags
, nixStyleOptions
)
import Distribution.Client.ProjectConfig.Types
( ProjectConfig (projectConfigShared)
, ProjectConfigShared (projectConfigProgPathExtra)
)
import Distribution.Client.ProjectOrchestration
import Distribution.Client.ProjectPlanning
( ElaboratedConfiguredPackage (..)
Expand Down Expand Up @@ -105,6 +109,9 @@ import Distribution.Types.UnqualComponentName
( UnqualComponentName
, unUnqualComponentName
)
import Distribution.Utils.NubList
( fromNubList
)
import Distribution.Verbosity
( normal
, silent
Expand Down Expand Up @@ -288,6 +295,13 @@ runAction flags@NixStyleFlags{..} targetAndArgs globalFlags =
buildSettingDryRun (buildSettings baseCtx)
|| buildSettingOnlyDownload (buildSettings baseCtx)

let extraPath =
fromNubList
. projectConfigProgPathExtra
. projectConfigShared
. projectConfig
$ baseCtx

if dryRun
then notice verbosity "Running of executable suppressed by flag(s)"
else
Expand All @@ -300,6 +314,7 @@ runAction flags@NixStyleFlags{..} targetAndArgs globalFlags =
dataDirsEnvironmentForPlan
(distDirLayout baseCtx)
elaboratedPlan
, progInvokePathEnv = extraPath
}
where
(targetStr, args) = splitAt 1 targetAndArgs
Expand Down
8 changes: 8 additions & 0 deletions cabal-install/src/Distribution/Client/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1540,6 +1540,14 @@ parseConfig src initial = \str -> do
splitMultiPath
(configConfigureArgs scf)
}
, savedGlobalFlags =
let sgf = savedGlobalFlags conf
in sgf
{ globalProgPathExtra =
toNubList $
splitMultiPath
(fromNubList $ globalProgPathExtra sgf)
}
}

parse =
Expand Down
12 changes: 9 additions & 3 deletions cabal-install/src/Distribution/Client/Get.hs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ import Distribution.Solver.Types.SourcePackage
import Control.Monad (mapM_)
import qualified Data.Map as Map
import Distribution.Client.Errors
import Distribution.Utils.NubList
( fromNubList
)
import System.Directory
( createDirectoryIfMissing
, doesDirectoryExist
Expand All @@ -99,7 +102,7 @@ get
-> IO ()
get verbosity _ _ _ [] =
notice verbosity "No packages requested. Nothing to do."
get verbosity repoCtxt _ getFlags userTargets = do
get verbosity repoCtxt globalFlags getFlags userTargets = do
let useSourceRepo = case getSourceRepository getFlags of
NoFlag -> False
_ -> True
Expand Down Expand Up @@ -154,7 +157,7 @@ get verbosity repoCtxt _ getFlags userTargets = do

clone :: [UnresolvedSourcePackage] -> IO ()
clone =
clonePackagesFromSourceRepo verbosity prefix kind
clonePackagesFromSourceRepo verbosity prefix kind (fromNubList $ globalProgPathExtra globalFlags)
. map (\pkg -> (packageId pkg, packageSourceRepos pkg))
where
kind :: Maybe RepoKind
Expand Down Expand Up @@ -337,6 +340,8 @@ clonePackagesFromSourceRepo
-- ^ destination dir prefix
-> Maybe RepoKind
-- ^ preferred 'RepoKind'
-> [FilePath]
-- ^ Extra prog paths
-> [(PackageId, [PD.SourceRepo])]
-- ^ the packages and their
-- available 'SourceRepo's
Expand All @@ -345,13 +350,14 @@ clonePackagesFromSourceRepo
verbosity
destDirPrefix
preferredRepoKind
progPaths
pkgrepos = do
-- Do a bunch of checks and collect the required info
pkgrepos' <- traverse preCloneChecks pkgrepos

-- Configure the VCS drivers for all the repository types we may need
vcss <-
configureVCSs verbosity $
configureVCSs verbosity progPaths $
Map.fromList
[ (vcsRepoType vcs, vcs)
| (_, _, vcs, _) <- pkgrepos'
Expand Down
7 changes: 3 additions & 4 deletions cabal-install/src/Distribution/Client/HttpUtils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ import Distribution.Simple.Program
( ConfiguredProgram
, Program
, ProgramInvocation (..)
, ProgramSearchPathEntry (..)
, getProgramInvocationOutput
, programInvocation
, programPath
Expand All @@ -50,7 +49,7 @@ import Distribution.Simple.Program.Db
, configureAllKnownPrograms
, emptyProgramDb
, lookupProgram
, modifyProgramSearchPath
, appendProgramSearchPath
, requireProgram
)
import Distribution.Simple.Program.Run
Expand Down Expand Up @@ -409,7 +408,7 @@ configureTransport verbosity extraPath (Just name) =

case find (\(name', _, _, _) -> name' == name) supportedTransports of
Just (_, mprog, _tls, mkTrans) -> do
let baseProgDb = modifyProgramSearchPath (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb
baseProgDb <- appendProgramSearchPath verbosity extraPath emptyProgramDb
progdb <- case mprog of
Nothing -> return emptyProgramDb
Just prog -> snd <$> requireProgram verbosity prog baseProgDb
Expand All @@ -425,7 +424,7 @@ configureTransport verbosity extraPath Nothing = do

-- for all the transports except plain-http we need to try and find
-- their external executable
let baseProgDb = modifyProgramSearchPath (\p -> map ProgramSearchPathDir extraPath ++ p) emptyProgramDb
baseProgDb <- appendProgramSearchPath verbosity extraPath emptyProgramDb
progdb <-
configureAllKnownPrograms verbosity $
addKnownPrograms
Expand Down
5 changes: 2 additions & 3 deletions cabal-install/src/Distribution/Client/ProjectConfig.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1351,11 +1351,10 @@ syncAndReadSourcePackagesRemoteRepos
| (repo, rloc, rtype, vcs) <- repos'
]

-- TODO: pass progPathExtra on to 'configureVCS'
let _progPathExtra = fromNubList projectConfigProgPathExtra
let progPathExtra = fromNubList projectConfigProgPathExtra
getConfiguredVCS <- delayInitSharedResources $ \repoType ->
let vcs = Map.findWithDefault (error $ "Unknown VCS: " ++ prettyShow repoType) repoType knownVCSs
in configureVCS verbosity {-progPathExtra-} vcs
in configureVCS verbosity progPathExtra vcs

concat
<$> sequenceA
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ data CurrentCommand = InstallCommand | HaddockCommand | BuildCommand | ReplComma
deriving (Show, Eq)

-- | This holds the context of a project prior to solving: the content of the
-- @cabal.project@ and all the local package @.cabal@ files.
-- @cabal.project@, @cabal/config@ and all the local package @.cabal@ files.
data ProjectBaseContext = ProjectBaseContext
{ distDirLayout :: DistDirLayout
, cabalDirLayout :: CabalDirLayout
Expand Down
Loading

0 comments on commit cbcfb6b

Please sign in to comment.