Commit efe1b211 authored by Edward Z. Yang's avatar Edward Z. Yang Committed by Edward Z. Yang
Browse files

Don't compile signature packages with instantiations.



A signature package is a package that contains only signatures but no
modules (equivalently, it is a package that has no provisions.)

Previously, we did not treat signature packages any differently from
normal packages, which, in particular, meant that when we instantiated a
package using a signature package, we also instantiated the signature
package.  This is actually pretty useless, because we never actually use
the instantiated signature (there's no code that actually gets compiled
in this case).

This patch treats signature packages specially, so that we don't
actually instantiate dependencies on them.  This means we have
to compile less packages when handling signatures.  Good!
Signed-off-by: default avatarEdward Z. Yang <ezyang@cs.stanford.edu>
parent 9930ea81
......@@ -42,6 +42,7 @@ import Data.Traversable
import Distribution.Text
( Text(disp) )
import Text.PrettyPrint
import Data.Either
-- | A linked component is a component that has been mix-in linked, at
-- which point we have determined how all the dependencies of the
......@@ -63,10 +64,15 @@ data LinkedComponent
-- | Is this the public library of a package? Corresponds to
-- 'cc_public'.
lc_public :: Bool,
-- | Corresponds to 'cc_includes', but the 'ModuleRenaming' for
-- requirements (stored in 'IncludeRenaming') has been removed,
-- as it is reflected in 'OpenUnitId'.)
-- | Corresponds to 'cc_includes', but (1) this does not contain
-- includes of signature packages (packages with no exports),
-- and (2) the 'ModuleRenaming' for requirements (stored in
-- 'IncludeRenaming') has been removed, as it is reflected in
-- 'OpenUnitId'.)
lc_includes :: [ComponentInclude OpenUnitId ModuleRenaming],
-- | Like 'lc_includes', but this specifies includes on
-- signature packages which have no exports.
lc_sig_includes :: [ComponentInclude OpenUnitId ModuleRenaming],
-- | The module shape computed by mix-in linking. This is
-- newly computed from 'ConfiguredComponent'
lc_shape :: ModuleShape
......@@ -89,6 +95,9 @@ dispLinkedComponent lc =
hang (text "unit" <+> disp (lc_uid lc)) 4 $
vcat [ text "include" <+> disp (ci_id incl) <+> disp (ci_renaming incl)
| incl <- lc_includes lc ]
$+$
vcat [ text "signature include" <+> disp (ci_id incl)
| incl <- lc_sig_includes lc ]
$+$ dispOpenModuleSubst (modShapeProvides (lc_shape lc))
instance Package LinkedComponent where
......@@ -140,7 +149,8 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
-- TODO: the unification monad might return errors, in which
-- case we have to deal. Use monadic bind for now.
(linked_shape0 :: ModuleScope,
linked_includes :: [ComponentInclude OpenUnitId ModuleRenaming])
linked_includes :: [ComponentInclude OpenUnitId ModuleRenaming],
linked_sig_includes :: [ComponentInclude OpenUnitId ModuleRenaming])
<- orErr $ runUnifyM verbosity db $ do
-- The unification monad is implemented using mutable
-- references. Thus, we must convert our *pure* data
......@@ -153,7 +163,7 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
-- NB: We DON'T convert locally defined modules, as in the
-- absence of mutual recursion across packages they
-- cannot participate in mix-in linking.
(shapes_u, includes_u) <- fmap unzip (mapM convertInclude unlinked_includes)
(shapes_u, all_includes_u) <- fmap unzip (mapM convertInclude unlinked_includes)
src_reqs_u <- mapM convertReq src_reqs
-- Mix-in link everything! mixLink is the real workhorse.
shape_u <- foldM mixLink emptyModuleScopeU (shapes_u ++ src_reqs_u)
......@@ -167,8 +177,10 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
ci_renaming = rns
})
shape <- convertModuleScopeU shape_u
let (includes_u, sig_includes_u) = partitionEithers all_includes_u
incls <- mapM convertIncludeU includes_u
return (shape, incls)
sig_incls <- mapM convertIncludeU sig_includes_u
return (shape, incls, sig_incls)
-- linked_shape0 is almost complete, but it doesn't contain
-- the actual modules we export ourselves. Add them!
......@@ -252,7 +264,8 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
-- These must be executables
lc_internal_build_tools = map (\cid -> IndefFullUnitId cid Map.empty) btools,
lc_shape = final_linked_shape,
lc_includes = linked_includes
lc_includes = linked_includes,
lc_sig_includes = linked_sig_includes
}
-- Handle mix-in linking for components. In the absence of Backpack,
......
......@@ -317,7 +317,7 @@ toReadyComponents pid_map subst0 comps
let indefc = IndefiniteComponent {
indefc_requires = map fst (lc_insts lc),
indefc_provides = modShapeProvides (lc_shape lc),
indefc_includes = lc_includes lc
indefc_includes = lc_includes lc ++ lc_sig_includes lc
}
return $ Just ReadyComponent {
rc_uid = uid,
......
......@@ -363,7 +363,9 @@ data ModuleSourceU s =
-- unification on it.
convertInclude
:: ComponentInclude (OpenUnitId, ModuleShape) IncludeRenaming
-> UnifyM s (ModuleScopeU s, ComponentInclude (UnitIdU s) ModuleRenaming)
-> UnifyM s (ModuleScopeU s,
Either (ComponentInclude (UnitIdU s) ModuleRenaming) {- normal -}
(ComponentInclude (UnitIdU s) ModuleRenaming) {- sig -})
convertInclude (ComponentInclude {
ci_id = (uid, ModuleShape provs reqs),
ci_pkgid = pid,
......@@ -472,7 +474,14 @@ convertInclude (ComponentInclude {
provs_u <- convertModuleProvides prov_scope
return ((provs_u, reqs_u), ComponentInclude uid_u pid prov_rns')
-- TODO: Assert that provs_u is empty if provs was empty
return ((provs_u, reqs_u),
-- NB: We test that requirements is not null so that
-- users can create packages with zero module exports
-- that cause some C library to linked in, etc.
(if Map.null provs && not (Set.null reqs)
then Right -- is sig
else Left) (ComponentInclude uid_u pid prov_rns'))
-- | Convert a 'ModuleScopeU' to a 'ModuleScope'.
convertModuleScopeU :: ModuleScopeU s -> UnifyM s ModuleScope
......
......@@ -336,10 +336,7 @@ rebuildInstallPlan verbosity
localPackages
phaseMaintainPlanOutputs elaboratedPlan elaboratedShared
let instantiatedPlan = phaseInstantiatePlan elaboratedPlan
liftIO $ debugNoWrap verbosity (InstallPlan.showInstallPlan instantiatedPlan)
return (instantiatedPlan, elaboratedShared, projectConfig)
return (elaboratedPlan, elaboratedShared, projectConfig)
-- The improved plan changes each time we install something, whereas
-- the underlying elaborated plan only changes when input config
......@@ -588,17 +585,14 @@ rebuildInstallPlan verbosity
projectConfigShared
projectConfigLocalPackages
(getMapMappend projectConfigSpecificPackage)
liftIO $ debugNoWrap verbosity (InstallPlan.showInstallPlan elaboratedPlan)
return (elaboratedPlan, elaboratedShared)
let instantiatedPlan = instantiateInstallPlan elaboratedPlan
liftIO $ debugNoWrap verbosity (InstallPlan.showInstallPlan instantiatedPlan)
return (instantiatedPlan, elaboratedShared)
where
withRepoCtx = projectConfigWithSolverRepoContext verbosity
projectConfigShared
projectConfigBuildOnly
phaseInstantiatePlan :: ElaboratedInstallPlan
-> ElaboratedInstallPlan
phaseInstantiatePlan plan = instantiateInstallPlan plan
-- Update the files we maintain that reflect our current build environment.
-- In particular we maintain a JSON representation of the elaborated
-- install plan (but not the improved plan since that reflects the state
......@@ -1205,6 +1199,10 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB
-- Fortunately this is "stable" part of Cabal API.
-- But the way we get the build directory is A HORRIBLE
-- HACK.
-- NB: elab is setup to be the correct form for an
-- indefinite library, or a definite library with no holes.
-- We will modify it in 'instantiateInstallPlan' to handle
-- instantiated packages.
let elab = elab1 {
elabModuleShape = lc_shape lc,
elabUnitId = abstractUnitId (lc_uid lc),
......@@ -1213,7 +1211,7 @@ elaborateInstallPlan verbosity platform compiler compilerprogdb pkgConfigDB
elabPkgOrComp = ElabComponent $ elab_comp {
compLinkedLibDependencies = ordNub (map ci_id (lc_includes lc)),
compNonSetupDependencies =
ordNub (map (abstractUnitId . ci_id) (lc_includes lc))
ordNub (map (abstractUnitId . ci_id) (lc_includes lc ++ lc_sig_includes lc))
}
}
inplace_bin_dir
......@@ -1833,16 +1831,7 @@ instantiateInstallPlan plan =
indefiniteComponent :: UnitId -> ComponentId -> InstM ElaboratedPlanPackage
indefiniteComponent _uid cid
| Just planpkg <- Map.lookup cid cmap
= case planpkg of
InstallPlan.Configured elab@ElaboratedConfiguredPackage
{ elabPkgOrComp = ElabComponent comp } ->
return $ InstallPlan.Configured elab {
elabPkgOrComp = ElabComponent comp {
compNonSetupDependencies =
ordNub (map abstractUnitId (compLinkedLibDependencies comp))
}
}
_ -> return planpkg -- shouldn't happen
= return planpkg
| otherwise = error ("indefiniteComponent: " ++ display cid)
ready_map = execState work Map.empty
......
......@@ -425,11 +425,15 @@ data ElaboratedComponent
-- | The *external* library dependencies of this component. We
-- pass this to the configure script.
compLibDependencies :: [ConfiguredId],
-- | The linked dependencies of the component which combined with the
-- substitution in 'elabComponentId' specify the dependencies we
-- care about from the perspective of ORDERING builds. It's more
-- precise than 'compLibDependencies', and also stores information
-- about internal dependencies.
-- | In a component prior to instantiation, this list specifies
-- the 'OpenUnitId's which, after instantiation, are the
-- actual dependencies of this package. Note that this does
-- NOT include signature packages, which do not turn into real
-- ordering dependencies when we instantiate. This is intended to be
-- a purely temporary field, to carry some information to the
-- instantiation phase. It's more precise than
-- 'compLibDependencies', and also stores information about internal
-- dependencies.
compLinkedLibDependencies :: [OpenUnitId],
-- | The executable dependencies of this component (including
-- internal executables).
......
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