Skip to content

More nix-local-build merging: solver and setup wrapper features #3094

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 1, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cabal-install/Distribution/Client/Configure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ configureSetupScript packageDBs
mpkg
= SetupScriptOptions {
useCabalVersion = cabalVersion
, useCabalSpecVersion = Nothing
, useCompiler = Just comp
, usePlatform = Just platform
, usePackageDB = packageDBs'
Expand All @@ -201,6 +202,7 @@ configureSetupScript packageDBs
-- Therefore, for now, we just leave this blank.
, useDependencies = fromMaybe [] explicitSetupDeps
, useDependenciesExclusive = isJust explicitSetupDeps
, useVersionMacros = isJust explicitSetupDeps
}
where
-- When we are compiling a legacy setup script without an explicit
Expand Down
45 changes: 40 additions & 5 deletions cabal-install/Distribution/Client/Dependency.hs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ module Distribution.Client.Dependency (
hideInstalledPackagesSpecificByUnitId,
hideInstalledPackagesSpecificBySourcePackageId,
hideInstalledPackagesAllVersions,
removeUpperBounds
removeUpperBounds,
addDefaultSetupDependencies,
) where

import Distribution.Client.Dependency.TopDown
Expand Down Expand Up @@ -356,13 +357,14 @@ hideBrokenInstalledPackages params =

-- | Remove upper bounds in dependencies using the policy specified by the
-- 'AllowNewer' argument (all/some/none).
--
-- Note: It's important to apply 'removeUpperBounds' after
-- 'addSourcePackages'. Otherwise, the packages inserted by
-- 'addSourcePackages' won't have upper bounds in dependencies relaxed.
--
removeUpperBounds :: AllowNewer -> DepResolverParams -> DepResolverParams
removeUpperBounds allowNewer params =
params {
-- NB: It's important to apply 'removeUpperBounds' after
-- 'addSourcePackages'. Otherwise, the packages inserted by
-- 'addSourcePackages' won't have upper bounds in dependencies relaxed.

depResolverSourcePkgIndex = sourcePkgIndex'
}
where
Expand Down Expand Up @@ -437,6 +439,39 @@ removeUpperBounds allowNewer params =
onCondTree g = mapCondTree g (map f) id


-- | Supply defaults for packages without explicit Setup dependencies
--
-- Note: It's important to apply 'addDefaultSetupDepends' after
-- 'addSourcePackages'. Otherwise, the packages inserted by
-- 'addSourcePackages' won't have upper bounds in dependencies relaxed.
--
addDefaultSetupDependencies :: (SourcePackage -> [Dependency])
-> DepResolverParams -> DepResolverParams
addDefaultSetupDependencies defaultSetupDeps params =
params {
depResolverSourcePkgIndex =
fmap applyDefaultSetupDeps (depResolverSourcePkgIndex params)
}
where
applyDefaultSetupDeps :: SourcePackage -> SourcePackage
applyDefaultSetupDeps srcpkg =
srcpkg {
packageDescription = gpkgdesc {
PD.packageDescription = pkgdesc {
PD.setupBuildInfo =
case PD.setupBuildInfo pkgdesc of
Just sbi -> Just sbi
Nothing -> Just PD.SetupBuildInfo {
PD.setupDepends = defaultSetupDeps srcpkg
}
}
}
}
where
gpkgdesc = packageDescription srcpkg
pkgdesc = PD.packageDescription gpkgdesc


upgradeDependencies :: DepResolverParams -> DepResolverParams
upgradeDependencies = setPreferenceDefault PreferAllLatest

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,9 +324,12 @@ deferWeakFlagChoices = trav go
go (GoalChoiceF xs) = GoalChoiceF (P.sortBy defer xs)
go x = x

-- weak flags go very last, weak stanzas second last
defer :: Tree a -> Tree a -> Ordering
defer (FChoice _ _ True _ _) _ = GT
defer _ (FChoice _ _ True _ _) = LT
defer (SChoice _ _ True _) _ = GT
defer _ (SChoice _ _ True _) = LT
defer _ _ = EQ

-- Transformation that sorts choice nodes so that
Expand Down
6 changes: 2 additions & 4 deletions cabal-install/Distribution/Client/Freeze.hs
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,8 @@ planPackages verbosity comp platform mSandboxPkgInfo freezeFlags

logMsg message rest = debug verbosity message >> rest

stanzas = concat
[ if testsEnabled then [TestStanzas] else []
, if benchmarksEnabled then [BenchStanzas] else []
]
stanzas = [ TestStanzas | testsEnabled ]
++ [ BenchStanzas | benchmarksEnabled ]
testsEnabled = fromFlagOrDefault False $ freezeTests freezeFlags
benchmarksEnabled = fromFlagOrDefault False $ freezeBenchmarks freezeFlags

Expand Down
8 changes: 3 additions & 5 deletions cabal-install/Distribution/Client/Install.hs
Original file line number Diff line number Diff line change
Expand Up @@ -402,11 +402,9 @@ planPackages comp platform mSandboxPkgInfo solver
$ standardInstallPolicy
installedPkgIndex sourcePkgDb pkgSpecifiers

stanzas = concat
[ if testsEnabled then [TestStanzas] else []
, if benchmarksEnabled then [BenchStanzas] else []
]
testsEnabled = fromFlagOrDefault False $ configTests configFlags
stanzas = [ TestStanzas | testsEnabled ]
++ [ BenchStanzas | benchmarksEnabled ]
testsEnabled = fromFlagOrDefault False $ configTests configFlags
benchmarksEnabled = fromFlagOrDefault False $ configBenchmarks configFlags

reinstall = fromFlag (installOverrideReinstall installFlags) ||
Expand Down
116 changes: 86 additions & 30 deletions cabal-install/Distribution/Client/SetupWrapper.hs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,37 @@ import System.Directory ( doesDirectoryExist )
import qualified System.Win32 as Win32
#endif

--TODO: The 'setupWrapper' and 'SetupScriptOptions' should be split into two
-- parts: one that has no policy and just does as it's told with all the
-- explicit options, and an optional initial part that applies certain
-- policies (like if we should add the Cabal lib as a dep, and if so which
-- version). This could be structured as an action that returns a fully
-- elaborated 'SetupScriptOptions' containing no remaining policy choices.
--
-- See also the discussion at https://github.com/haskell/cabal/pull/3094

data SetupScriptOptions = SetupScriptOptions {
-- | The version of the Cabal library to use (if 'useDependenciesExclusive'
-- is not set). A suitable version of the Cabal library must be installed
-- (or for some build-types be the one cabal-install was built with).
--
-- The version found also determines the version of the Cabal specification
-- that we us for talking to the Setup.hs, unless overridden by
-- 'useCabalSpecVersion'.
--
useCabalVersion :: VersionRange,

-- | This is the version of the Cabal specification that we believe that
-- this package uses. This affects the semantics and in particular the
-- Setup command line interface.
--
-- This is similar to 'useCabalVersion' but instead of probing the system
-- for a version of the /Cabal library/ you just say exactly which version
-- of the /spec/ we will use. Using this also avoid adding the Cabal
-- library as an additional dependency, so add it to 'useDependencies'
-- if needed.
--
useCabalSpecVersion :: Maybe Version,
useCompiler :: Maybe Compiler,
usePlatform :: Maybe Platform,
usePackageDB :: PackageDBStack,
Expand All @@ -137,14 +166,25 @@ data SetupScriptOptions = SetupScriptOptions {

-- | Is the list of setup dependencies exclusive?
--
-- This is here for legacy reasons. Before the introduction of the explicit
-- setup stanza in .cabal files we compiled Setup.hs scripts with all
-- packages in the environment visible, but we will needed to restrict
-- _some_ packages; in particular, we need to restrict the version of Cabal
-- that the setup script gets linked against (this was the only "dependency
-- constraint" that we had previously for Setup scripts).
-- When this is @False@, if we compile the Setup.hs script we do so with
-- the list in 'useDependencies' but all other packages in the environment
-- are also visible. Additionally, a suitable version of @Cabal@ library
-- is added to the list of dependencies (see 'useCabalVersion').
--
-- When @True@, only the 'useDependencies' packages are used, with other
-- packages in the environment hidden.
--
-- This feature is here to support the setup stanza in .cabal files that
-- specifies explicit (and exclusive) dependencies, as well as the old
-- style with no dependencies.
useDependenciesExclusive :: Bool,

-- | Should we build the Setup.hs with CPP version macros available?
-- We turn this on when we have a setup stanza in .cabal that declares
-- explicit setup dependencies.
--
useVersionMacros :: Bool,

-- Used only by 'cabal clean' on Windows.
--
-- Note: win32 clean hack
Expand Down Expand Up @@ -174,12 +214,14 @@ data SetupScriptOptions = SetupScriptOptions {
defaultSetupScriptOptions :: SetupScriptOptions
defaultSetupScriptOptions = SetupScriptOptions {
useCabalVersion = anyVersion,
useCabalSpecVersion = Nothing,
useCompiler = Nothing,
usePlatform = Nothing,
usePackageDB = [GlobalPackageDB, UserPackageDB],
usePackageIndex = Nothing,
useDependencies = [],
useDependenciesExclusive = False,
useVersionMacros = False,
useProgramConfig = emptyProgramConfiguration,
useDistPref = defaultDistPref,
useLoggingHandle = Nothing,
Expand Down Expand Up @@ -235,7 +277,9 @@ determineSetupMethod options buildType'
-- between the self and internal setup methods, which are
-- consistent with each other.
| buildType' == Custom = externalSetupMethod
| not (cabalVersion `withinRange`
| maybe False (cabalVersion /=)
(useCabalSpecVersion options)
|| not (cabalVersion `withinRange`
useCabalVersion options) = externalSetupMethod
| isJust (useLoggingHandle options)
-- Forcing is done to use an external process e.g. due to parallel
Expand Down Expand Up @@ -338,18 +382,24 @@ externalSetupMethod verbosity options pkg bt mkargs = do

cabalLibVersionToUse :: IO (Version, (Maybe UnitId)
,SetupScriptOptions)
cabalLibVersionToUse = do
savedVer <- savedVersion
case savedVer of
Just version | version `withinRange` useCabalVersion options
-> do updateSetupScript version bt
-- Does the previously compiled setup executable still exist and
-- is it up-to date?
useExisting <- canUseExistingSetup version
if useExisting
then return (version, Nothing, options)
else installedVersion
_ -> installedVersion
cabalLibVersionToUse =
case useCabalSpecVersion options of
Just version -> do
updateSetupScript version bt
writeFile setupVersionFile (show version ++ "\n")
return (version, Nothing, options)
Nothing -> do
savedVer <- savedVersion
case savedVer of
Just version | version `withinRange` useCabalVersion options
-> do updateSetupScript version bt
-- Does the previously compiled setup executable still exist
-- and is it up-to date?
useExisting <- canUseExistingSetup version
if useExisting
then return (version, Nothing, options)
else installedVersion
_ -> installedVersion
where
-- This check duplicates the checks in 'getCachedSetupExecutable' /
-- 'compileSetupExecutable'. Unfortunately, we have to perform it twice
Expand Down Expand Up @@ -551,13 +601,19 @@ externalSetupMethod verbosity options pkg bt mkargs = do
cabalDep = maybe [] (\ipkgid -> [(ipkgid, cabalPkgid)])
maybeCabalLibInstalledPkgId

-- We do a few things differently once packages opt-in and declare
-- a custom-settup stanza. In particular we then enforce the deps
-- specified, but also let the Setup.hs use the version macros.
newPedanticDeps = useDependenciesExclusive options'
selectedDeps
| newPedanticDeps = useDependencies options'
| otherwise = useDependencies options' ++ cabalDep
-- With 'useDependenciesExclusive' we enforce the deps specified,
-- so only the given ones can be used. Otherwise we allow the use
-- of packages in the ambient environment, and add on a dep on the
-- Cabal library.
--
-- With 'useVersionMacros' we use a version CPP macros .h file.
--
-- Both of these options should be enabled for packages that have
-- opted-in and declared a custom-settup stanza.
--
selectedDeps | useDependenciesExclusive options'
= useDependencies options'
| otherwise = useDependencies options' ++ cabalDep
addRenaming (ipid, pid) = (ipid, pid, defaultRenaming)
cppMacrosFile = setupDir </> "setup_macros.h"
ghcOptions = mempty {
Expand All @@ -570,15 +626,15 @@ externalSetupMethod verbosity options pkg bt mkargs = do
, ghcOptSourcePathClear = Flag True
, ghcOptSourcePath = toNubListR [workingDir]
, ghcOptPackageDBs = usePackageDB options''
, ghcOptHideAllPackages = Flag newPedanticDeps
, ghcOptCabal = Flag newPedanticDeps
, ghcOptHideAllPackages = Flag (useDependenciesExclusive options')
, ghcOptCabal = Flag (useDependenciesExclusive options')
, ghcOptPackages = toNubListR $ map addRenaming selectedDeps
, ghcOptCppIncludes = toNubListR [ cppMacrosFile
| newPedanticDeps ]
| useVersionMacros options' ]
, ghcOptExtra = toNubListR extraOpts
}
let ghcCmdLine = renderGhcOptions compiler ghcOptions
when newPedanticDeps $
when (useVersionMacros options') $
rewriteFile cppMacrosFile (generatePackageVersionMacros
[ pid | (_ipid, pid) <- selectedDeps ])
case useLoggingHandle options of
Expand Down