diff options
author | Ian Lynagh <ian@well-typed.com> | 2013-04-06 23:05:29 +0100 |
---|---|---|
committer | Ian Lynagh <ian@well-typed.com> | 2013-04-07 11:39:35 +0100 |
commit | 444119fbb78aef88450bc51b54429942f8ef3cbf (patch) | |
tree | bb2a46d5ac319bdfbf2ae31ebcbff5a2ed2ab96d /utils/dll-split | |
parent | 8c2f2803e4d76cd8a6e579f55a023d7e132d479b (diff) | |
download | haskell-444119fbb78aef88450bc51b54429942f8ef3cbf.tar.gz |
Add a check that the Windows DLL split is OK; fixes #7780
Diffstat (limited to 'utils/dll-split')
-rw-r--r-- | utils/dll-split/Main.hs | 85 | ||||
-rw-r--r-- | utils/dll-split/dll-split.cabal | 21 | ||||
-rw-r--r-- | utils/dll-split/ghc.mk | 18 |
3 files changed, 124 insertions, 0 deletions
diff --git a/utils/dll-split/Main.hs b/utils/dll-split/Main.hs new file mode 100644 index 0000000000..336b6d9b26 --- /dev/null +++ b/utils/dll-split/Main.hs @@ -0,0 +1,85 @@ + +{-# LANGUAGE PatternGuards #-} + +module Main (main) where + +import Control.Monad +import Data.Function +import Data.List +import Data.Map (Map) +import qualified Data.Map as Map +import Data.Maybe +import Data.Set (Set) +import qualified Data.Set as Set +import System.Environment +import System.Exit +import System.FilePath + +main :: IO () +main = do args <- getArgs + case args of + [depfile, startModule, reachableModules] -> + doit depfile + (Module startModule) + (Set.fromList $ map Module $ words reachableModules) + _ -> error "dll-split: Bad args" + +doit :: FilePath -> Module -> Set Module -> IO () +doit depfile startModule expectedReachableMods + = do xs <- readFile depfile + let ys = catMaybes $ map mkEdge $ lines xs + mapping = mkMap ys + actualReachableMods = reachable mapping startModule + unless (actualReachableMods == expectedReachableMods) $ do + let extra = actualReachableMods Set.\\ expectedReachableMods + redundant = expectedReachableMods Set.\\ actualReachableMods + tellSet name set = unless (Set.null set) $ + let ms = map moduleName (Set.toList set) + in putStrLn (name ++ ": " ++ unwords ms) + putStrLn ("Reachable modules from " ++ moduleName startModule + ++ " out of date") + putStrLn "Please fix it, or building DLLs on Widnows may break (#7780)" + tellSet "Redundant modules" redundant + tellSet "Extra modules" extra + exitFailure + +newtype Module = Module String + deriving (Eq, Ord) + +moduleName :: Module -> String +moduleName (Module name) = name + +-- Given: +-- compiler/stage2/build/X86/Regs.o : compiler/stage2/build/CodeGen/Platform.hi +-- Produce: +-- Just ("X86.Regs", "CodeGen.Platform") +mkEdge :: String -> Maybe (Module, Module) +mkEdge str = case words str of + [from, ":", to] + | Just from' <- getModule from + , Just to' <- getModule to -> + Just (from', to') + _ -> + Nothing + where getModule xs + = case stripPrefix "compiler/stage2/build/" xs of + Just xs' -> + let name = filePathToModuleName $ dropExtension xs' + in Just $ Module name + Nothing -> Nothing + filePathToModuleName = map filePathToModuleNameChar + filePathToModuleNameChar '/' = '.' + filePathToModuleNameChar c = c + +mkMap :: [(Module, Module)] -> (Map Module (Set Module)) +mkMap edges = let groupedEdges = groupBy ((==) `on` fst) $ sort edges + mkEdgeMap ys = (fst (head ys), Set.fromList (map snd ys)) + in Map.fromList $ map mkEdgeMap groupedEdges + +reachable :: Map Module (Set Module) -> Module -> Set Module +reachable mapping startModule = f Set.empty startModule + where f done m = if m `Set.member` done + then done + else foldl' f (m `Set.insert` done) (get m) + get m = Set.toList (Map.findWithDefault Set.empty m mapping) + diff --git a/utils/dll-split/dll-split.cabal b/utils/dll-split/dll-split.cabal new file mode 100644 index 0000000000..bece0a4770 --- /dev/null +++ b/utils/dll-split/dll-split.cabal @@ -0,0 +1,21 @@ +Name: dll-split +Version: 0.1 +Copyright: XXX +License: BSD3 +-- XXX License-File: LICENSE +Author: XXX +Maintainer: XXX +Synopsis: XXX +Description: + XXX +Category: Development +build-type: Simple +cabal-version: >=1.2 + +Executable dll-split + Main-Is: Main.hs + + Build-Depends: base >= 4 && < 5, + containers, + filepath + diff --git a/utils/dll-split/ghc.mk b/utils/dll-split/ghc.mk new file mode 100644 index 0000000000..324c7e04b1 --- /dev/null +++ b/utils/dll-split/ghc.mk @@ -0,0 +1,18 @@ +# ----------------------------------------------------------------------------- +# +# (c) 2009 The University of Glasgow +# +# This file is part of the GHC build system. +# +# To understand how the build system works and how to modify it, see +# http://hackage.haskell.org/trac/ghc/wiki/Building/Architecture +# http://hackage.haskell.org/trac/ghc/wiki/Building/Modifying +# +# ----------------------------------------------------------------------------- + +utils/dll-split_USES_CABAL = YES +utils/dll-split_PACKAGE = dll-split +utils/dll-split_dist-install_PROGNAME = dll-split +utils/dll-split_dist-install_INSTALL = NO +utils/dll-split_dist-install_INSTALL_INPLACE = YES +$(eval $(call build-prog,utils/dll-split,dist-install,1)) |