From b41505aa0e003a1150b69587625d42b79e54174c Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 3 Feb 2017 11:21:19 -0800 Subject: [PATCH 01/34] enviroment -> environment --- .../Distribution/Client/ProjectPlanOutput.hs | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index b5c1e39d6a1..c37563e6f13 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -678,21 +678,21 @@ writePlanGhcEnvironment projectRootDir = writeGhcEnvironmentFile projectRootDir platform (compilerVersion compiler) - (renderGhcEnviromentFile projectRootDir - elaboratedInstallPlan - postBuildStatus) + (renderGhcEnvironmentFile projectRootDir + elaboratedInstallPlan + postBuildStatus) --TODO: [required eventually] support for writing user-wide package -- environments, e.g. like a global project, but we would not put the -- env file in the home dir, rather it lives under ~/.ghc/ writePlanGhcEnvironment _ _ _ _ = return () -renderGhcEnviromentFile :: FilePath - -> ElaboratedInstallPlan - -> PostBuildProjectStatus - -> [GhcEnvironmentFileEntry] -renderGhcEnviromentFile projectRootDir elaboratedInstallPlan - postBuildStatus = +renderGhcEnvironmentFile :: FilePath + -> ElaboratedInstallPlan + -> PostBuildProjectStatus + -> [GhcEnvironmentFileEntry] +renderGhcEnvironmentFile projectRootDir elaboratedInstallPlan + postBuildStatus = headerComment : simpleGhcEnvironmentFile packageDBs unitIds where @@ -703,9 +703,9 @@ renderGhcEnviromentFile projectRootDir elaboratedInstallPlan ++ "But you still need to use cabal repl $target to get the environment\n" ++ "of specific components (libs, exes, tests etc) because each one can\n" ++ "have its own source dirs, cpp flags etc.\n\n" - unitIds = selectGhcEnviromentFileLibraries postBuildStatus + unitIds = selectGhcEnvironmentFileLibraries postBuildStatus packageDBs = relativePackageDBPaths projectRootDir $ - selectGhcEnviromentFilePackageDbs elaboratedInstallPlan + selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan -- We're producing an environment for users to use in ghci, so of course @@ -740,10 +740,10 @@ renderGhcEnviromentFile projectRootDir elaboratedInstallPlan -- to find the libs) then those exes still end up in our list so we have -- to filter them out at the end. -- -selectGhcEnviromentFileLibraries :: PostBuildProjectStatus -> [UnitId] -selectGhcEnviromentFileLibraries PostBuildProjectStatus{..} = +selectGhcEnvironmentFileLibraries :: PostBuildProjectStatus -> [UnitId] +selectGhcEnvironmentFileLibraries PostBuildProjectStatus{..} = case Graph.closure packagesLibDepGraph (Set.toList packagesBuildLocal) of - Nothing -> error "renderGhcEnviromentFile: broken dep closure" + Nothing -> error "renderGhcEnvironmentFile: broken dep closure" Just nodes -> [ pkgid | Graph.N pkg pkgid _ <- nodes , hasUpToDateLib pkg ] where @@ -761,8 +761,8 @@ selectGhcEnviromentFileLibraries PostBuildProjectStatus{..} = && installedUnitId pkg `Set.member` packagesProbablyUpToDate -selectGhcEnviromentFilePackageDbs :: ElaboratedInstallPlan -> PackageDBStack -selectGhcEnviromentFilePackageDbs elaboratedInstallPlan = +selectGhcEnvironmentFilePackageDbs :: ElaboratedInstallPlan -> PackageDBStack +selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan = -- If we have any inplace packages then their package db stack is the -- one we should use since it'll include the store + the local db but -- it's certainly possible to have no local inplace packages @@ -775,7 +775,7 @@ selectGhcEnviromentFilePackageDbs elaboratedInstallPlan = case ordNub (map elabBuildPackageDBStack pkgs) of [packageDbs] -> packageDbs [] -> [] - _ -> error $ "renderGhcEnviromentFile: packages with " + _ -> error $ "renderGhcEnvironmentFile: packages with " ++ "different package db stacks" -- This should not happen at the moment but will happen as soon -- as we support projects where we build packages with different From 599120e38e6bae5619264624cf270a2e056636b8 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 3 Feb 2017 11:52:18 -0800 Subject: [PATCH 02/34] disable GHC environment files in another way Although we may not want to create GHC environment files in a standard location after every build, it is still useful to be able to build them in a custom place in special circumstances. So let's disable this feature at the call-sites where it doesn't work properly rather than inside the implementation of the feature. --- cabal-install/Distribution/Client/ProjectOrchestration.hs | 4 +++- cabal-install/Distribution/Client/ProjectPlanOutput.hs | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index 8847fc987e3..6180dd9b0bb 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -277,17 +277,19 @@ runProjectPostBuildPhase verbosity ProjectBuildContext {..} buildOutcomes = do -- - delete stale lib registrations -- - delete stale package dirs - postBuildStatus <- updatePostBuildProjectStatus + _postBuildStatus <- updatePostBuildProjectStatus verbosity distDirLayout elaboratedPlanOriginal pkgsBuildStatus buildOutcomes + {-TODO: This feature is temporarily disabled due to #4010 writePlanGhcEnvironment projectRootDir elaboratedPlanOriginal elaboratedShared postBuildStatus + -} -- Finally if there were any build failures then report them and throw -- an exception to terminate the program diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index c37563e6f13..03d715599dc 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -673,8 +673,6 @@ writePlanGhcEnvironment projectRootDir | compilerFlavor compiler == GHC , supportsPkgEnvFiles (getImplInfo compiler) --TODO: check ghcjs compat - --TODO: This feature is temporarily disabled due to #4010 - , False = writeGhcEnvironmentFile projectRootDir platform (compilerVersion compiler) From 585fe3a43181c955e00840775ba0144590d7c03a Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Fri, 3 Feb 2017 20:31:06 -0800 Subject: [PATCH 03/34] bare-bones new-exec support This implements a bare-bones skeleton for cabal new-exec. The old cabal exec gave programs access to a sandbox's package database. By analogy, cabal new-exec should give programs access to the store's package database; however, this database will be cluttered with many non-project-related packages that may confuse issues. Therefore new-exec selects just the packages that are in the current project's dependency tree and makes them available to compiler tools. Currently only very new GHCs are supported, via the GHC_ENVIRONMENT mechanism for selecting a subset of some package databases. Eventually we should probably also modify the PATH so that dependencies' executables are available. --- Cabal/Distribution/Simple/GHC/Internal.hs | 8 +- cabal-install/Distribution/Client/CmdExec.hs | 132 ++++++++++++++++++ .../Distribution/Client/ProjectPlanOutput.hs | 44 +++++- cabal-install/Distribution/Client/Setup.hs | 2 +- cabal-install/cabal-install.cabal | 1 + cabal-install/main/Main.hs | 2 + 6 files changed, 182 insertions(+), 7 deletions(-) create mode 100644 cabal-install/Distribution/Client/CmdExec.hs diff --git a/Cabal/Distribution/Simple/GHC/Internal.hs b/Cabal/Distribution/Simple/GHC/Internal.hs index ea3c2bd2bc5..99ab12b96dc 100644 --- a/Cabal/Distribution/Simple/GHC/Internal.hs +++ b/Cabal/Distribution/Simple/GHC/Internal.hs @@ -531,13 +531,15 @@ simpleGhcEnvironmentFile packageDBs pkgids = -- -- The 'Platform' and GHC 'Version' are needed as part of the file name. -- +-- Returns the name of the file written. writeGhcEnvironmentFile :: FilePath -- ^ directory in which to put it -> Platform -- ^ the GHC target platform -> Version -- ^ the GHC version -> [GhcEnvironmentFileEntry] -- ^ the content - -> NoCallStackIO () -writeGhcEnvironmentFile directory platform ghcversion = - writeFileAtomic envfile . BS.pack . renderGhcEnvironmentFile + -> NoCallStackIO FilePath +writeGhcEnvironmentFile directory platform ghcversion entries = do + writeFileAtomic envfile . BS.pack . renderGhcEnvironmentFile $ entries + return envfile where envfile = directory ghcEnvironmentFileName platform ghcversion diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs new file mode 100644 index 00000000000..c361b7bff70 --- /dev/null +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -0,0 +1,132 @@ +------------------------------------------------------------------------------- +-- | +-- Module : Distribution.Client.Exec +-- Maintainer : cabal-devel@haskell.org +-- Portability : portable +-- +-- Implementation of the 'new-exec' command for running an arbitrary executable +-- in an environment suited to the part of the store built for a project. +------------------------------------------------------------------------------- + +{-# LANGUAGE StandaloneDeriving #-} +module Distribution.Client.CmdExec + ( execAction + , execCommand + ) where + +import Distribution.Client.DistDirLayout + ( distTempDirectory + ) +import Distribution.Client.Setup + ( GlobalFlags(..) + , ExecFlags(..) + , defaultExecFlags + ) +import Distribution.Client.ProjectOrchestration + ( ProjectBuildContext(..) + , PreBuildHooks(..) + , runProjectPreBuildPhase + ) +import Distribution.Client.ProjectPlanOutput + ( updatePostBuildProjectStatus + , createPackageEnvironment + ) +import Distribution.Simple.Command + ( CommandUI(..) + ) +import Distribution.Simple.Program.Run + ( ProgramInvocation(..) + , runProgramInvocation + , simpleProgramInvocation + ) +import Distribution.Simple.Setup + ( fromFlag + , optionDistPref, optionVerbosity + , configDistPref, configVerbosity + , haddockDistPref, haddockVerbosity + ) +import Distribution.Simple.Utils + ( die + , withTempDirectory + , wrapText + ) + +execCommand :: CommandUI ExecFlags +execCommand = CommandUI + { commandName = "new-exec" + , commandSynopsis = "Give a command access to the store." + , commandUsage = \pname -> + "Usage: " ++ pname ++ " new-exec [FLAGS] [--] COMMAND [--] [ARGS]\n" + , commandDescription = Just $ \_pname -> wrapText $ + "TODO" + , commandNotes = Nothing + , commandDefaultFlags = defaultExecFlags + , commandOptions = \showOrParseArgs -> + [ optionVerbosity execVerbosity (\v flags -> flags { execVerbosity = v }) + , optionDistPref + execDistPref (\v flags -> flags { execDistPref = v }) + showOrParseArgs + ] + } + +execAction :: ExecFlags -> [String] -> GlobalFlags -> IO () +execAction execFlags extraArgs globalFlags = do + let verbosity = fromFlag (execVerbosity execFlags) + + -- To set up the environment, we'd like to select the libraries in our + -- dependency tree that we've already built. So first we set up an install + -- plan, but we walk the dependency tree without first executing the plan. + -- + -- TODO: We set a lot of default settings here (with mempty). It might be + -- worth walking through each of the settings we default and making sure they + -- shouldn't become ExecFlags. + buildCtx <- runProjectPreBuildPhase + verbosity + ( globalFlags + , mempty + { configDistPref = execDistPref execFlags + , configVerbosity = execVerbosity execFlags + } + , mempty + , mempty + , mempty + { haddockDistPref = execDistPref execFlags + , haddockVerbosity = execVerbosity execFlags + } + ) + PreBuildHooks + { hookPrePlanning = \_ _ _ -> return () + , hookSelectPlanSubset = \_ -> return + } + buildStatus <- updatePostBuildProjectStatus + verbosity + (distDirLayout buildCtx) + (elaboratedPlanToExecute buildCtx) + (pkgsBuildStatus buildCtx) + mempty + + -- Now that we have the packages, set up the environment. We accomplish this + -- by creating an environment file that selects the databases and packages we + -- computed in the previous step, and setting an environment variable to + -- point at the file. + withTempDirectory + verbosity + (distTempDirectory (distDirLayout buildCtx)) + "environment." + $ \tmpDir -> do + envOverrides <- createPackageEnvironment + verbosity + tmpDir + (elaboratedPlanToExecute buildCtx) + (elaboratedShared buildCtx) + buildStatus + + -- TODO: discuss PATH munging with #hackage + + case extraArgs of + exe:args -> runProgramInvocation + verbosity + (simpleProgramInvocation exe args) + { progInvokeEnv = envOverrides + } + [] -> die "Please specify an executable to run" diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 03d715599dc..fc164b5fb8c 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -10,6 +10,7 @@ module Distribution.Client.ProjectPlanOutput ( -- | Several outputs rely on having a general overview of PostBuildProjectStatus(..), updatePostBuildProjectStatus, + createPackageEnvironment, writePlanGhcEnvironment, ) where @@ -655,6 +656,43 @@ writePackagesUpToDateCacheFile DistDirLayout{distProjectCacheFile} upToDate = writeFileAtomic (distProjectCacheFile "up-to-date") $ Binary.encode upToDate +-- | Prepare a package environment that includes all the library dependencies +-- for a plan. +-- +-- When running cabal new-exec, we want to set things up so that the compiler +-- can find all the right packages (and nothing else). This function is +-- intended to do that work. It takes a location where it can write files +-- temporarily, in case the compiler wants to learn this information via the +-- filesystem, and returns any environment variable overrides the compiler +-- needs. +createPackageEnvironment :: Verbosity + -> FilePath + -> ElaboratedInstallPlan + -> ElaboratedSharedConfig + -> PostBuildProjectStatus + -> IO [(String, Maybe String)] +createPackageEnvironment verbosity + tmpDir + elaboratedPlan + elaboratedShared + buildStatus + | compilerFlavor (pkgConfigCompiler elaboratedShared) == GHC + = do + envFileM <- writePlanGhcEnvironment + tmpDir + elaboratedPlan + elaboratedShared + buildStatus + case envFileM of + Just envFile -> return [("GHC_ENVIRONMENT", Just envFile)] + Nothing -> do + warn verbosity "the configured version of GHC does not support reading package lists from the environment; commands that need the current project's package database are likely to fail" + return [] + | otherwise + = do + warn verbosity "package environment configuration is not supported for the currently configured compiler; commands that need the current project's package database are likely to fail" + return [] + -- Writing .ghc.environment files -- @@ -662,7 +700,7 @@ writePlanGhcEnvironment :: FilePath -> ElaboratedInstallPlan -> ElaboratedSharedConfig -> PostBuildProjectStatus - -> IO () + -> IO (Maybe FilePath) writePlanGhcEnvironment projectRootDir elaboratedInstallPlan ElaboratedSharedConfig { @@ -673,7 +711,7 @@ writePlanGhcEnvironment projectRootDir | compilerFlavor compiler == GHC , supportsPkgEnvFiles (getImplInfo compiler) --TODO: check ghcjs compat - = writeGhcEnvironmentFile + = fmap Just $ writeGhcEnvironmentFile projectRootDir platform (compilerVersion compiler) (renderGhcEnvironmentFile projectRootDir @@ -683,7 +721,7 @@ writePlanGhcEnvironment projectRootDir -- environments, e.g. like a global project, but we would not put the -- env file in the home dir, rather it lives under ~/.ghc/ -writePlanGhcEnvironment _ _ _ _ = return () +writePlanGhcEnvironment _ _ _ _ = return Nothing renderGhcEnvironmentFile :: FilePath -> ElaboratedInstallPlan diff --git a/cabal-install/Distribution/Client/Setup.hs b/cabal-install/Distribution/Client/Setup.hs index 6c5df68527c..7c9022a6b4c 100644 --- a/cabal-install/Distribution/Client/Setup.hs +++ b/cabal-install/Distribution/Client/Setup.hs @@ -45,7 +45,7 @@ module Distribution.Client.Setup , win32SelfUpgradeCommand, Win32SelfUpgradeFlags(..) , actAsSetupCommand, ActAsSetupFlags(..) , sandboxCommand, defaultSandboxLocation, SandboxFlags(..) - , execCommand, ExecFlags(..) + , execCommand, ExecFlags(..), defaultExecFlags , userConfigCommand, UserConfigFlags(..) , manpageCommand diff --git a/cabal-install/cabal-install.cabal b/cabal-install/cabal-install.cabal index fcd48f0e1f6..30fe32e688d 100644 --- a/cabal-install/cabal-install.cabal +++ b/cabal-install/cabal-install.cabal @@ -234,6 +234,7 @@ library Distribution.Client.CmdHaddock Distribution.Client.CmdTest Distribution.Client.CmdRepl + Distribution.Client.CmdExec Distribution.Client.Config Distribution.Client.Configure Distribution.Client.Dependency diff --git a/cabal-install/main/Main.hs b/cabal-install/main/Main.hs index 34c4653b692..cd756deab52 100644 --- a/cabal-install/main/Main.hs +++ b/cabal-install/main/Main.hs @@ -80,6 +80,7 @@ import qualified Distribution.Client.CmdFreeze as CmdFreeze import qualified Distribution.Client.CmdHaddock as CmdHaddock import qualified Distribution.Client.CmdRepl as CmdRepl import qualified Distribution.Client.CmdTest as CmdTest +import qualified Distribution.Client.CmdExec as CmdExec import Distribution.Client.Install (install) import Distribution.Client.Configure (configure, writeConfigFlags) @@ -292,6 +293,7 @@ mainWorker args = topHandler $ , hiddenCmd CmdTest.testCommand CmdTest.testAction , regularCmd CmdFreeze.freezeCommand CmdFreeze.freezeAction , regularCmd CmdHaddock.haddockCommand CmdHaddock.haddockAction + , regularCmd CmdExec.execCommand CmdExec.execAction ] type Action = GlobalFlags -> IO () From c5f00526e63a75e5cc93721523e38793b46a8ae5 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 6 Feb 2017 16:26:08 -0800 Subject: [PATCH 04/34] factor out the logic for choosing a directory for binaries --- .../Distribution/Client/ProjectPlanning.hs | 68 ++++++++++++------- 1 file changed, 45 insertions(+), 23 deletions(-) diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index e1c6996dd46..3649d023686 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -50,7 +50,10 @@ module Distribution.Client.ProjectPlanning ( packageHashInputs, -- TODO: [code cleanup] utils that should live in some shared place? - createPackageDBIfMissing + createPackageDBIfMissing, + inplaceBinDirectory, + installedBinDirectory, + binDirectory ) where import Prelude () @@ -1234,15 +1237,10 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB ordNub (map (abstractUnitId . ci_id) (lc_includes lc ++ lc_sig_includes lc)) } } - inplace_bin_dir - | shouldBuildInplaceOnly spkg - = distBuildDirectory - (elabDistDirParams elaboratedSharedConfig elab) - "build" case Cabal.componentNameString cname of - Just n -> display n - Nothing -> "" - | otherwise - = InstallDirs.bindir install_dirs + inplace_bin_dir = binDirectory + DistDirLayout{..} + elaboratedSharedConfig + elab exe_map' = Map.insert cid inplace_bin_dir exe_map return ((cc_map', lc_map', exe_map'), elab) where @@ -1452,21 +1450,12 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB where -- Pre-existing executables are assumed to be in PATH -- already. In fact, this should be impossible. - -- Modest duplication with 'inplace_bin_dir' get_exe_path (InstallPlan.PreExisting _) = [] get_exe_path (InstallPlan.Configured elab) = - [if elabBuildStyle elab == BuildInplaceOnly - then distBuildDirectory - (elabDistDirParams elaboratedSharedConfig elab) - "build" - case elabPkgOrComp elab of - ElabPackage _ -> "" - ElabComponent comp -> - case fmap Cabal.componentNameString - (compComponentName comp) of - Just (Just n) -> display n - _ -> "" - else InstallDirs.bindir (elabInstallDirs elab)] + [binDirectory DistDirLayout{..} + elaboratedSharedConfig + elab + ] get_exe_path (InstallPlan.Installed _) = unexpectedState unexpectedState = error "elaborateInstallPlan: unexpected Installed state" @@ -1811,6 +1800,39 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB -- + vanilla libs & exes, exe needs lib, recursive -- + ghci or shared lib needed by TH, recursive, ghc version dependent +-- | Get the bin\/ directory that executables should reside in, assuming that +-- they are the result of an in-place build. +inplaceBinDirectory + :: DistDirLayout + -> ElaboratedSharedConfig + -> ElaboratedConfiguredPackage + -> FilePath +inplaceBinDirectory layout config package + = distBuildDirectory layout (elabDistDirParams config package) + "build" + case elabPkgOrComp package of + ElabPackage _ -> "" + ElabComponent comp -> case compComponentName comp >>= + Cabal.componentNameString of + Just n -> display n + _ -> "" + +-- | Get the bin\/ directory that executables should reside in after the +-- package has been built and installed. +installedBinDirectory :: ElaboratedConfiguredPackage -> FilePath +installedBinDirectory = InstallDirs.bindir . elabInstallDirs + +-- | Get the bin\/ directory that a package's executables should reside in. +binDirectory + :: DistDirLayout + -> ElaboratedSharedConfig + -> ElaboratedConfiguredPackage + -> FilePath +binDirectory layout config package = + if elabBuildStyle package == BuildInplaceOnly + then inplaceBinDirectory layout config package + else installedBinDirectory package + -- | A newtype for 'SolverInstallPlan.SolverPlanPackage' for which the -- dependency graph considers only dependencies on libraries which are -- NOT from setup dependencies. Used to compute the set From effe36ba61d2b8f15ae6899a268e455a843cd47e Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 6 Feb 2017 17:39:42 -0800 Subject: [PATCH 05/34] PATH modifications for new-exec cabal new-exec should be allowed to run any executables available in the dependencies for the current project. This patch introduces that ability: we walk the installation plan, picking out a bin/ directory for each package, then including it in the PATH if there are any executables in that directory. --- cabal-install/Distribution/Client/CmdExec.hs | 78 +++++++++++++++++++- 1 file changed, 74 insertions(+), 4 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index c361b7bff70..520e8dd820c 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -8,14 +8,18 @@ -- in an environment suited to the part of the store built for a project. ------------------------------------------------------------------------------- -{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE RecordWildCards #-} module Distribution.Client.CmdExec ( execAction , execCommand ) where import Distribution.Client.DistDirLayout - ( distTempDirectory + ( DistDirLayout(..) + ) +import Distribution.Client.InstallPlan + ( GenericPlanPackage(..) + , toGraph ) import Distribution.Client.Setup ( GlobalFlags(..) @@ -31,6 +35,11 @@ import Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus , createPackageEnvironment ) +import Distribution.Client.ProjectPlanning + ( ElaboratedInstallPlan + , ElaboratedSharedConfig(..) + , binDirectory + ) import Distribution.Simple.Command ( CommandUI(..) ) @@ -46,10 +55,22 @@ import Distribution.Simple.Setup , haddockDistPref, haddockVerbosity ) import Distribution.Simple.Utils - ( die + ( debug + , die + , info , withTempDirectory , wrapText ) +import Distribution.Verbosity + ( Verbosity + ) + +import Control.Monad (filterM) +import Data.Set (Set) +import qualified Data.Set as S +import System.Directory (executable, getPermissions, listDirectory) +import System.FilePath (()) +import System.IO.Error (catchIOError) execCommand :: CommandUI ExecFlags execCommand = CommandUI @@ -105,6 +126,9 @@ execAction execFlags extraArgs globalFlags = do (pkgsBuildStatus buildCtx) mempty + -- TODO: use the ProgramDb hidden in the buildCtx to invoke the right + -- compiler tools (e.g. ghc, ghc-pkg, etc.) with the right arguments + -- Now that we have the packages, set up the environment. We accomplish this -- by creating an environment file that selects the databases and packages we -- computed in the previous step, and setting an environment variable to @@ -121,12 +145,58 @@ execAction execFlags extraArgs globalFlags = do (elaboratedShared buildCtx) buildStatus - -- TODO: discuss PATH munging with #hackage + -- Some dependencies may have executables. Let's put those on the PATH. + extraPaths <- pathAdditions verbosity buildCtx case extraArgs of exe:args -> runProgramInvocation verbosity (simpleProgramInvocation exe args) { progInvokeEnv = envOverrides + , progInvokePathEnv = extraPaths } [] -> die "Please specify an executable to run" + +pathAdditions :: Verbosity -> ProjectBuildContext -> IO [FilePath] +pathAdditions verbosity ProjectBuildContext{..} = do + debug verbosity $ "Considering the following directories for inclusion in PATH:" + mapM_ (debug verbosity) paths + occupiedPaths <- filterM hasExecutable (S.toAscList paths) + info verbosity $ "Including the following directories in PATH:" + mapM_ (info verbosity) occupiedPaths + return occupiedPaths + where + paths = binDirectories distDirLayout elaboratedShared elaboratedPlanToExecute + +binDirectories + :: DistDirLayout + -> ElaboratedSharedConfig + -> ElaboratedInstallPlan + -> Set FilePath +binDirectories layout config = fromElaboratedInstallPlan where + fromElaboratedInstallPlan = fromGraph . toGraph + fromGraph = foldMap fromPlan + fromSrcPkg pkg = S.singleton (binDirectory layout config pkg) + + fromPlan (PreExisting _) = mempty + fromPlan (Configured pkg) = fromSrcPkg pkg + fromPlan (Installed pkg) = fromSrcPkg pkg + +-- | Check whether a directory contains an executable. +hasExecutable :: FilePath -> IO Bool +hasExecutable dir = catchIOError + (listDirectory dir >>= anyM (isExecutable . (dir))) + (\_ -> return False) + +-- | Check whether a file is an executable. +isExecutable :: FilePath -> IO Bool +isExecutable file = catchIOError + (executable <$> getPermissions file) + (\_ -> return False) + +-- | Like 'any', but short-circuits side-effects, too. +anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool +anyM _ [] = return False +anyM f (x:xs) = do + fx <- f x + if fx then return True else anyM f xs From 43893e40f8e53ab1c6b6a848c5429d9326980c94 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 7 Feb 2017 17:26:30 -0800 Subject: [PATCH 06/34] use the ProgramDb in new-exec Previously, whichever version of compiler tools that were on the PATH would be used. Going through the ProgramDb should let us use the appropriate versions of these tools, instead. --- cabal-install/Distribution/Client/CmdExec.hs | 36 ++++++++++++++------ 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 520e8dd820c..eb1a5acc6e7 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -43,10 +43,20 @@ import Distribution.Client.ProjectPlanning import Distribution.Simple.Command ( CommandUI(..) ) +import Distribution.Simple.Program.Db + ( modifyProgramSearchPath + , requireProgram + ) +import Distribution.Simple.Program.Find + ( ProgramSearchPathEntry(..) + ) import Distribution.Simple.Program.Run - ( ProgramInvocation(..) + ( programInvocation , runProgramInvocation - , simpleProgramInvocation + ) +import Distribution.Simple.Program.Types + ( programOverrideEnv + , simpleProgram ) import Distribution.Simple.Setup ( fromFlag @@ -126,9 +136,6 @@ execAction execFlags extraArgs globalFlags = do (pkgsBuildStatus buildCtx) mempty - -- TODO: use the ProgramDb hidden in the buildCtx to invoke the right - -- compiler tools (e.g. ghc, ghc-pkg, etc.) with the right arguments - -- Now that we have the packages, set up the environment. We accomplish this -- by creating an environment file that selects the databases and packages we -- computed in the previous step, and setting an environment variable to @@ -147,15 +154,22 @@ execAction execFlags extraArgs globalFlags = do -- Some dependencies may have executables. Let's put those on the PATH. extraPaths <- pathAdditions verbosity buildCtx + let programDb = modifyProgramSearchPath + (map ProgramSearchPathDir extraPaths ++) + . pkgConfigCompilerProgs + . elaboratedShared + $ buildCtx case extraArgs of - exe:args -> runProgramInvocation - verbosity - (simpleProgramInvocation exe args) - { progInvokeEnv = envOverrides - , progInvokePathEnv = extraPaths - } + exe:args -> do + (program, _) <- requireProgram verbosity (simpleProgram exe) programDb + let program' = withOverrides envOverrides program + invocation = programInvocation program' args + runProgramInvocation verbosity invocation [] -> die "Please specify an executable to run" + where + withOverrides env program = program + { programOverrideEnv = programOverrideEnv program ++ env } pathAdditions :: Verbosity -> ProjectBuildContext -> IO [FilePath] pathAdditions verbosity ProjectBuildContext{..} = do From 1d4533e508e2d0bf7f03eddb46fe84faf1af03af Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Wed, 8 Feb 2017 16:00:47 -0800 Subject: [PATCH 07/34] write help text for new-exec --- cabal-install/Distribution/Client/CmdExec.hs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index eb1a5acc6e7..9a4af09507a 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -88,8 +88,20 @@ execCommand = CommandUI , commandSynopsis = "Give a command access to the store." , commandUsage = \pname -> "Usage: " ++ pname ++ " new-exec [FLAGS] [--] COMMAND [--] [ARGS]\n" - , commandDescription = Just $ \_pname -> wrapText $ - "TODO" + , commandDescription = Just $ \pname -> wrapText $ + "During development it is often useful to run build tasks and perform" + ++ " one-off program executions to experiment with the behavior of build" + ++ " tools. It is convenient to run these tools in the same way " ++ pname + ++ " itself would. The `" ++ pname ++ " new-exec` command provides a way to" + ++ " do so.\n" + ++ "\n" + ++ "Compiler tools will be configured to see the same subset of the store" + ++ " that builds would see. The PATH is modified to make all executables in" + ++ " the dependency tree available (provided they have been built already)." + ++ " Commands are also rewritten in the way cabal itself would. For" + ++ " example, `" ++ pname ++ " new-exec ghc` will consult the configuration" + ++ " to choose an appropriate version of ghc and to include any" + ++ " ghc-specific flags requested." , commandNotes = Nothing , commandDefaultFlags = defaultExecFlags , commandOptions = \showOrParseArgs -> From 603897f90f8aa039e6d69aa3511ea82a0ba9dda9 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Thu, 9 Feb 2017 14:07:19 -0800 Subject: [PATCH 08/34] backwards compatibility --- cabal-install/Distribution/Client/CmdExec.hs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 9a4af09507a..8ab8bb34258 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -75,10 +75,12 @@ import Distribution.Verbosity ( Verbosity ) -import Control.Monad (filterM) +import Prelude () +import Distribution.Client.Compat.Prelude + import Data.Set (Set) import qualified Data.Set as S -import System.Directory (executable, getPermissions, listDirectory) +import System.Directory (executable, getDirectoryContents, getPermissions) import System.FilePath (()) import System.IO.Error (catchIOError) @@ -186,10 +188,10 @@ execAction execFlags extraArgs globalFlags = do pathAdditions :: Verbosity -> ProjectBuildContext -> IO [FilePath] pathAdditions verbosity ProjectBuildContext{..} = do debug verbosity $ "Considering the following directories for inclusion in PATH:" - mapM_ (debug verbosity) paths + traverse_ (debug verbosity) paths occupiedPaths <- filterM hasExecutable (S.toAscList paths) info verbosity $ "Including the following directories in PATH:" - mapM_ (info verbosity) occupiedPaths + traverse_ (info verbosity) occupiedPaths return occupiedPaths where paths = binDirectories distDirLayout elaboratedShared elaboratedPlanToExecute @@ -208,6 +210,14 @@ binDirectories layout config = fromElaboratedInstallPlan where fromPlan (Configured pkg) = fromSrcPkg pkg fromPlan (Installed pkg) = fromSrcPkg pkg +-- This exists because old versions of the directory package don't supply it. +-- If our dependency on directory ever bumps up to above 1.2.5 this should be +-- deleted. +-- | Returns a list of all entries in the directory except the special entries +-- @.@ and @..@. +listDirectory :: FilePath -> IO [FilePath] +listDirectory d = filter (`notElem` [".", ".."]) <$> getDirectoryContents d + -- | Check whether a directory contains an executable. hasExecutable :: FilePath -> IO Bool hasExecutable dir = catchIOError From 44af73e05f6c9dcac1bec3910407f26255a5c572 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Feb 2017 12:48:53 -0800 Subject: [PATCH 09/34] use the install plan to modify PATH in new-exec Previously, cabal new-exec would modify the PATH by including each package's bin directory if it contained executables. This has some drawbacks: * Lots of filesystem probing * Can have false positives due to dynamic libraries * Mildly unpredictable The new plan is to add each package's bin directory if the package includes an executable stanza. This may include some directories that have no executables in them (e.g. if the executable is not yet built or is not in the install plan), but is more reproducible and requires less filesystem access. --- cabal-install/Distribution/Client/CmdExec.hs | 56 ++++++-------------- 1 file changed, 16 insertions(+), 40 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 8ab8bb34258..04110d0faa3 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -36,7 +36,8 @@ import Distribution.Client.ProjectPlanOutput , createPackageEnvironment ) import Distribution.Client.ProjectPlanning - ( ElaboratedInstallPlan + ( ElaboratedConfiguredPackage(elabPkgDescription) + , ElaboratedInstallPlan , ElaboratedSharedConfig(..) , binDirectory ) @@ -65,12 +66,14 @@ import Distribution.Simple.Setup , haddockDistPref, haddockVerbosity ) import Distribution.Simple.Utils - ( debug - , die + ( die , info , withTempDirectory , wrapText ) +import Distribution.Types.PackageDescription + ( executables + ) import Distribution.Verbosity ( Verbosity ) @@ -80,9 +83,6 @@ import Distribution.Client.Compat.Prelude import Data.Set (Set) import qualified Data.Set as S -import System.Directory (executable, getDirectoryContents, getPermissions) -import System.FilePath (()) -import System.IO.Error (catchIOError) execCommand :: CommandUI ExecFlags execCommand = CommandUI @@ -187,14 +187,12 @@ execAction execFlags extraArgs globalFlags = do pathAdditions :: Verbosity -> ProjectBuildContext -> IO [FilePath] pathAdditions verbosity ProjectBuildContext{..} = do - debug verbosity $ "Considering the following directories for inclusion in PATH:" - traverse_ (debug verbosity) paths - occupiedPaths <- filterM hasExecutable (S.toAscList paths) - info verbosity $ "Including the following directories in PATH:" - traverse_ (info verbosity) occupiedPaths - return occupiedPaths + info verbosity . unlines $ "Including the following directories in PATH:" + : paths + return paths where - paths = binDirectories distDirLayout elaboratedShared elaboratedPlanToExecute + paths = S.toList + $ binDirectories distDirLayout elaboratedShared elaboratedPlanToExecute binDirectories :: DistDirLayout @@ -204,35 +202,13 @@ binDirectories binDirectories layout config = fromElaboratedInstallPlan where fromElaboratedInstallPlan = fromGraph . toGraph fromGraph = foldMap fromPlan - fromSrcPkg pkg = S.singleton (binDirectory layout config pkg) + fromSrcPkg pkg = if hasExecutable pkg + then S.singleton (binDirectory layout config pkg) + else mempty fromPlan (PreExisting _) = mempty fromPlan (Configured pkg) = fromSrcPkg pkg fromPlan (Installed pkg) = fromSrcPkg pkg --- This exists because old versions of the directory package don't supply it. --- If our dependency on directory ever bumps up to above 1.2.5 this should be --- deleted. --- | Returns a list of all entries in the directory except the special entries --- @.@ and @..@. -listDirectory :: FilePath -> IO [FilePath] -listDirectory d = filter (`notElem` [".", ".."]) <$> getDirectoryContents d - --- | Check whether a directory contains an executable. -hasExecutable :: FilePath -> IO Bool -hasExecutable dir = catchIOError - (listDirectory dir >>= anyM (isExecutable . (dir))) - (\_ -> return False) - --- | Check whether a file is an executable. -isExecutable :: FilePath -> IO Bool -isExecutable file = catchIOError - (executable <$> getPermissions file) - (\_ -> return False) - --- | Like 'any', but short-circuits side-effects, too. -anyM :: Monad m => (a -> m Bool) -> [a] -> m Bool -anyM _ [] = return False -anyM f (x:xs) = do - fx <- f x - if fx then return True else anyM f xs +hasExecutable :: ElaboratedConfiguredPackage -> Bool +hasExecutable = not . null . executables . elabPkgDescription From e49880ba7c9255bc5252a9945f212dde490ae6cc Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Feb 2017 13:02:00 -0800 Subject: [PATCH 10/34] comment on a tricky line of code --- cabal-install/Distribution/Client/CmdExec.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 04110d0faa3..b61b0fd8b9c 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -143,6 +143,11 @@ execAction execFlags extraArgs globalFlags = do { hookPrePlanning = \_ _ _ -> return () , hookSelectPlanSubset = \_ -> return } + + -- We use the build status below to decide what libraries to include in the + -- compiler environment, but we don't want to actually build anything. So we + -- pass mempty to indicate that nothing happened and we just want the current + -- status. buildStatus <- updatePostBuildProjectStatus verbosity (distDirLayout buildCtx) From a6df3e821429cfb9d7de4315d64b929dcfc173bd Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Mon, 13 Feb 2017 13:22:08 -0800 Subject: [PATCH 11/34] accept all new-build flags in new-exec --- cabal-install/Distribution/Client/CmdExec.hs | 51 ++++++-------------- 1 file changed, 16 insertions(+), 35 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index b61b0fd8b9c..6093ebbc62f 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -22,9 +22,11 @@ import Distribution.Client.InstallPlan , toGraph ) import Distribution.Client.Setup - ( GlobalFlags(..) - , ExecFlags(..) - , defaultExecFlags + ( ConfigExFlags + , ConfigFlags(configVerbosity) + , GlobalFlags + , InstallFlags + , installCommand ) import Distribution.Client.ProjectOrchestration ( ProjectBuildContext(..) @@ -60,10 +62,8 @@ import Distribution.Simple.Program.Types , simpleProgram ) import Distribution.Simple.Setup - ( fromFlag - , optionDistPref, optionVerbosity - , configDistPref, configVerbosity - , haddockDistPref, haddockVerbosity + ( HaddockFlags + , fromFlagOrDefault ) import Distribution.Simple.Utils ( die @@ -76,6 +76,7 @@ import Distribution.Types.PackageDescription ) import Distribution.Verbosity ( Verbosity + , normal ) import Prelude () @@ -84,8 +85,8 @@ import Distribution.Client.Compat.Prelude import Data.Set (Set) import qualified Data.Set as S -execCommand :: CommandUI ExecFlags -execCommand = CommandUI +execCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) +execCommand = installCommand { commandName = "new-exec" , commandSynopsis = "Give a command access to the store." , commandUsage = \pname -> @@ -105,40 +106,20 @@ execCommand = CommandUI ++ " to choose an appropriate version of ghc and to include any" ++ " ghc-specific flags requested." , commandNotes = Nothing - , commandDefaultFlags = defaultExecFlags - , commandOptions = \showOrParseArgs -> - [ optionVerbosity execVerbosity (\v flags -> flags { execVerbosity = v }) - , optionDistPref - execDistPref (\v flags -> flags { execDistPref = v }) - showOrParseArgs - ] } -execAction :: ExecFlags -> [String] -> GlobalFlags -> IO () -execAction execFlags extraArgs globalFlags = do - let verbosity = fromFlag (execVerbosity execFlags) +execAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) + -> [String] -> GlobalFlags -> IO () +execAction (configFlags, configExFlags, installFlags, haddockFlags) + extraArgs globalFlags = do + let verbosity = fromFlagOrDefault normal (configVerbosity configFlags) -- To set up the environment, we'd like to select the libraries in our -- dependency tree that we've already built. So first we set up an install -- plan, but we walk the dependency tree without first executing the plan. - -- - -- TODO: We set a lot of default settings here (with mempty). It might be - -- worth walking through each of the settings we default and making sure they - -- shouldn't become ExecFlags. buildCtx <- runProjectPreBuildPhase verbosity - ( globalFlags - , mempty - { configDistPref = execDistPref execFlags - , configVerbosity = execVerbosity execFlags - } - , mempty - , mempty - , mempty - { haddockDistPref = execDistPref execFlags - , haddockVerbosity = execVerbosity execFlags - } - ) + (globalFlags, configFlags, configExFlags, installFlags, haddockFlags) PreBuildHooks { hookPrePlanning = \_ _ _ -> return () , hookSelectPlanSubset = \_ -> return From 108ab93ba6d429a490f575b6e14bbe8f69746606 Mon Sep 17 00:00:00 2001 From: Daniel Wagner Date: Tue, 14 Feb 2017 16:42:04 -0800 Subject: [PATCH 12/34] allow new-exec'ing of executables built inplace Previously, new-exec would use the `build` directory when looking for executables built inplace. But these executables are actually in subdirectories of `build`, so the search would fail (potentially falling back to an executable in the user's PATH instead). Now we place one directory in the PATH for each executable in each inplace-build package in the install plan. --- cabal-install/Distribution/Client/CmdExec.hs | 15 ++----- .../Distribution/Client/ProjectPlanning.hs | 45 +++++++++++++++++-- 2 files changed, 45 insertions(+), 15 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 6093ebbc62f..e1b037cbe03 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -37,11 +37,10 @@ import Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus , createPackageEnvironment ) +import qualified Distribution.Client.ProjectPlanning as Planning import Distribution.Client.ProjectPlanning - ( ElaboratedConfiguredPackage(elabPkgDescription) - , ElaboratedInstallPlan + ( ElaboratedInstallPlan , ElaboratedSharedConfig(..) - , binDirectory ) import Distribution.Simple.Command ( CommandUI(..) @@ -71,9 +70,6 @@ import Distribution.Simple.Utils , withTempDirectory , wrapText ) -import Distribution.Types.PackageDescription - ( executables - ) import Distribution.Verbosity ( Verbosity , normal @@ -188,13 +184,8 @@ binDirectories binDirectories layout config = fromElaboratedInstallPlan where fromElaboratedInstallPlan = fromGraph . toGraph fromGraph = foldMap fromPlan - fromSrcPkg pkg = if hasExecutable pkg - then S.singleton (binDirectory layout config pkg) - else mempty + fromSrcPkg = S.fromList . Planning.binDirectories layout config fromPlan (PreExisting _) = mempty fromPlan (Configured pkg) = fromSrcPkg pkg fromPlan (Installed pkg) = fromSrcPkg pkg - -hasExecutable :: ElaboratedConfiguredPackage -> Bool -hasExecutable = not . null . executables . elabPkgDescription diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index 3649d023686..4fa1695d265 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -51,9 +51,7 @@ module Distribution.Client.ProjectPlanning ( -- TODO: [code cleanup] utils that should live in some shared place? createPackageDBIfMissing, - inplaceBinDirectory, - installedBinDirectory, - binDirectory + binDirectories ) where import Prelude () @@ -1800,8 +1798,14 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB -- + vanilla libs & exes, exe needs lib, recursive -- + ghci or shared lib needed by TH, recursive, ghc version dependent +-- TODO: Delete this and binDirectory. -- | Get the bin\/ directory that executables should reside in, assuming that -- they are the result of an in-place build. +-- +-- For packages that get built inplace, the executable named @foo@ goes in +-- @bin/foo/foo@, and this function will return just @bin@. The more general +-- 'inplaceBinDirectories' will return @bin/foo@ (and @bin/bar@, etc., one such +-- directory for each executable in the package). inplaceBinDirectory :: DistDirLayout -> ElaboratedSharedConfig @@ -1822,7 +1826,13 @@ inplaceBinDirectory layout config package installedBinDirectory :: ElaboratedConfiguredPackage -> FilePath installedBinDirectory = InstallDirs.bindir . elabInstallDirs +-- TODO: Probably calling this is a mistake. We should check each caller and +-- make sure it shouldn't be transitioned to binDirectories instead, then +-- delete this function. -- | Get the bin\/ directory that a package's executables should reside in. +-- +-- See also the more general 'binDirectories', which handles packages built +-- inplace more gracefully. binDirectory :: DistDirLayout -> ElaboratedSharedConfig @@ -1833,6 +1843,35 @@ binDirectory layout config package = then inplaceBinDirectory layout config package else installedBinDirectory package +-- | Get the bin\/ directories that a package's executables should reside in. +-- +-- The result may be empty if the package does not build any executables. +-- +-- The result may have several entries if this is an inplace build of a package +-- with multiple executables. +binDirectories + :: DistDirLayout + -> ElaboratedSharedConfig + -> ElaboratedConfiguredPackage + -> [FilePath] +binDirectories layout config package = case elabBuildStyle package of + -- quick sanity check: no sense returning a bin directory if we're not going + -- to put any executables in it, that will just clog up the PATH + _ | noExecutables -> [] + BuildAndInstall -> [installedBinDirectory package] + BuildInplaceOnly -> map (root) $ case elabPkgOrComp package of + ElabComponent comp -> case compSolverName comp of + CD.ComponentExe n -> [display n] + _ -> [] + ElabPackage _ -> map (display . PD.exeName) + . PD.executables + . elabPkgDescription + $ package + where + noExecutables = null . PD.executables . elabPkgDescription $ package + root = distBuildDirectory layout (elabDistDirParams config package) + "build" + -- | A newtype for 'SolverInstallPlan.SolverPlanPackage' for which the -- dependency graph considers only dependencies on libraries which are -- NOT from setup dependencies. Used to compute the set From b13bcbfe9780be91eb7f22996df03c8d5dad5279 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Thu, 20 Jul 2017 22:51:48 +0200 Subject: [PATCH 13/34] Make new-bench actually run the benchmarks Based on new-test. --- cabal-install/Distribution/Client/CmdBench.hs | 2 +- .../Distribution/Client/ProjectBuilding.hs | 19 ++++++++++++-- .../Client/ProjectBuilding/Types.hs | 1 + .../Client/ProjectOrchestration.hs | 2 ++ .../Distribution/Client/ProjectPlanning.hs | 25 +++++++++++++++++++ .../Client/ProjectPlanning/Types.hs | 6 +++++ 6 files changed, 52 insertions(+), 3 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdBench.hs b/cabal-install/Distribution/Client/CmdBench.hs index 0bc4ff4d24a..113317119f1 100644 --- a/cabal-install/Distribution/Client/CmdBench.hs +++ b/cabal-install/Distribution/Client/CmdBench.hs @@ -103,7 +103,7 @@ benchAction (configFlags, configExFlags, installFlags, haddockFlags) targetSelectors let elaboratedPlan' = pruneInstallPlanToTargets - TargetActionBuild + TargetActionBench targets elaboratedPlan return (elaboratedPlan', targets) diff --git a/cabal-install/Distribution/Client/ProjectBuilding.hs b/cabal-install/Distribution/Client/ProjectBuilding.hs index 7bce035d17e..7e574f30c43 100644 --- a/cabal-install/Distribution/Client/ProjectBuilding.hs +++ b/cabal-install/Distribution/Client/ProjectBuilding.hs @@ -357,6 +357,7 @@ packageFileMonitorKeyValues elab = elab { elabBuildTargets = [], elabTestTargets = [], + elabBenchTargets = [], elabReplTarget = Nothing, elabBuildHaddocks = False } @@ -1161,6 +1162,10 @@ buildInplaceUnpackedPackage verbosity annotateFailureNoLog TestsFailed $ setup testCommand testFlags testArgs + whenBench $ + annotateFailureNoLog BenchFailed $ + setup benchCommand benchFlags benchArgs + -- Repl phase -- whenRepl $ @@ -1199,14 +1204,19 @@ buildInplaceUnpackedPackage verbosity whenRebuild action | null (elabBuildTargets pkg) - -- NB: we have to build the test suite! - , null (elabTestTargets pkg) = return () + -- NB: we have to build the test/bench suite! + , null (elabTestTargets pkg) + , null (elabBenchTargets pkg) = return () | otherwise = action whenTest action | null (elabTestTargets pkg) = return () | otherwise = action + whenBench action + | null (elabBenchTargets pkg) = return () + | otherwise = action + whenRepl action | isNothing (elabReplTarget pkg) = return () | otherwise = action @@ -1239,6 +1249,11 @@ buildInplaceUnpackedPackage verbosity verbosity builddir testArgs = setupHsTestArgs pkg + benchCommand = Cabal.benchmarkCommand + benchFlags _ = setupHsBenchFlags pkg pkgshared + verbosity builddir + benchArgs = setupHsBenchArgs pkg + replCommand = Cabal.replCommand defaultProgramDb replFlags _ = setupHsReplFlags pkg pkgshared verbosity builddir diff --git a/cabal-install/Distribution/Client/ProjectBuilding/Types.hs b/cabal-install/Distribution/Client/ProjectBuilding/Types.hs index 24ca5149652..2ceff15c944 100644 --- a/cabal-install/Distribution/Client/ProjectBuilding/Types.hs +++ b/cabal-install/Distribution/Client/ProjectBuilding/Types.hs @@ -201,6 +201,7 @@ data BuildFailureReason = DependentFailed PackageId | ReplFailed SomeException | HaddocksFailed SomeException | TestsFailed SomeException + | BenchFailed SomeException | InstallFailed SomeException deriving Show diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index 6712769cf92..6e0157aef9b 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -892,6 +892,7 @@ dieOnBuildFailures verbosity plan buildOutcomes ReplFailed _ -> "repl failed for " ++ pkgstr HaddocksFailed _ -> "Failed to build documentation for " ++ pkgstr TestsFailed _ -> "Tests failed for " ++ pkgstr + BenchFailed _ -> "Benchmarks failed for " ++ pkgstr InstallFailed _ -> "Failed to build " ++ pkgstr DependentFailed depid -> "Failed to build " ++ display (packageId pkg) @@ -975,6 +976,7 @@ dieOnBuildFailures verbosity plan buildOutcomes ReplFailed e -> Just e HaddocksFailed e -> Just e TestsFailed e -> Just e + BenchFailed e -> Just e InstallFailed e -> Just e DependentFailed _ -> Nothing diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index e1616029b5c..e948a002963 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -51,6 +51,8 @@ module Distribution.Client.ProjectPlanning ( setupHsReplArgs, setupHsTestFlags, setupHsTestArgs, + setupHsBenchFlags, + setupHsBenchArgs, setupHsCopyFlags, setupHsRegisterFlags, setupHsHaddockFlags, @@ -1638,6 +1640,7 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB -- Check the comments of those functions for more details. elabBuildTargets = [] elabTestTargets = [] + elabBenchTargets = [] elabReplTarget = Nothing elabBuildHaddocks = False @@ -2304,6 +2307,7 @@ pkgHasEphemeralBuildTargets :: ElaboratedConfiguredPackage -> Bool pkgHasEphemeralBuildTargets elab = isJust (elabReplTarget elab) || (not . null) (elabTestTargets elab) + || (not . null) (elabBenchTargets elab) || (not . null) [ () | ComponentTarget _ subtarget <- elabBuildTargets elab , subtarget /= WholeComponent ] @@ -2329,6 +2333,7 @@ elabBuildTargetWholeComponents elab = data TargetAction = TargetActionBuild | TargetActionRepl | TargetActionTest + | TargetActionBench | TargetActionHaddock -- | Given a set of per-package\/per-component targets, take the subset of the @@ -2396,6 +2401,7 @@ setRootTargets targetAction perPkgTargetsMap = (Nothing, _) -> elab (Just tgts, TargetActionBuild) -> elab { elabBuildTargets = tgts } (Just tgts, TargetActionTest) -> elab { elabTestTargets = tgts } + (Just tgts, TargetActionBench) -> elab { elabBenchTargets = tgts } (Just [tgt], TargetActionRepl) -> elab { elabReplTarget = Just tgt } (Just _, TargetActionHaddock) -> elab { elabBuildHaddocks = True } (Just _, TargetActionRepl) -> @@ -2426,6 +2432,7 @@ pruneInstallPlanPass1 pkgs = find_root (InstallPlan.Configured (PrunedPackage elab _)) = if not (null (elabBuildTargets elab) && null (elabTestTargets elab) + && null (elabBenchTargets elab) && isNothing (elabReplTarget elab) && not (elabBuildHaddocks elab)) then Just (installedUnitId elab) @@ -2484,6 +2491,7 @@ pruneInstallPlanPass1 pkgs = [ stanza | ComponentTarget cname _ <- elabBuildTargets pkg ++ elabTestTargets pkg + ++ elabBenchTargets pkg ++ maybeToList (elabReplTarget pkg) , stanza <- maybeToList (componentOptionalStanza cname) ] @@ -3128,6 +3136,23 @@ setupHsTestArgs :: ElaboratedConfiguredPackage -> [String] setupHsTestArgs elab = mapMaybe (showTestComponentTarget (packageId elab)) (elabTestTargets elab) + +setupHsBenchFlags :: ElaboratedConfiguredPackage + -> ElaboratedSharedConfig + -> Verbosity + -> FilePath + -> Cabal.BenchmarkFlags +setupHsBenchFlags _ _ verbosity builddir = Cabal.BenchmarkFlags + { benchmarkDistPref = toFlag builddir + , benchmarkVerbosity = toFlag verbosity + , benchmarkOptions = mempty + } + +setupHsBenchArgs :: ElaboratedConfiguredPackage -> [String] +setupHsBenchArgs elab = + mapMaybe (showBenchComponentTarget (packageId elab)) (elabBenchTargets elab) + + setupHsReplFlags :: ElaboratedConfiguredPackage -> ElaboratedSharedConfig -> Verbosity diff --git a/cabal-install/Distribution/Client/ProjectPlanning/Types.hs b/cabal-install/Distribution/Client/ProjectPlanning/Types.hs index c0a1faa8ba4..cbce1858e48 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning/Types.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning/Types.hs @@ -42,6 +42,7 @@ module Distribution.Client.ProjectPlanning.Types ( ComponentTarget(..), showComponentTarget, showTestComponentTarget, + showBenchComponentTarget, SubComponentTarget(..), isTestComponentTarget, @@ -284,6 +285,7 @@ data ElaboratedConfiguredPackage -- Build time related: elabBuildTargets :: [ComponentTarget], elabTestTargets :: [ComponentTarget], + elabBenchTargets :: [ComponentTarget], elabReplTarget :: Maybe ComponentTarget, elabBuildHaddocks :: Bool, @@ -659,6 +661,10 @@ isTestComponentTarget :: ComponentTarget -> Bool isTestComponentTarget (ComponentTarget (CTestName _) _) = True isTestComponentTarget _ = False +showBenchComponentTarget :: PackageId -> ComponentTarget -> Maybe String +showBenchComponentTarget _ (ComponentTarget (CBenchName n) _) = Just $ display n +showBenchComponentTarget _ _ = Nothing + --------------------------- -- Setup.hs script policy -- From ae9ae09568a587a02e87b1eb9ff1dad9cec29d17 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 22 Jul 2017 12:54:34 +0200 Subject: [PATCH 14/34] Add brief description of mew-bench in docs --- Cabal/doc/nix-local-build.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Cabal/doc/nix-local-build.rst b/Cabal/doc/nix-local-build.rst index 4be4536e673..96bb23f7656 100644 --- a/Cabal/doc/nix-local-build.rst +++ b/Cabal/doc/nix-local-build.rst @@ -395,6 +395,13 @@ users see a consistent set of dependencies. For libraries, this is not recommended: users often need to build against different versions of libraries than what you developed against. +cabal new-bench +--------------- + +``cabal new-bench [TARGETS] [OPTIONS]`` runs the specified benchmarks +(all the benchmarks in the current package by default), first ensuring +they are up to date. + Unsupported commands -------------------- From f7c2b18f5b18ea3d9e107d79ee91db7cb8c2a6a4 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Sat, 22 Jul 2017 12:56:23 +0200 Subject: [PATCH 15/34] Add new-bench to changelog --- cabal-install/changelog | 1 + 1 file changed, 1 insertion(+) diff --git a/cabal-install/changelog b/cabal-install/changelog index edc4a6b5e3b..13cc7e310a9 100644 --- a/cabal-install/changelog +++ b/cabal-install/changelog @@ -8,6 +8,7 @@ * Completed the 'new-run' command (#4477). The functionality is the same of the old 'run' command but using nix-style builds. Additionally, it can run executables across packages in a project. + * Completed the 'new-bench' command. Same as above. * '--allow-{newer,older}' syntax has been enhanced. Dependency relaxation can be now limited to a specific release of a package, plus there's a now syntax for relaxing only caret dependencies From 57763ca4729a361c249891330e192b6dc6761957 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Fri, 11 Aug 2017 11:40:39 +0200 Subject: [PATCH 16/34] Adapt new-exec to the new new-build structure --- cabal-install/Distribution/Client/CmdExec.hs | 48 +++++++++++-------- .../Client/ProjectOrchestration.hs | 2 +- .../Distribution/Client/ProjectPlanOutput.hs | 6 +-- .../Distribution/Client/ProjectPlanning.hs | 7 --- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index e1b037cbe03..0c9a33448a1 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -30,8 +30,11 @@ import Distribution.Client.Setup ) import Distribution.Client.ProjectOrchestration ( ProjectBuildContext(..) - , PreBuildHooks(..) , runProjectPreBuildPhase + , establishProjectBaseContext + , distDirLayout + , commandLineFlagsToProjectConfig + , ProjectBaseContext(..) ) import Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus @@ -65,7 +68,7 @@ import Distribution.Simple.Setup , fromFlagOrDefault ) import Distribution.Simple.Utils - ( die + ( die' , info , withTempDirectory , wrapText @@ -80,6 +83,7 @@ import Distribution.Client.Compat.Prelude import Data.Set (Set) import qualified Data.Set as S +import qualified Data.Map as M execCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) execCommand = installCommand @@ -108,18 +112,16 @@ execAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) -> [String] -> GlobalFlags -> IO () execAction (configFlags, configExFlags, installFlags, haddockFlags) extraArgs globalFlags = do - let verbosity = fromFlagOrDefault normal (configVerbosity configFlags) + + baseCtx <- establishProjectBaseContext verbosity cliConfig -- To set up the environment, we'd like to select the libraries in our -- dependency tree that we've already built. So first we set up an install -- plan, but we walk the dependency tree without first executing the plan. buildCtx <- runProjectPreBuildPhase verbosity - (globalFlags, configFlags, configExFlags, installFlags, haddockFlags) - PreBuildHooks - { hookPrePlanning = \_ _ _ -> return () - , hookSelectPlanSubset = \_ -> return - } + baseCtx + (\plan -> return (plan, M.empty)) -- We use the build status below to decide what libraries to include in the -- compiler environment, but we don't want to actually build anything. So we @@ -127,8 +129,8 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) -- status. buildStatus <- updatePostBuildProjectStatus verbosity - (distDirLayout buildCtx) - (elaboratedPlanToExecute buildCtx) + (distDirLayout baseCtx) + (elaboratedPlanOriginal buildCtx) (pkgsBuildStatus buildCtx) mempty @@ -136,20 +138,21 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) -- by creating an environment file that selects the databases and packages we -- computed in the previous step, and setting an environment variable to -- point at the file. - withTempDirectory + {-withTempDirectory verbosity - (distTempDirectory (distDirLayout buildCtx)) + (distTempDirectory (distDirLayout baseCtx)) "environment." - $ \tmpDir -> do + $ \tmpDir -> do-} + do envOverrides <- createPackageEnvironment verbosity - tmpDir + (distDirLayout baseCtx)--tmpDir (elaboratedPlanToExecute buildCtx) (elaboratedShared buildCtx) buildStatus -- Some dependencies may have executables. Let's put those on the PATH. - extraPaths <- pathAdditions verbosity buildCtx + extraPaths <- pathAdditions verbosity baseCtx buildCtx let programDb = modifyProgramSearchPath (map ProgramSearchPathDir extraPaths ++) . pkgConfigCompilerProgs @@ -162,13 +165,17 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) let program' = withOverrides envOverrides program invocation = programInvocation program' args runProgramInvocation verbosity invocation - [] -> die "Please specify an executable to run" + [] -> die' verbosity "Please specify an executable to run" where - withOverrides env program = program - { programOverrideEnv = programOverrideEnv program ++ env } + verbosity = fromFlagOrDefault normal (configVerbosity configFlags) + cliConfig = commandLineFlagsToProjectConfig + globalFlags configFlags configExFlags + installFlags haddockFlags + withOverrides env program = program + { programOverrideEnv = programOverrideEnv program ++ env } -pathAdditions :: Verbosity -> ProjectBuildContext -> IO [FilePath] -pathAdditions verbosity ProjectBuildContext{..} = do +pathAdditions :: Verbosity -> ProjectBaseContext -> ProjectBuildContext -> IO [FilePath] +pathAdditions verbosity ProjectBaseContext{..}ProjectBuildContext{..} = do info verbosity . unlines $ "Including the following directories in PATH:" : paths return paths @@ -189,3 +196,4 @@ binDirectories layout config = fromElaboratedInstallPlan where fromPlan (PreExisting _) = mempty fromPlan (Configured pkg) = fromSrcPkg pkg fromPlan (Installed pkg) = fromSrcPkg pkg + diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index 1cd3a24dd16..6e0157aef9b 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -334,7 +334,7 @@ runProjectPostBuildPhase verbosity -- - delete stale lib registrations -- - delete stale package dirs - _postBuildStatus <- updatePostBuildProjectStatus + postBuildStatus <- updatePostBuildProjectStatus verbosity distDirLayout elaboratedPlanOriginal diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index eed306e5040..61bca51c150 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -666,20 +666,20 @@ writePackagesUpToDateCacheFile DistDirLayout{distProjectCacheFile} upToDate = -- filesystem, and returns any environment variable overrides the compiler -- needs. createPackageEnvironment :: Verbosity - -> FilePath + -> DistDirLayout -> ElaboratedInstallPlan -> ElaboratedSharedConfig -> PostBuildProjectStatus -> IO [(String, Maybe String)] createPackageEnvironment verbosity - tmpDir + distDirLayout elaboratedPlan elaboratedShared buildStatus | compilerFlavor (pkgConfigCompiler elaboratedShared) == GHC = do envFileM <- writePlanGhcEnvironment - tmpDir + distDirLayout elaboratedPlan elaboratedShared buildStatus diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index f3bda01088b..3b6b5a3185f 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -61,8 +61,6 @@ module Distribution.Client.ProjectPlanning ( -- * Path construction binDirectoryFor, - -- TODO: [code cleanup] utils that should live in some shared place? - createPackageDBIfMissing, binDirectories ) where @@ -1948,11 +1946,6 @@ inplaceBinDirectory layout config package Just n -> display n _ -> "" --- | Get the bin\/ directory that executables should reside in after the --- package has been built and installed. -installedBinDirectory :: ElaboratedConfiguredPackage -> FilePath -installedBinDirectory = InstallDirs.bindir . elabInstallDirs - -- TODO: Probably calling this is a mistake. We should check each caller and -- make sure it shouldn't be transitioned to binDirectories instead, then -- delete this function. From ce2518d6017b8b0cacfb704b4041ebb02c133195 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Fri, 11 Aug 2017 14:07:53 +0200 Subject: [PATCH 17/34] Fix some warnings --- .../Client/ProjectOrchestration.hs | 8 ++-- .../Distribution/Client/ProjectPlanning.hs | 39 ------------------- 2 files changed, 4 insertions(+), 43 deletions(-) diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index c02350e1c7c..4263d641ebb 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -349,10 +349,10 @@ runProjectPostBuildPhase verbosity pkgsBuildStatus buildOutcomes - writePlanGhcEnvironment distDirLayout - elaboratedPlanOriginal - elaboratedShared - postBuildStatus + _ <- writePlanGhcEnvironment distDirLayout + elaboratedPlanOriginal + elaboratedShared + postBuildStatus -- Finally if there were any build failures then report them and throw -- an exception to terminate the program diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index 743f90d5b97..602d5150eee 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -1928,45 +1928,6 @@ mkShapeMapping dpkg = IndefFullUnitId dcid (Map.fromList [ (req, OpenModuleVar req) | req <- Set.toList (modShapeRequires shape)]) --- TODO: Delete this and binDirectory. --- | Get the bin\/ directory that executables should reside in, assuming that --- they are the result of an in-place build. --- --- For packages that get built inplace, the executable named @foo@ goes in --- @bin/foo/foo@, and this function will return just @bin@. The more general --- 'inplaceBinDirectories' will return @bin/foo@ (and @bin/bar@, etc., one such --- directory for each executable in the package). -inplaceBinDirectory - :: DistDirLayout - -> ElaboratedSharedConfig - -> ElaboratedConfiguredPackage - -> FilePath -inplaceBinDirectory layout config package - = distBuildDirectory layout (elabDistDirParams config package) - "build" - case elabPkgOrComp package of - ElabPackage _ -> "" - ElabComponent comp -> case compComponentName comp >>= - Cabal.componentNameString of - Just n -> display n - _ -> "" - --- TODO: Probably calling this is a mistake. We should check each caller and --- make sure it shouldn't be transitioned to binDirectories instead, then --- delete this function. --- | Get the bin\/ directory that a package's executables should reside in. --- --- See also the more general 'binDirectories', which handles packages built --- inplace more gracefully. -binDirectory - :: DistDirLayout - -> ElaboratedSharedConfig - -> ElaboratedConfiguredPackage - -> FilePath -binDirectory layout config package = - if elabBuildStyle package == BuildInplaceOnly - then inplaceBinDirectory layout config package - else installedBinDirectory package -- | Get the bin\/ directories that a package's executables should reside in. -- From 4ee6da96076fa7165a7ecba94d2d560ffbafe17b Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 22 Aug 2017 10:29:28 +0200 Subject: [PATCH 18/34] Re-enable .ghc.env temp directory for new-exec --- cabal-install/Distribution/Client/CmdExec.hs | 7 +++---- .../Distribution/Client/ProjectOrchestration.hs | 3 ++- .../Distribution/Client/ProjectPlanOutput.hs | 14 +++++++------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 0c9a33448a1..141ec24a281 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -138,15 +138,14 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) -- by creating an environment file that selects the databases and packages we -- computed in the previous step, and setting an environment variable to -- point at the file. - {-withTempDirectory + withTempDirectory verbosity (distTempDirectory (distDirLayout baseCtx)) "environment." - $ \tmpDir -> do-} - do + $ \tmpDir -> do envOverrides <- createPackageEnvironment verbosity - (distDirLayout baseCtx)--tmpDir + tmpDir (elaboratedPlanToExecute buildCtx) (elaboratedShared buildCtx) buildStatus diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index 4263d641ebb..25e4c813644 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -349,7 +349,8 @@ runProjectPostBuildPhase verbosity pkgsBuildStatus buildOutcomes - _ <- writePlanGhcEnvironment distDirLayout + _ <- writePlanGhcEnvironment (distProjectRootDirectory + distDirLayout) elaboratedPlanOriginal elaboratedShared postBuildStatus diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 61bca51c150..22db5fda3a6 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -666,20 +666,20 @@ writePackagesUpToDateCacheFile DistDirLayout{distProjectCacheFile} upToDate = -- filesystem, and returns any environment variable overrides the compiler -- needs. createPackageEnvironment :: Verbosity - -> DistDirLayout + -> FilePath -> ElaboratedInstallPlan -> ElaboratedSharedConfig -> PostBuildProjectStatus -> IO [(String, Maybe String)] createPackageEnvironment verbosity - distDirLayout + path elaboratedPlan elaboratedShared buildStatus | compilerFlavor (pkgConfigCompiler elaboratedShared) == GHC = do envFileM <- writePlanGhcEnvironment - distDirLayout + path elaboratedPlan elaboratedShared buildStatus @@ -696,12 +696,12 @@ createPackageEnvironment verbosity -- Writing .ghc.environment files -- -writePlanGhcEnvironment :: DistDirLayout +writePlanGhcEnvironment :: FilePath -> ElaboratedInstallPlan -> ElaboratedSharedConfig -> PostBuildProjectStatus -> IO (Maybe FilePath) -writePlanGhcEnvironment DistDirLayout{distProjectRootDirectory} +writePlanGhcEnvironment path elaboratedInstallPlan ElaboratedSharedConfig { pkgConfigCompiler = compiler, @@ -712,9 +712,9 @@ writePlanGhcEnvironment DistDirLayout{distProjectRootDirectory} , supportsPkgEnvFiles (getImplInfo compiler) --TODO: check ghcjs compat = fmap Just $ writeGhcEnvironmentFile - distProjectRootDirectory + path platform (compilerVersion compiler) - (renderGhcEnvironmentFile distProjectRootDirectory + (renderGhcEnvironmentFile path elaboratedInstallPlan postBuildStatus) --TODO: [required eventually] support for writing user-wide package From 33a8b51e97519c2ce59f0fdff0f0e7c4cb1b6ddc Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 12:53:46 +0200 Subject: [PATCH 19/34] Add args fallback when we can't use .ghc.env files Still in progress. The support check doesn't work yet. --- Cabal/Distribution/Simple/Program/GHC.hs | 2 + cabal-install/Distribution/Client/CmdExec.hs | 53 +++++++++++++++++-- .../Distribution/Client/ProjectPlanOutput.hs | 30 ++++++++++- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/Cabal/Distribution/Simple/Program/GHC.hs b/Cabal/Distribution/Simple/Program/GHC.hs index 6e70a703ecf..0d756f11fd6 100644 --- a/Cabal/Distribution/Simple/Program/GHC.hs +++ b/Cabal/Distribution/Simple/Program/GHC.hs @@ -14,6 +14,8 @@ module Distribution.Simple.Program.GHC ( runGHC, + packageDbArgsDb, + ) where import Prelude () diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 141ec24a281..a84c6eaceb1 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -39,6 +39,7 @@ import Distribution.Client.ProjectOrchestration import Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus , createPackageEnvironment + , argsEquivalentOfGhcEnvironmentFile ) import qualified Distribution.Client.ProjectPlanning as Planning import Distribution.Client.ProjectPlanning @@ -61,7 +62,10 @@ import Distribution.Simple.Program.Run ) import Distribution.Simple.Program.Types ( programOverrideEnv + , programOverrideArgs , simpleProgram + , programId +-- , programVersion ) import Distribution.Simple.Setup ( HaddockFlags @@ -77,6 +81,7 @@ import Distribution.Verbosity ( Verbosity , normal ) +--import Distribution.Simple.GHC (supportsPkgEnvFiles) import Prelude () import Distribution.Client.Compat.Prelude @@ -161,7 +166,46 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) case extraArgs of exe:args -> do (program, _) <- requireProgram verbosity (simpleProgram exe) programDb - let program' = withOverrides envOverrides program + let argOverrides = + argsEquivalentOfGhcEnvironmentFile + (distDirLayout baseCtx) + (elaboratedPlanOriginal buildCtx) + buildStatus + isCompilerWithGhcFlags = + -- TODO how do I get this? + -- MAYBE just support ghc[js] + programId program `elem` ["ghc", "ghcjs", "lhc"] + envFilesAreSupported = fromMaybe False $ + --TODO replace all this with a generic + --getImplInfo + case programId program + of {-"ghc" -> + supportsPkgEnvFiles <$> + ghcVersionImplInfo <$> + programVersion program + "lhc" -> + supportsPkgEnvFiles <$> + lhcVersionImplInfo <$> + programVersion program + "ghcjs" -> + supportsPkgEnvFiles <$> + ghcjsVersionImplInfo <$> + programVersion program <*> + programVersion program --HACK + -} + _ -> Nothing + argOverrides' = + if + not isCompilerWithGhcFlags + || envFilesAreSupported + then + [] + else + argOverrides + program' = withOverrides + envOverrides + argOverrides' + program invocation = programInvocation program' args runProgramInvocation verbosity invocation [] -> die' verbosity "Please specify an executable to run" @@ -170,8 +214,11 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) cliConfig = commandLineFlagsToProjectConfig globalFlags configFlags configExFlags installFlags haddockFlags - withOverrides env program = program - { programOverrideEnv = programOverrideEnv program ++ env } + withOverrides env args program = program + { programOverrideEnv = programOverrideEnv program ++ env + -- XXX Override or Default? + , programOverrideArgs = programOverrideArgs program ++ args} + pathAdditions :: Verbosity -> ProjectBaseContext -> ProjectBuildContext -> IO [FilePath] pathAdditions verbosity ProjectBaseContext{..}ProjectBuildContext{..} = do diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 22db5fda3a6..5fb38cfaa1d 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -12,6 +12,7 @@ module Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus, createPackageEnvironment, writePlanGhcEnvironment, + argsEquivalentOfGhcEnvironmentFile, ) where import Distribution.Client.ProjectPlanning.Types @@ -46,8 +47,9 @@ import Distribution.Simple.Utils import Distribution.Verbosity import qualified Paths_cabal_install as Our (version) -import Data.Maybe (maybeToList, fromMaybe) -import Data.Monoid +import Prelude () +import Distribution.Client.Compat.Prelude + import qualified Data.Map as Map import Data.Set (Set) import qualified Data.Set as Set @@ -57,6 +59,7 @@ import qualified Data.ByteString.Builder as BB import System.FilePath import System.IO +import Distribution.Simple.Program.GHC (packageDbArgsDb) ----------------------------------------------------------------------------- -- Writing plan.json files @@ -744,6 +747,29 @@ renderGhcEnvironmentFile projectRootDir elaboratedInstallPlan selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan +-- remove this when we drop support for non-.ghc.env ghc +argsEquivalentOfGhcEnvironmentFile + :: DistDirLayout + -> ElaboratedInstallPlan + -> PostBuildProjectStatus + -> [String] +argsEquivalentOfGhcEnvironmentFile + distDirLayout + elaboratedInstallPlan + postBuildStatus = + clearPackageDbStackFlag + ++ packageDbArgsDb packageDBs + ++ foldMap packageIdFlag packageIds + where + projectRootDir = distProjectRootDirectory distDirLayout + packageIds = selectGhcEnvironmentFileLibraries postBuildStatus + packageDBs = relativePackageDBPaths projectRootDir $ + selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan + -- TODO use proper flags? but packageDbArgsDb is private + clearPackageDbStackFlag = ["-clear-package-db"] + packageIdFlag uid = ["-package-id", display uid] + + -- We're producing an environment for users to use in ghci, so of course -- that means libraries only (can't put exes into the ghc package env!). -- The library environment should be /consistent/ with the environment From e92310774840d7799c931abb610a233453989758 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 17:22:48 +0200 Subject: [PATCH 20/34] Add basic test for new-exec --- .../NewBuild/CmdExec/GhcInvocation/Main.hs | 2 ++ .../NewBuild/CmdExec/GhcInvocation/cabal.out | 9 +++++++++ .../CmdExec/GhcInvocation/cabal.project | 2 ++ .../CmdExec/GhcInvocation/cabal.test.hs | 17 +++++++++++++++++ .../GhcInvocation/inplace-dep/InplaceDep.hs | 5 +++++ .../GhcInvocation/inplace-dep/inplace-dep.cabal | 10 ++++++++++ 6 files changed, 45 insertions(+) create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/Main.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.project create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/InplaceDep.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/inplace-dep.cabal diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/Main.hs b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/Main.hs new file mode 100644 index 00000000000..6e3ea40e846 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/Main.hs @@ -0,0 +1,2 @@ +import InplaceDep +main = f diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.out b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.out new file mode 100644 index 00000000000..c1a6d3625fe --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.out @@ -0,0 +1,9 @@ +# cabal new-build +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - inplace-dep-1.0 (lib) (first run) +Configuring library for inplace-dep-1.0.. +Preprocessing library for inplace-dep-1.0.. +Building library for inplace-dep-1.0.. +# cabal new-exec diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.project b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.project new file mode 100644 index 00000000000..69b0621721b --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.project @@ -0,0 +1,2 @@ +packages: + inplace-dep diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs new file mode 100644 index 00000000000..6a9cb0a87c1 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/cabal.test.hs @@ -0,0 +1,17 @@ +import Test.Cabal.Prelude +import Control.Monad.Trans (liftIO) +import System.Directory-- (getDirectoryContents, removeFile) +main = cabalTest $ do + cabal "new-build" ["inplace-dep"] + env <- getTestEnv + liftIO $ removeEnvFiles $ testSourceDir env -- we don't want existing env files to interfere + cabal "new-exec" ["ghc", "Main.hs"] + -- TODO external (store) deps, once new-install is working + +removeEnvFiles :: FilePath -> IO () +removeEnvFiles dir = (mapM_ (removeFile . (dir )) + . filter + ((".ghc.environment" ==) + . take 16)) + =<< getDirectoryContents dir + diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/InplaceDep.hs b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/InplaceDep.hs new file mode 100644 index 00000000000..428dab1deb2 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/InplaceDep.hs @@ -0,0 +1,5 @@ +module InplaceDep ( f ) where + +f :: IO () +f = putStrLn "Hello world" + diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/inplace-dep.cabal b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/inplace-dep.cabal new file mode 100644 index 00000000000..614e67ae348 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/GhcInvocation/inplace-dep/inplace-dep.cabal @@ -0,0 +1,10 @@ +name: inplace-dep +version: 1.0 +build-type: Simple +cabal-version: >= 1.10 + +library + exposed-modules: InplaceDep + build-depends: base + default-language: Haskell2010 + From 5e454c6bd2dde98e28639f67fcd8438e65c1092e Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 17:50:43 +0200 Subject: [PATCH 21/34] Add global package env to new-exec ghc invocations The global db (note: not the user db) is needed (it contains `base`). --- cabal-install/Distribution/Client/ProjectPlanOutput.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 5fb38cfaa1d..3e03b24ac1e 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -766,7 +766,7 @@ argsEquivalentOfGhcEnvironmentFile packageDBs = relativePackageDBPaths projectRootDir $ selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan -- TODO use proper flags? but packageDbArgsDb is private - clearPackageDbStackFlag = ["-clear-package-db"] + clearPackageDbStackFlag = ["-clear-package-db", "-global-package-db"] packageIdFlag uid = ["-package-id", display uid] From 194453e4f1978944fe93ae1b81850b4307972137 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 19:00:34 +0200 Subject: [PATCH 22/34] Reorder things a bit Edge cases first, restrict do blocks... --- cabal-install/Distribution/Client/CmdExec.hs | 122 ++++++++++--------- 1 file changed, 62 insertions(+), 60 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index a84c6eaceb1..d69432fccaa 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -139,76 +139,78 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) (pkgsBuildStatus buildCtx) mempty + -- Some dependencies may have executables. Let's put those on the PATH. + extraPaths <- pathAdditions verbosity baseCtx buildCtx + let programDb = modifyProgramSearchPath + (map ProgramSearchPathDir extraPaths ++) + . pkgConfigCompilerProgs + . elaboratedShared + $ buildCtx + -- Now that we have the packages, set up the environment. We accomplish this -- by creating an environment file that selects the databases and packages we -- computed in the previous step, and setting an environment variable to -- point at the file. - withTempDirectory - verbosity - (distTempDirectory (distDirLayout baseCtx)) - "environment." - $ \tmpDir -> do - envOverrides <- createPackageEnvironment + -- In case ghc is too old to support environment files, + -- we pass the same info as arguments + case extraArgs of + [] -> die' verbosity "Please specify an executable to run" + exe:args -> do + (program, _) <- requireProgram verbosity (simpleProgram exe) programDb + let argOverrides = + argsEquivalentOfGhcEnvironmentFile + (distDirLayout baseCtx) + (elaboratedPlanOriginal buildCtx) + buildStatus + isCompilerWithGhcFlags = + -- TODO how do I get this? + -- MAYBE just support ghc[js] + programId program `elem` ["ghc", "ghcjs", "lhc"] + envFilesAreSupported = fromMaybe False $ + --TODO replace all this with a generic + --getImplInfo + case programId program + of {-"ghc" -> + supportsPkgEnvFiles <$> + ghcVersionImplInfo <$> + programVersion program + "lhc" -> + supportsPkgEnvFiles <$> + lhcVersionImplInfo <$> + programVersion program + "ghcjs" -> + supportsPkgEnvFiles <$> + ghcjsVersionImplInfo <$> + programVersion program <*> + programVersion program --HACK + -} + _ -> Nothing + argOverrides' = + if + not isCompilerWithGhcFlags + || envFilesAreSupported + then + [] + else + argOverrides + + withTempDirectory verbosity - tmpDir - (elaboratedPlanToExecute buildCtx) - (elaboratedShared buildCtx) - buildStatus - - -- Some dependencies may have executables. Let's put those on the PATH. - extraPaths <- pathAdditions verbosity baseCtx buildCtx - let programDb = modifyProgramSearchPath - (map ProgramSearchPathDir extraPaths ++) - . pkgConfigCompilerProgs - . elaboratedShared - $ buildCtx - - case extraArgs of - exe:args -> do - (program, _) <- requireProgram verbosity (simpleProgram exe) programDb - let argOverrides = - argsEquivalentOfGhcEnvironmentFile - (distDirLayout baseCtx) - (elaboratedPlanOriginal buildCtx) - buildStatus - isCompilerWithGhcFlags = - -- TODO how do I get this? - -- MAYBE just support ghc[js] - programId program `elem` ["ghc", "ghcjs", "lhc"] - envFilesAreSupported = fromMaybe False $ - --TODO replace all this with a generic - --getImplInfo - case programId program - of {-"ghc" -> - supportsPkgEnvFiles <$> - ghcVersionImplInfo <$> - programVersion program - "lhc" -> - supportsPkgEnvFiles <$> - lhcVersionImplInfo <$> - programVersion program - "ghcjs" -> - supportsPkgEnvFiles <$> - ghcjsVersionImplInfo <$> - programVersion program <*> - programVersion program --HACK - -} - _ -> Nothing - argOverrides' = - if - not isCompilerWithGhcFlags - || envFilesAreSupported - then - [] - else - argOverrides - program' = withOverrides + (distTempDirectory (distDirLayout baseCtx)) + "environment." + $ \tmpDir -> do + envOverrides <- createPackageEnvironment + verbosity + tmpDir + (elaboratedPlanToExecute buildCtx) + (elaboratedShared buildCtx) + buildStatus + let program' = withOverrides envOverrides argOverrides' program invocation = programInvocation program' args runProgramInvocation verbosity invocation - [] -> die' verbosity "Please specify an executable to run" where verbosity = fromFlagOrDefault normal (configVerbosity configFlags) cliConfig = commandLineFlagsToProjectConfig From 6b9d462a7673d153dd765be1e12686940a8327cb Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 20:56:49 +0200 Subject: [PATCH 23/34] Check if the compiler is supported in the buildCtx ...rather than in the command --- cabal-install/Distribution/Client/CmdExec.hs | 47 +++++++------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index d69432fccaa..04b89e0202e 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -65,8 +65,13 @@ import Distribution.Simple.Program.Types , programOverrideArgs , simpleProgram , programId --- , programVersion ) +import Distribution.Simple.Compiler + ( compilerFlavor + , CompilerFlavor(..) ) +import Distribution.Simple.GHC + ( getImplInfo + , GhcImplInfo(supportsPkgEnvFiles) ) import Distribution.Simple.Setup ( HaddockFlags , fromFlagOrDefault @@ -153,6 +158,10 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) -- point at the file. -- In case ghc is too old to support environment files, -- we pass the same info as arguments + let compiler = pkgConfigCompiler $ elaboratedShared buildCtx + unless (compilerFlavor compiler `elem` [GHC, GHCJS]) $ + die' verbosity "exec only works with GHC and GHCJS" + let envFilesSupported = supportsPkgEnvFiles (getImplInfo compiler) case extraArgs of [] -> die' verbosity "Please specify an executable to run" exe:args -> do @@ -162,37 +171,13 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) (distDirLayout baseCtx) (elaboratedPlanOriginal buildCtx) buildStatus - isCompilerWithGhcFlags = - -- TODO how do I get this? - -- MAYBE just support ghc[js] - programId program `elem` ["ghc", "ghcjs", "lhc"] - envFilesAreSupported = fromMaybe False $ - --TODO replace all this with a generic - --getImplInfo - case programId program - of {-"ghc" -> - supportsPkgEnvFiles <$> - ghcVersionImplInfo <$> - programVersion program - "lhc" -> - supportsPkgEnvFiles <$> - lhcVersionImplInfo <$> - programVersion program - "ghcjs" -> - supportsPkgEnvFiles <$> - ghcjsVersionImplInfo <$> - programVersion program <*> - programVersion program --HACK - -} - _ -> Nothing + programIsCompiler = + programId program `elem` ["ghc", "ghcjs", "ghci"] argOverrides' = - if - not isCompilerWithGhcFlags - || envFilesAreSupported - then - [] - else - argOverrides + if envFilesSupported + || not programIsCompiler + then [] + else argOverrides withTempDirectory verbosity From e0b085ef399fa4f49eb59d850927f7ecf60ceea2 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 21:51:32 +0200 Subject: [PATCH 24/34] Don't use ghc env files if they aren't supported --- cabal-install/Distribution/Client/CmdExec.hs | 41 ++++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 04b89e0202e..dd69a0f06a8 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -179,23 +179,30 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) then [] else argOverrides - withTempDirectory - verbosity - (distTempDirectory (distDirLayout baseCtx)) - "environment." - $ \tmpDir -> do - envOverrides <- createPackageEnvironment - verbosity - tmpDir - (elaboratedPlanToExecute buildCtx) - (elaboratedShared buildCtx) - buildStatus - let program' = withOverrides - envOverrides - argOverrides' - program - invocation = programInvocation program' args - runProgramInvocation verbosity invocation + -- MAYBE move this outside this "do" block + -- or make it a top level function (with 5 args) + withEnvFile action = + withTempDirectory + verbosity + (distTempDirectory (distDirLayout baseCtx)) + "environment." + (\tmpDir -> do + envOverrides <- createPackageEnvironment + verbosity + tmpDir + (elaboratedPlanToExecute buildCtx) + (elaboratedShared buildCtx) + buildStatus + action envOverrides) + (if envFilesSupported + then withEnvFile + else \f -> f []) $ \envOverrides -> do + let program' = withOverrides + envOverrides + argOverrides' + program + invocation = programInvocation program' args + runProgramInvocation verbosity invocation where verbosity = fromFlagOrDefault normal (configVerbosity configFlags) cliConfig = commandLineFlagsToProjectConfig From 9298ad8b0fe11bcc6a4229027c90a0359d47a7d3 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 21:53:00 +0200 Subject: [PATCH 25/34] Exec args are defaults, not overrides --- cabal-install/Distribution/Client/CmdExec.hs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index dd69a0f06a8..25415500773 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -62,7 +62,7 @@ import Distribution.Simple.Program.Run ) import Distribution.Simple.Program.Types ( programOverrideEnv - , programOverrideArgs + , programDefaultArgs , simpleProgram , programId ) @@ -210,8 +210,7 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) installFlags haddockFlags withOverrides env args program = program { programOverrideEnv = programOverrideEnv program ++ env - -- XXX Override or Default? - , programOverrideArgs = programOverrideArgs program ++ args} + , programDefaultArgs = programDefaultArgs program ++ args} pathAdditions :: Verbosity -> ProjectBaseContext -> ProjectBuildContext -> IO [FilePath] From 8e050a65fef40ebdb8a680b58793d59bf24dbcf8 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Wed, 23 Aug 2017 22:00:14 +0200 Subject: [PATCH 26/34] Make withTempEnvFile its own function --- cabal-install/Distribution/Client/CmdExec.hs | 45 +++++++++++++------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 25415500773..4645caa80bd 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -40,6 +40,7 @@ import Distribution.Client.ProjectPlanOutput ( updatePostBuildProjectStatus , createPackageEnvironment , argsEquivalentOfGhcEnvironmentFile + , PostBuildProjectStatus ) import qualified Distribution.Client.ProjectPlanning as Planning import Distribution.Client.ProjectPlanning @@ -179,23 +180,8 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) then [] else argOverrides - -- MAYBE move this outside this "do" block - -- or make it a top level function (with 5 args) - withEnvFile action = - withTempDirectory - verbosity - (distTempDirectory (distDirLayout baseCtx)) - "environment." - (\tmpDir -> do - envOverrides <- createPackageEnvironment - verbosity - tmpDir - (elaboratedPlanToExecute buildCtx) - (elaboratedShared buildCtx) - buildStatus - action envOverrides) (if envFilesSupported - then withEnvFile + then withTempEnvFile verbosity baseCtx buildCtx buildStatus else \f -> f []) $ \envOverrides -> do let program' = withOverrides envOverrides @@ -213,6 +199,33 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) , programDefaultArgs = programDefaultArgs program ++ args} +-- | Execute an action with a temporary .ghc.environment file reflecting the +-- current environment. The action takes an environment containing the env +-- variable which points ghc to the file. +withTempEnvFile :: Verbosity + -> ProjectBaseContext + -> ProjectBuildContext + -> PostBuildProjectStatus + -> ([(String, Maybe String)] -> IO a) + -> IO a +withTempEnvFile verbosity + baseCtx + buildCtx + buildStatus + action = + withTempDirectory + verbosity + (distTempDirectory (distDirLayout baseCtx)) + "environment." + (\tmpDir -> do + envOverrides <- createPackageEnvironment + verbosity + tmpDir + (elaboratedPlanToExecute buildCtx) + (elaboratedShared buildCtx) + buildStatus + action envOverrides) + pathAdditions :: Verbosity -> ProjectBaseContext -> ProjectBuildContext -> IO [FilePath] pathAdditions verbosity ProjectBaseContext{..}ProjectBuildContext{..} = do info verbosity . unlines $ "Including the following directories in PATH:" From 5fd32dcb1af59329aef6b7624bf78cf07ce12221 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Thu, 24 Aug 2017 18:39:12 +0200 Subject: [PATCH 27/34] Add test: new-exec can run an exe --- .../PackageTests/NewBuild/CmdExec/RunExe/Main.hs | 1 + .../PackageTests/NewBuild/CmdExec/RunExe/RunExe.cabal | 9 +++++++++ .../PackageTests/NewBuild/CmdExec/RunExe/cabal.out | 9 +++++++++ .../PackageTests/NewBuild/CmdExec/RunExe/cabal.project | 1 + .../PackageTests/NewBuild/CmdExec/RunExe/cabal.test.hs | 5 +++++ 5 files changed, 25 insertions(+) create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/Main.hs create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/RunExe.cabal create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.out create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.project create mode 100644 cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.test.hs diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/Main.hs b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/Main.hs new file mode 100644 index 00000000000..73566f6f203 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/Main.hs @@ -0,0 +1 @@ +main = putStrLn "Hello World" diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/RunExe.cabal b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/RunExe.cabal new file mode 100644 index 00000000000..e392dcdae11 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/RunExe.cabal @@ -0,0 +1,9 @@ +name: RunExe +version: 1.0 +build-type: Simple +cabal-version: >= 1.10 + +executable foo + main-is: Main.hs + build-depends: base + default-language: Haskell2010 diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.out b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.out new file mode 100644 index 00000000000..f5d3127ddc4 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.out @@ -0,0 +1,9 @@ +# cabal new-build +Resolving dependencies... +Build profile: -w ghc- -O1 +In order, the following will be built: + - RunExe-1.0 (exe:foo) (first run) +Configuring executable 'foo' for RunExe-1.0.. +Preprocessing executable 'foo' for RunExe-1.0.. +Building executable 'foo' for RunExe-1.0.. +# cabal new-exec diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.project b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.project new file mode 100644 index 00000000000..e6fdbadb439 --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.project @@ -0,0 +1 @@ +packages: . diff --git a/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.test.hs b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.test.hs new file mode 100644 index 00000000000..17149902bca --- /dev/null +++ b/cabal-testsuite/PackageTests/NewBuild/CmdExec/RunExe/cabal.test.hs @@ -0,0 +1,5 @@ +import Test.Cabal.Prelude +main = cabalTest $ do + cabal "new-build" [] + cabal' "new-exec" ["foo"] >>= assertOutputContains "Hello World" + From d0ba72d8d2ed64e2345eb4276f8326d3672ac737 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Thu, 24 Aug 2017 18:53:27 +0200 Subject: [PATCH 28/34] Remove useless comment --- cabal-install/Distribution/Client/CmdExec.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 4645caa80bd..37e0a705ada 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -87,7 +87,6 @@ import Distribution.Verbosity ( Verbosity , normal ) ---import Distribution.Simple.GHC (supportsPkgEnvFiles) import Prelude () import Distribution.Client.Compat.Prelude From 630634abe7267f711458c91323bcf5520a54d3a2 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 29 Aug 2017 20:21:14 +0200 Subject: [PATCH 29/34] Match the configured compiler in new-exec Alter the compiler flags only if the exe path matches the configured compiler's one. Ex. `cabal -w ghc-8.0 new-exec ghc-8.0 Main.hs` The flags depend on the compiler flavor. Only GHC and GHCJS are supported right now. --- cabal-install/Distribution/Client/CmdExec.hs | 26 ++++++++++++------- .../Distribution/Client/ProjectPlanOutput.hs | 21 ++++++++++++--- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index 37e0a705ada..d81c65e1e74 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -53,6 +53,7 @@ import Distribution.Simple.Command import Distribution.Simple.Program.Db ( modifyProgramSearchPath , requireProgram + , configuredPrograms ) import Distribution.Simple.Program.Find ( ProgramSearchPathEntry(..) @@ -64,12 +65,10 @@ import Distribution.Simple.Program.Run import Distribution.Simple.Program.Types ( programOverrideEnv , programDefaultArgs + , programPath , simpleProgram - , programId + , ConfiguredProgram ) -import Distribution.Simple.Compiler - ( compilerFlavor - , CompilerFlavor(..) ) import Distribution.Simple.GHC ( getImplInfo , GhcImplInfo(supportsPkgEnvFiles) ) @@ -159,23 +158,23 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) -- In case ghc is too old to support environment files, -- we pass the same info as arguments let compiler = pkgConfigCompiler $ elaboratedShared buildCtx - unless (compilerFlavor compiler `elem` [GHC, GHCJS]) $ - die' verbosity "exec only works with GHC and GHCJS" - let envFilesSupported = supportsPkgEnvFiles (getImplInfo compiler) + envFilesSupported = supportsPkgEnvFiles (getImplInfo compiler) case extraArgs of [] -> die' verbosity "Please specify an executable to run" exe:args -> do (program, _) <- requireProgram verbosity (simpleProgram exe) programDb let argOverrides = argsEquivalentOfGhcEnvironmentFile + compiler (distDirLayout baseCtx) (elaboratedPlanOriginal buildCtx) buildStatus - programIsCompiler = - programId program `elem` ["ghc", "ghcjs", "ghci"] + programIsConfiguredCompiler = matchCompilerPath + (elaboratedShared buildCtx) + program argOverrides' = if envFilesSupported - || not programIsCompiler + || not programIsConfiguredCompiler then [] else argOverrides @@ -197,6 +196,13 @@ execAction (configFlags, configExFlags, installFlags, haddockFlags) { programOverrideEnv = programOverrideEnv program ++ env , programDefaultArgs = programDefaultArgs program ++ args} +matchCompilerPath :: ElaboratedSharedConfig -> ConfiguredProgram -> Bool +matchCompilerPath elaboratedShared program = + programPath program + `elem` + (programPath <$> configuredCompilers) + where + configuredCompilers = configuredPrograms $ pkgConfigCompilerProgs elaboratedShared -- | Execute an action with a temporary .ghc.environment file reflecting the -- current environment. The action takes an environment containing the env diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 3e03b24ac1e..0419feeccac 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -31,10 +31,11 @@ import Distribution.Package import Distribution.System import Distribution.InstalledPackageInfo (InstalledPackageInfo) import qualified Distribution.PackageDescription as PD -import Distribution.Compiler (CompilerFlavor(GHC)) +import Distribution.Compiler (CompilerFlavor(GHC, GHCJS)) import Distribution.Simple.Compiler ( PackageDBStack, PackageDB(..) - , compilerVersion, compilerFlavor, showCompilerId ) + , compilerVersion, compilerFlavor, showCompilerId + , compilerId, CompilerId(..), Compiler ) import Distribution.Simple.GHC ( getImplInfo, GhcImplInfo(supportsPkgEnvFiles) , GhcEnvironmentFileEntry(..), simpleGhcEnvironmentFile @@ -747,13 +748,25 @@ renderGhcEnvironmentFile projectRootDir elaboratedInstallPlan selectGhcEnvironmentFilePackageDbs elaboratedInstallPlan --- remove this when we drop support for non-.ghc.env ghc argsEquivalentOfGhcEnvironmentFile + :: Compiler + -> DistDirLayout + -> ElaboratedInstallPlan + -> PostBuildProjectStatus + -> [String] +argsEquivalentOfGhcEnvironmentFile compiler = + case compilerId compiler + of CompilerId GHC _ -> argsEquivalentOfGhcEnvironmentFileGhc + CompilerId GHCJS _ -> argsEquivalentOfGhcEnvironmentFileGhc + CompilerId _ _ -> error "Only GHC and GHCJS are supported" + +-- remove this when we drop support for non-.ghc.env ghc +argsEquivalentOfGhcEnvironmentFileGhc :: DistDirLayout -> ElaboratedInstallPlan -> PostBuildProjectStatus -> [String] -argsEquivalentOfGhcEnvironmentFile +argsEquivalentOfGhcEnvironmentFileGhc distDirLayout elaboratedInstallPlan postBuildStatus = From f99f1698e8ca0680c79dc170900345767aa060da Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 26 Sep 2017 22:38:08 +0200 Subject: [PATCH 30/34] Use void instead of _ <- --- .../Distribution/Client/ProjectOrchestration.hs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs index 25e4c813644..0004cd8a3f4 100644 --- a/cabal-install/Distribution/Client/ProjectOrchestration.hs +++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs @@ -140,6 +140,7 @@ import Data.Map (Map) import Data.List import Data.Maybe import Data.Either +import Control.Monad (void) import Control.Exception (Exception(..), throwIO, assert) import System.Exit (ExitCode(..), exitFailure) #ifdef MIN_VERSION_unix @@ -349,11 +350,11 @@ runProjectPostBuildPhase verbosity pkgsBuildStatus buildOutcomes - _ <- writePlanGhcEnvironment (distProjectRootDirectory - distDirLayout) - elaboratedPlanOriginal - elaboratedShared - postBuildStatus + void $ writePlanGhcEnvironment (distProjectRootDirectory + distDirLayout) + elaboratedPlanOriginal + elaboratedShared + postBuildStatus -- Finally if there were any build failures then report them and throw -- an exception to terminate the program From ca31578e11907b57e22904352d9df25856a61146 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 26 Sep 2017 22:43:28 +0200 Subject: [PATCH 31/34] Fix comment --- cabal-install/Distribution/Client/ProjectPlanOutput.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cabal-install/Distribution/Client/ProjectPlanOutput.hs b/cabal-install/Distribution/Client/ProjectPlanOutput.hs index 0419feeccac..1dcf5fa2479 100644 --- a/cabal-install/Distribution/Client/ProjectPlanOutput.hs +++ b/cabal-install/Distribution/Client/ProjectPlanOutput.hs @@ -760,7 +760,7 @@ argsEquivalentOfGhcEnvironmentFile compiler = CompilerId GHCJS _ -> argsEquivalentOfGhcEnvironmentFileGhc CompilerId _ _ -> error "Only GHC and GHCJS are supported" --- remove this when we drop support for non-.ghc.env ghc +-- TODO remove this when we drop support for non-.ghc.env ghc argsEquivalentOfGhcEnvironmentFileGhc :: DistDirLayout -> ElaboratedInstallPlan From 8945ebdfd1c6b2151ed7f9d5c2939202c1dfdae5 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 26 Sep 2017 23:01:18 +0200 Subject: [PATCH 32/34] Don't base execCommand on installCommand --- cabal-install/Distribution/Client/CmdExec.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cabal-install/Distribution/Client/CmdExec.hs b/cabal-install/Distribution/Client/CmdExec.hs index d81c65e1e74..c421dc8b9f0 100644 --- a/cabal-install/Distribution/Client/CmdExec.hs +++ b/cabal-install/Distribution/Client/CmdExec.hs @@ -26,7 +26,6 @@ import Distribution.Client.Setup , ConfigFlags(configVerbosity) , GlobalFlags , InstallFlags - , installCommand ) import Distribution.Client.ProjectOrchestration ( ProjectBuildContext(..) @@ -87,6 +86,8 @@ import Distribution.Verbosity , normal ) +import qualified Distribution.Client.CmdBuild as CmdBuild + import Prelude () import Distribution.Client.Compat.Prelude @@ -95,7 +96,7 @@ import qualified Data.Set as S import qualified Data.Map as M execCommand :: CommandUI (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) -execCommand = installCommand +execCommand = CommandUI { commandName = "new-exec" , commandSynopsis = "Give a command access to the store." , commandUsage = \pname -> @@ -115,6 +116,8 @@ execCommand = installCommand ++ " to choose an appropriate version of ghc and to include any" ++ " ghc-specific flags requested." , commandNotes = Nothing + , commandOptions = commandOptions CmdBuild.buildCommand + , commandDefaultFlags = commandDefaultFlags CmdBuild.buildCommand } execAction :: (ConfigFlags, ConfigExFlags, InstallFlags, HaddockFlags) From cb9a35514756e51a8ac6d5192992bafc74b58a5e Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 26 Sep 2017 23:11:49 +0200 Subject: [PATCH 33/34] Add new-exec to changelog [ci skip] --- cabal-install/changelog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cabal-install/changelog b/cabal-install/changelog index 11f39702b2c..b611de20326 100644 --- a/cabal-install/changelog +++ b/cabal-install/changelog @@ -10,7 +10,8 @@ * Completed the 'new-run' command (#4477). The functionality is the same of the old 'run' command but using nix-style builds. Additionally, it can run executables across packages in a project. - * Completed the 'new-bench' command. Same as above. + * Completed the 'new-bench' command (#3638). Same as above. + * Completed the 'new-exec' command (#3638). Same as above. * '--allow-{newer,older}' syntax has been enhanced. Dependency relaxation can be now limited to a specific release of a package, plus there's a now syntax for relaxing only caret-style (i.e. '^>=') From 442bb9133b63b1a8dcaacc0e339e9a4f26e9fc99 Mon Sep 17 00:00:00 2001 From: Francesco Gazzetta Date: Tue, 26 Sep 2017 23:27:00 +0200 Subject: [PATCH 34/34] Add new-exec to the docs [ci skip] --- Cabal/doc/nix-local-build.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Cabal/doc/nix-local-build.rst b/Cabal/doc/nix-local-build.rst index d3ca17823b3..f89856bf6d5 100644 --- a/Cabal/doc/nix-local-build.rst +++ b/Cabal/doc/nix-local-build.rst @@ -402,10 +402,12 @@ cabal new-bench (all the benchmarks in the current package by default), first ensuring they are up to date. -Unsupported commands --------------------- +cabal new-exec +--------------- -The following commands are not currently supported: +``cabal new-exec [FLAGS] [--] COMMAND [--] [ARGS]`` runs the specified command +using the project's environment. That is, passing the right flags to compiler +invocations and bringing the project's executables into scope. ``cabal new-test`` (:issue:`3638`) Workaround: run the test executable directly (see `Where are my @@ -415,10 +417,7 @@ The following commands are not currently supported: Workaround: run the benchmark executable directly (see `Where are my build products <#where-are-my-build-products>`__?) -``cabal new-exec`` - Workaround: if you wanted to execute GHCi, consider using - ``cabal new-repl`` instead. Otherwise, use ``-v`` to find the list - of flags GHC is being invoked with and pass it manually. +The following commands are not currently supported: ``cabal new-haddock`` (:issue:`3535`) Workaround: run