Commit 1f05d301 authored by Simon Marlow's avatar Simon Marlow
Browse files

Refuse to run any commands if the .cabal has been modified

See GHC bug #1372
This is a consistency check, intended to prevent this class of build
failures:

   * Package P is updated, its version number is bumped, the
     new version is compiled and installed.

   * Package Q depends on P.  Q is modified to use the new P, and Q's
     .cabal file is updated with changes to the build-depends field to
     depend on the new version of P.

   * The user has an old build of Q.  They pull the changes to Q and
     'setup build' without cleaning or re-configuring.  Build errors
     ensue, because the code of Q depends on changes to P's API, and
     we're still building against the old P.

Note that you can't get segfaults this way, only build errors.

This also relies on some new consistency checking in GHC 6.8 to work
properly.  If the user re-configures their Q build and then issues
'setup build' without cleaning, GHC must now realise that the package
flags have changed, and re-compile all the affected Q modules.  GHC
6.6 would not do this, but 6.8 does.
parent aea8fd57
......@@ -84,7 +84,9 @@ import Distribution.Simple.Register ( register, unregister,
removeRegScripts
)
import Distribution.Simple.Configure(getPersistBuildConfig, maybeGetPersistBuildConfig,
import Distribution.Simple.Configure(getPersistBuildConfig,
maybeGetPersistBuildConfig,
checkPersistBuildConfig,
configure, writePersistBuildConfig)
import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo(..), distPref, srcPref)
......@@ -305,7 +307,7 @@ defaultMainWorker mdescr action all_args hooks prog_conf
parseConfigureArgs prog_conf flags all_args [scratchDirOpt]
pbi <- preConf hooks args flags'
pkg_descr0 <- maybe (confPkgDescr flags') (return . Right) mdescr
(mb_pd_file, pkg_descr0) <- confPkgDescr flags'
-- get_pkg_descr (configVerbose flags')
--let pkg_descr = updatePackageDescription pbi pkg_descr0
......@@ -314,26 +316,33 @@ defaultMainWorker mdescr action all_args hooks prog_conf
--(warns, ers) <- sanityCheckPackage pkg_descr
--errorOut (configVerbose flags') warns ers
localbuildinfo <- confHook hooks epkg_descr flags'
localbuildinfo0 <- confHook hooks epkg_descr flags'
-- remember the .cabal filename if we know it
let localbuildinfo = localbuildinfo0{ pkgDescrFile = mb_pd_file }
writePersistBuildConfig (foldr id localbuildinfo optFns)
let pkg_descr = localPkgDescr localbuildinfo
postConf hooks args flags' pkg_descr localbuildinfo
where
confPkgDescr :: ConfigFlags -> IO (Either GenericPackageDescription
PackageDescription)
confPkgDescr cfgflags = do
mdescr' <- readDesc hooks
case mdescr' of
Just descr -> return $ Right descr
Nothing -> do
pdfile <- defaultPackageDesc (configVerbose cfgflags)
ppd <- readPackageDescription (configVerbose cfgflags) pdfile
return (Left ppd)
confPkgDescr :: ConfigFlags
-> IO (Maybe FilePath,
Either GenericPackageDescription
PackageDescription)
confPkgDescr cfgflags =
case mdescr of
Just ppd -> return (Nothing, Right ppd)
Nothing -> do
mdescr' <- readDesc hooks
case mdescr' of
Just descr -> return (Nothing, Right descr)
Nothing -> do
pdfile <- defaultPackageDesc (configVerbose cfgflags)
ppd <- readPackageDescription (configVerbose cfgflags) pdfile
return (Just pdfile, Left ppd)
BuildCmd -> do
lbi <- getPersistBuildConfig
lbi <- getBuildConfigIfUpToDate
res@(flags, _, _) <-
parseBuildArgs prog_conf
(emptyBuildFlags (withPrograms lbi)) all_args []
......@@ -344,22 +353,22 @@ defaultMainWorker mdescr action all_args hooks prog_conf
MakefileCmd ->
command (parseMakefileArgs emptyMakefileFlags) makefileVerbose
preMakefile makefileHook postMakefile
getPersistBuildConfig
getBuildConfigIfUpToDate
HscolourCmd ->
command (parseHscolourArgs emptyHscolourFlags) hscolourVerbose
preHscolour hscolourHook postHscolour
getPersistBuildConfig
getBuildConfigIfUpToDate
HaddockCmd ->
command (parseHaddockArgs emptyHaddockFlags) haddockVerbose
preHaddock haddockHook postHaddock
getPersistBuildConfig
getBuildConfigIfUpToDate
ProgramaticaCmd -> do
command parseProgramaticaArgs pfeVerbose
prePFE pfeHook postPFE
getPersistBuildConfig
getBuildConfigIfUpToDate
CleanCmd -> do
(flags, _, args) <- parseCleanArgs emptyCleanFlags all_args []
......@@ -378,12 +387,12 @@ defaultMainWorker mdescr action all_args hooks prog_conf
CopyCmd mprefix -> do
command (parseCopyArgs (emptyCopyFlags mprefix)) copyVerbose
preCopy copyHook postCopy
getPersistBuildConfig
getBuildConfigIfUpToDate
InstallCmd -> do
command (parseInstallArgs emptyInstallFlags) installVerbose
preInst instHook postInst
getPersistBuildConfig
getBuildConfigIfUpToDate
SDistCmd -> do
(flags, _, args) <- parseSDistArgs all_args []
......@@ -401,19 +410,19 @@ defaultMainWorker mdescr action all_args hooks prog_conf
TestCmd -> do
(_verbosity,_, args) <- parseTestArgs all_args []
localbuildinfo <- getPersistBuildConfig
localbuildinfo <- getBuildConfigIfUpToDate
let pkg_descr = localPkgDescr localbuildinfo
runTests hooks args False pkg_descr localbuildinfo
RegisterCmd -> do
command (parseRegisterArgs emptyRegisterFlags) regVerbose
preReg regHook postReg
getPersistBuildConfig
getBuildConfigIfUpToDate
UnregisterCmd -> do
command (parseUnregisterArgs emptyRegisterFlags) regVerbose
preUnreg unregHook postUnreg
getPersistBuildConfig
getBuildConfigIfUpToDate
HelpCmd -> return () -- this is handled elsewhere
where
......@@ -438,6 +447,14 @@ getModulePaths lbi bi =
fmap concat .
mapM (flip (moduleToFilePath (buildDir lbi : hsSourceDirs bi)) ["hs", "lhs"])
getBuildConfigIfUpToDate :: IO LocalBuildInfo
getBuildConfigIfUpToDate = do
lbi <- getPersistBuildConfig
case pkgDescrFile lbi of
Nothing -> return ()
Just pkg_descr_file -> checkPersistBuildConfig pkg_descr_file
return lbi
-- --------------------------------------------------------------------------
-- Programmatica support
......
......@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -}
module Distribution.Simple.Configure (configure,
writePersistBuildConfig,
getPersistBuildConfig,
checkPersistBuildConfig,
maybeGetPersistBuildConfig,
-- getConfiguredPkgDescr,
localBuildInfoFile,
......@@ -119,7 +120,7 @@ import Data.List
import Data.Maybe
( fromMaybe, isNothing )
import System.Directory
( doesFileExist )
( doesFileExist, getModificationTime )
import System.Environment
( getProgName )
import System.Exit
......@@ -154,7 +155,9 @@ tryGetConfigStateFile filename = do
tryGetPersistBuildConfig :: IO (Either String LocalBuildInfo)
tryGetPersistBuildConfig = tryGetConfigStateFile localBuildInfoFile
-- |Read the 'localBuildInfoFile'. Error if it doesn't exist.
-- |Read the 'localBuildInfoFile'. Error if it doesn't exist. Also
-- fail if the file containing LocalBuildInfo is older than the .cabal
-- file, indicating that a re-configure is required.
getPersistBuildConfig :: IO LocalBuildInfo
getPersistBuildConfig = do
lbi <- tryGetPersistBuildConfig
......@@ -173,11 +176,19 @@ writePersistBuildConfig lbi = do
createDirectoryIfMissing False distPref
writeFile localBuildInfoFile (show lbi)
-- |Check that localBuildInfoFile is up-to-date with respect to the
-- .cabal file.
checkPersistBuildConfig :: FilePath -> IO ()
checkPersistBuildConfig pkg_descr_file = do
t0 <- getModificationTime pkg_descr_file
t1 <- getModificationTime localBuildInfoFile
when (t0 > t1) $
die (pkg_descr_file ++ " has been changed, please re-configure.")
-- |@dist\/setup-config@
localBuildInfoFile :: FilePath
localBuildInfoFile = distPref </> "setup-config"
-- -----------------------------------------------------------------------------
-- * Configuration
-- -----------------------------------------------------------------------------
......@@ -289,6 +300,7 @@ configure (pkg_descr0, pbi) cfg
buildDir = distPref </> "build",
scratchDir = distPref </> "scratch",
packageDeps = dep_pkgs,
pkgDescrFile = Nothing,
localPkgDescr = pkg_descr',
withPrograms = programsConfig'',
withVanillaLib = configVanillaLib cfg,
......
......@@ -87,6 +87,8 @@ data LocalBuildInfo = LocalBuildInfo {
-- that must be satisfied in terms of version ranges. This
-- field fixes those dependencies to the specific versions
-- available on this machine for this compiler.
pkgDescrFile :: Maybe FilePath,
-- ^ the filename containing the .cabal file, if available
localPkgDescr :: PackageDescription,
-- ^ The resolved package description, that does not contain
-- any conditionals.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment