diff --git a/Cabal/Cabal.cabal b/Cabal/Cabal.cabal index 735f946b4f6..e9b58ca181e 100644 --- a/Cabal/Cabal.cabal +++ b/Cabal/Cabal.cabal @@ -80,6 +80,7 @@ extra-source-files: tests/PackageTests/BuildDeps/TargetSpecificDeps3/MyLibrary.hs tests/PackageTests/BuildDeps/TargetSpecificDeps3/lemon.hs tests/PackageTests/BuildDeps/TargetSpecificDeps3/my.cabal + tests/PackageTests/BuildOneShot/BuildOneShot.cabal tests/PackageTests/BuildTestSuiteDetailedV09/Dummy2.hs tests/PackageTests/BuildableField/BuildableField.cabal tests/PackageTests/BuildableField/Main.hs diff --git a/Cabal/Distribution/Simple/Build.hs b/Cabal/Distribution/Simple/Build.hs index 51086d5c148..523024cbd48 100644 --- a/Cabal/Distribution/Simple/Build.hs +++ b/Cabal/Distribution/Simple/Build.hs @@ -75,10 +75,36 @@ build :: PackageDescription -- ^ Mostly information from the .cabal file -> BuildFlags -- ^ Flags that the user passed to build -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling -> IO () -build pkg_descr lbi flags suffixes = do - let distPref = fromFlag (buildDistPref flags) - verbosity = fromFlag (buildVerbosity flags) - +build pkg_descr lbi flags suffixes + | fromFlag (buildOneShot flags) = do + -- TODO: if checkBuildTargets ignores a target we may accept + -- a --one-shot with multiple arguments. Arguably, we should + -- error early in this case. + targets <- readBuildTargets pkg_descr (buildArgs flags) + (cname, _) <- checkBuildTargets verbosity pkg_descr targets >>= \r -> case r of + [] -> die "In --one-shot mode you must specify a target" + [target'] -> return target' + _ -> die "In --one-shot mode you can only build a single target" + -- NB: do NOT 'createInternalPackageDB'; we don't want to delete it. + -- But this means we have to be careful about unregistering + -- ourselves. + let dbPath = internalPackageDBPath lbi distPref + internalPackageDB = SpecificPackageDB dbPath + clbi = getComponentLocalBuildInfo lbi cname + comp = getComponent pkg_descr cname + -- TODO: do we need to unregister libraries? In any case, this would + -- need to be done in the buildLib functionality. + -- Do the build + initialBuildSteps distPref pkg_descr lbi clbi verbosity + let bi = componentBuildInfo comp + progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi) + lbi' = lbi { + withPrograms = progs', + withPackageDB = withPackageDB lbi ++ [internalPackageDB] + } + buildComponent verbosity (buildNumJobs flags) pkg_descr + lbi' suffixes comp clbi distPref + | otherwise = do targets <- readBuildTargets pkg_descr (buildArgs flags) targets' <- checkBuildTargets verbosity pkg_descr targets let componentsToBuild = componentsInBuildOrder lbi (map fst targets') @@ -102,6 +128,9 @@ build pkg_descr lbi flags suffixes = do } buildComponent verbosity (buildNumJobs flags) pkg_descr lbi' suffixes comp clbi distPref + where + distPref = fromFlag (buildDistPref flags) + verbosity = fromFlag (buildVerbosity flags) repl :: PackageDescription -- ^ Mostly information from the .cabal file @@ -188,7 +217,7 @@ buildComponent verbosity numJobs pkg_descr lbi suffixes installedPkgInfo = inplaceInstalledPackageInfo pwd distPref pkg_descr (AbiHash "") lib' lbi clbi - registerPackage verbosity (compiler lbi) (withPrograms lbi) HcPkg.MultiInstance + registerPackage verbosity (compiler lbi) (withPrograms lbi) HcPkg.NoMultiInstance (withPackageDB lbi) installedPkgInfo buildComponent verbosity numJobs pkg_descr lbi suffixes diff --git a/Cabal/Distribution/Simple/Setup.hs b/Cabal/Distribution/Simple/Setup.hs index e27df954be8..de84765eba9 100644 --- a/Cabal/Distribution/Simple/Setup.hs +++ b/Cabal/Distribution/Simple/Setup.hs @@ -1444,6 +1444,9 @@ data BuildFlags = BuildFlags { buildDistPref :: Flag FilePath, buildVerbosity :: Flag Verbosity, buildNumJobs :: Flag (Maybe Int), + -- | If this is true, we don't build the dependencies of + -- 'buildArgs': only the directly referenced components. + buildOneShot :: Flag Bool, -- TODO: this one should not be here, it's just that the silly -- UserHooks stop us from passing extra info in other ways buildArgs :: [String] @@ -1461,6 +1464,7 @@ defaultBuildFlags = BuildFlags { buildDistPref = mempty, buildVerbosity = Flag normal, buildNumJobs = mempty, + buildOneShot = Flag False, buildArgs = [] } @@ -1508,6 +1512,11 @@ buildOptions :: ProgramConfiguration -> ShowOrParseArgs buildOptions progConf showOrParseArgs = [ optionNumJobs buildNumJobs (\v flags -> flags { buildNumJobs = v }) + + , option "" ["one-shot"] + "One-shot build" + buildOneShot (\c flags -> flags { buildOneShot = c }) + trueArg ] ++ programConfigurationPaths progConf showOrParseArgs diff --git a/Cabal/tests/PackageTests/BuildOneShot/.gitignore b/Cabal/tests/PackageTests/BuildOneShot/.gitignore new file mode 100644 index 00000000000..25d2ea63cd4 --- /dev/null +++ b/Cabal/tests/PackageTests/BuildOneShot/.gitignore @@ -0,0 +1 @@ +*.hs diff --git a/Cabal/tests/PackageTests/BuildOneShot/BuildOneShot.cabal b/Cabal/tests/PackageTests/BuildOneShot/BuildOneShot.cabal new file mode 100644 index 00000000000..828e1f2cd98 --- /dev/null +++ b/Cabal/tests/PackageTests/BuildOneShot/BuildOneShot.cabal @@ -0,0 +1,21 @@ +-- Initial BuildOneShot.cabal generated by cabal init. For further +-- documentation, see http://haskell.org/cabal/users-guide/ + +name: BuildOneShot +version: 0.1.0.0 +license: BSD3 +author: Edward Z. Yang +maintainer: ezyang@cs.stanford.edu +build-type: Simple +cabal-version: >=1.10 + +library + exposed-modules: A + build-depends: base + default-language: Haskell2010 + +executable one-shot + main-is: Main.hs + hs-source-dirs: one-shot + build-depends: BuildOneShot, base + default-language: Haskell2010 diff --git a/Cabal/tests/PackageTests/BuildOneShot/one-shot/.gitignore b/Cabal/tests/PackageTests/BuildOneShot/one-shot/.gitignore new file mode 100644 index 00000000000..25d2ea63cd4 --- /dev/null +++ b/Cabal/tests/PackageTests/BuildOneShot/one-shot/.gitignore @@ -0,0 +1 @@ +*.hs diff --git a/Cabal/tests/PackageTests/Tests.hs b/Cabal/tests/PackageTests/Tests.hs index 331fa0bf57e..742acaf8b0f 100644 --- a/Cabal/tests/PackageTests/Tests.hs +++ b/Cabal/tests/PackageTests/Tests.hs @@ -408,6 +408,21 @@ tests config = do cabal "build" [] runExe' "T3294" [] >>= assertOutputContains "bbb" + -- Test build --one-shot + tc "BuildOneShot" $ do + pkg_dir <- packageDir + liftIO $ writeFile (pkg_dir "A.hs") "module A where\na = \"a1\"" + liftIO $ writeFile (pkg_dir "one-shot/Main.hs") "import A\nmain = print (a ++ \" b1\")" + cabal_build [] + runExe' "one-shot" [] + >>= assertOutputContains "a1 b1" + ghcFileModDelay + liftIO $ writeFile (pkg_dir "A.hs") "module A where\na = \"a2\"" + liftIO $ writeFile (pkg_dir "one-shot/Main.hs") "import A\nmain = print (a ++ \" b2\")" + cabal "build" ["--one-shot", "one-shot"] + runExe' "one-shot" [] + >>= assertOutputContains "a1 b2" + where ghc_pkg_guess bin_name = do cwd <- packageDir diff --git a/cabal-install/Distribution/Client/ProjectPlanning.hs b/cabal-install/Distribution/Client/ProjectPlanning.hs index bf34f5e8cc7..52f02d9f262 100644 --- a/cabal-install/Distribution/Client/ProjectPlanning.hs +++ b/cabal-install/Distribution/Client/ProjectPlanning.hs @@ -2071,6 +2071,7 @@ setupHsBuildFlags ElaboratedConfiguredPackage{..} _ verbosity builddir = buildProgramArgs = mempty, --unused, set at configure time buildVerbosity = toFlag verbosity, buildDistPref = toFlag builddir, + buildOneShot = toFlag False, buildNumJobs = mempty, --TODO: [nice to have] sometimes want to use toFlag (Just numBuildJobs), buildArgs = mempty -- unused, passed via args not flags }