77{-# LANGUAGE LambdaCase #-}
88{-# LANGUAGE ScopedTypeVariables #-}
99{-# LANGUAGE StandaloneDeriving #-}
10+ {-# LANGUAGE TupleSections #-}
1011{-# LANGUAGE TypeApplications #-}
1112
1213-- |
@@ -88,6 +89,7 @@ import Distribution.Compat.Prelude
8889import Prelude ()
8990
9091import Distribution.Compat.Lens ((.~) )
92+ import Distribution.ModuleName (ModuleName )
9193import Distribution.PackageDescription
9294import Distribution.Simple.BuildPaths
9395import Distribution.Simple.Compiler (Compiler (.. ))
@@ -123,6 +125,7 @@ import qualified Data.Map as Map
123125import qualified Data.Set as Set
124126
125127import System.Directory (doesFileExist )
128+ import qualified System.FilePath as FilePath
126129
127130--------------------------------------------------------------------------------
128131-- SetupHooks
@@ -890,20 +893,64 @@ executeRulesUserOrSystem scope runDepsCmdData runCmdData verbosity lbi tgtInfo a
890893 , map (fmap ruleFromVertex) (v : vs)
891894 )
892895
893- -- Compute demanded rules.
896+ -- Compute demanded rules: anything reachable from the roots, which are:
894897 --
895- -- SetupHooks TODO: maybe requiring all generated modules to appear
896- -- in autogen-modules is excessive; we can look through all modules instead.
898+ -- - autogen modules
899+ -- - extra-c-sources, extra-asm-sources, ...
900+ -- (there is no 'autogen' field for those, at least not yet)
901+ --
902+ -- This does not include autogen-includes, because .h files are required
903+ -- during configure time, so not relevant for pre-build rules which are run
904+ -- after configure.
905+ autogenModPaths :: [RelativePath Source File ]
897906 autogenModPaths =
898907 map (\ m -> moduleNameSymbolicPath m <.> " hs" ) $
899- autogenModules $
900- componentBuildInfo $
901- targetComponent tgtInfo
902- leafRule_maybe (rId, r) =
903- if any ((r `ruleOutputsLocation` ) . (Location compAutogenDir)) autogenModPaths
904- then vertexFromRuleId rId
905- else Nothing
906- leafRules = mapMaybe leafRule_maybe $ Map. toList allRules
908+ autogenModules compBuildInfo
909+ autogenExtraSourcesPaths :: [RelativePath Source File ]
910+ autogenExtraSourcesPaths =
911+ concatMap (mapMaybe relativeToAutogen) $
912+ [ cSources compBuildInfo
913+ , cxxSources compBuildInfo
914+ , cmmSources compBuildInfo
915+ , asmSources compBuildInfo
916+ , jsSources compBuildInfo
917+ ]
918+ leafRule_maybe
919+ :: (RuleId , RuleData scope )
920+ -> Either (NotDemandedRuleReasons scope ) Graph. Vertex
921+ leafRule_maybe (rId, r)
922+ | any (any $ (r `ruleOutputsLocation` ) . Location compAutogenDir) $
923+ [ autogenModPaths
924+ , autogenExtraSourcesPaths
925+ ] =
926+ case vertexFromRuleId rId of
927+ Just v -> Right v
928+ Nothing ->
929+ error $
930+ unlines
931+ [ " internal error: no graph vertex for rule " ++ show rId
932+ , " Rule: " ++ show rId
933+ ]
934+ | otherwise =
935+ Left $
936+ NDRR
937+ { nonDemandedRules = Map. singleton rId r
938+ , nonAutogenHaskellModules =
939+ Map. singleton
940+ rId
941+ [ fromString $ intercalate " ." $ FilePath. splitDirectories hsPath
942+ | Location _ outPath <- NE. toList (results r)
943+ , (hsPath, " .hs" ) <- [FilePath. splitExtension (getSymbolicPath outPath)]
944+ ]
945+ , filesNotInAutogenFolders =
946+ Map. singleton
947+ rId
948+ [ unsafeCoerceSymbolicPath fp
949+ | Location base fp <- NE. toList (results r)
950+ , Nothing <- [relativeToAutogen base]
951+ ]
952+ }
953+ (nonDmdReasons, leafRules) = partitionEithers $ map leafRule_maybe $ Map. toList allRules
907954 demandedRuleVerts = Set. fromList $ concatMap (Graph. reachable ruleGraph) leafRules
908955 nonDemandedRuleVerts = Set. fromList (Graph. vertices ruleGraph) Set. \\ demandedRuleVerts
909956
@@ -922,22 +969,7 @@ executeRulesUserOrSystem scope runDepsCmdData runCmdData verbosity lbi tgtInfo a
922969 -- Emit a warning if there are non-demanded rules.
923970 unless (null nonDemandedRuleVerts) $
924971 warn verbosity $
925- unlines $
926- " The following rules are not demanded and will not be run:"
927- : concat
928- [ [ " - " ++ show rId ++ " ,"
929- , " generating " ++ show (NE. toList $ results r)
930- ]
931- | v <- Set. toList nonDemandedRuleVerts
932- , let (r, rId, _) = ruleFromVertex v
933- ]
934- ++ [ " Possible reasons for this error:"
935- , " - Some autogenerated modules were not declared"
936- , " (in the package description or in the pre-configure hooks)"
937- , " - The output location for an autogenerated module is incorrect,"
938- , " (e.g. the file extension is incorrect, or"
939- , " it is not in the appropriate 'autogenComponentModules' directory)"
940- ]
972+ pprNotDemandedRuleReasons comp compAutogenDir (mconcat nonDmdReasons)
941973
942974 -- Run all the demanded rules, in dependency order.
943975 for_ sccs $ \ (Graph. Node ruleVertex _) ->
@@ -977,12 +1009,74 @@ executeRulesUserOrSystem scope runDepsCmdData runCmdData verbosity lbi tgtInfo a
9771009 SSystem -> id
9781010 clbi = targetCLBI tgtInfo
9791011 mbWorkDir = mbWorkDirLBI lbi
1012+ comp = targetComponent tgtInfo
9801013 compAutogenDir = autogenComponentModulesDir lbi clbi
1014+ compBuildInfo = componentBuildInfo comp
9811015 errorOut e =
9821016 dieWithException verbosity $
9831017 SetupHooksException $
9841018 RulesException e
9851019
1020+ relativeToAutogen :: SymbolicPath Pkg to -> Maybe (RelativePath Source to )
1021+ relativeToAutogen = relativePathMaybe compAutogenDir
1022+
1023+ data NotDemandedRuleReasons scope = NDRR
1024+ { nonDemandedRules :: Map RuleId (RuleData scope )
1025+ , nonAutogenHaskellModules :: Map RuleId [ModuleName ]
1026+ , filesNotInAutogenFolders :: Map RuleId [RelativePath Pkg File ]
1027+ }
1028+ instance Semigroup (NotDemandedRuleReasons scope ) where
1029+ NDRR r1 m1 f1 <> NDRR r2 m2 f2 = NDRR (r1 <> r2) (m1 <> m2) (f1 <> f2)
1030+ instance Monoid (NotDemandedRuleReasons scope ) where
1031+ mempty = NDRR mempty mempty mempty
1032+
1033+ pprNotDemandedRuleReasons
1034+ :: Component
1035+ -> SymbolicPath Pkg (Dir Source )
1036+ -> NotDemandedRuleReasons scope
1037+ -> String
1038+ pprNotDemandedRuleReasons
1039+ comp
1040+ compAutogenDir
1041+ (NDRR non_dmd_verts mods_map miss_files_map) =
1042+ unlines $ header ++ mods_lines ++ files_lines
1043+ where
1044+ mods = aux mods_map
1045+ miss_files = aux miss_files_map
1046+
1047+ aux xs = concatMap (\ (rId, x) -> map (rId,) x) $ Map. toList xs
1048+ ppr (rId, x) = " - " ++ show x ++ " (for rule " ++ show rId ++ " )"
1049+
1050+ header :: [String ]
1051+ header =
1052+ " The following rules are not demanded and will not be run:"
1053+ : concat
1054+ [ [ " - " ++ show rId ++ " ,"
1055+ , " generating " ++ show (NE. toList $ results r)
1056+ ]
1057+ | (rId, r) <- Map. toList non_dmd_verts
1058+ ]
1059+
1060+ mods_lines , files_lines :: [String ]
1061+ mods_lines
1062+ | null mods =
1063+ []
1064+ | otherwise =
1065+ (" Perhaps add the following to the 'autogen-modules' field of '" ++ show comp ++ " '." )
1066+ : map ppr mods
1067+ files_lines
1068+ | null miss_files =
1069+ []
1070+ | otherwise =
1071+ (" The following autogenerated file" ++ s ++ " for " ++ show comp ++ " " ++ isOrAre ++ " misplaced." )
1072+ : (itOrThey ++ " should go in " ++ show compAutogenDir ++ " '." )
1073+ : map ppr miss_files
1074+ where
1075+ (s, isOrAre, itOrThey) =
1076+ case miss_files of
1077+ [_] -> (" " , " is" , " It" )
1078+ _ -> (" s" , " are" , " They" )
1079+
9861080directRuleDependencyMaybe :: Rule. Dependency -> Maybe RuleId
9871081directRuleDependencyMaybe (RuleDependency dep) = Just $ outputOfRule dep
9881082directRuleDependencyMaybe (FileDependency {}) = Nothing
0 commit comments