packages feed

package-o-tron (empty) → 0.1.0.0

raw patch · 12 files changed

+849/−0 lines, 12 filesdep +Cabaldep +basedep +filemanipsetup-changed

Dependencies added: Cabal, base, filemanip, filepath, groom, packdeps, process

Files

+ Distribution/Pot/Modules.lhs view
@@ -0,0 +1,140 @@++simplistic parser which can list the modules imported by a haskell+source file++provides a recursive-memoized mode which can efficiently get the+complete transitive imports of a set of files++provides a method of splitting the imports into modules which are in+the local fileset, and modules which aren't (the local module+dependencies can be used for a build tool, and the non-local ones for+determining which packages are referenced)++> {-# LANGUAGE TupleSections #-}+> module Distribution.Pot.Modules+>     (ModuleInfo(..)+>     ,modulesInfo+>     ,showmi+>     ,filterModules) where++> import Data.Maybe+> import qualified System.FilePath.Find as F+> import System.FilePath.Find ((==?),(||?))+> import System.FilePath+> import Text.Groom+> import Data.List+> import Distribution.Pot.Packages+> import Control.Arrow++> parseImports :: String -> [String]+> parseImports src = mapMaybe (im . words) $ lines src+>   where+>     im (">":x:_) | x /= "import" = Nothing+>     im (">":"import":"qualified":nm:_) = Just nm+>     im (">":"import":nm:_) = Just nm+>     im (x:_) | x /= "import" = Nothing+>     im ("import":"qualified":nm:_) = Just nm+>     im ("import":nm:_) = Just nm+>     im _ = Nothing++reads the folders passed in as source roots and returns a list of all+the modules++> getLocalModules :: [FilePath] -> IO [(FilePath,FilePath)]+> getLocalModules dirs =+>   concat `fmap` mapM findHs dirs+>   where+>     findHs dir =+>        map ((dir,) . makeRelative dir) `fmap`+>        F.find (return True) (F.extension ==? ".lhs" ||? F.extension ==? ".hs") dir++> -- | The collected information on one module+> data ModuleInfo =+>     ModuleInfo+>     {miFileName :: FilePath+>     ,miFilePrefix :: FilePath+>     ,miModuleFile :: FilePath+>     ,miModuleName :: String+>     ,miLocalDependencies :: [((FilePath,FilePath),String)]+>     ,miLocalTransitiveDependencies :: [((FilePath,FilePath),String)]+>     ,miPackages :: [String]+>     ,miTransitivePackages :: [String]+>     } deriving Show+++> -- | Takes a set of source files and gets the ModuleInfo information+> --   for all of them+> modulesInfo :: [FilePath] -- ^ the root folders containing the source files+>                           -- to analyze+>             -> IO [(FilePath,ModuleInfo)]+> modulesInfo srcs = do+>   lms <- getLocalModules srcs+>   mps <- mapM (\(a,b) -> ((a,b),) `fmap` parseImports `fmap` readFile (a </> b)) lms+>   -- mps is a map from (sourceroot,modulepath) to [modules imported]+>   --putStrLn $ intercalate "\n\n" $ map (\(n,is) -> show n ++ "\n" ++ groom is) mps+>   -- split mps 2nd elements into local modules and other modules+>   let localModuleFiles = map (snd . fst) mps+>       localModuleNames = map (repSlash . dropExtension) localModuleFiles+>   --putStrLn $ groom localModuleNames+>   let mps2 = map (second (partition (`elem` localModuleNames))) mps+>   --putStrLn $ intercalate "\n\n" $ map (\(n,is) -> show n ++ "\n" ++ groom is) mps2+>   -- process the other module lists to get list of packages instead+>   pkgs <- readPackages+>   let mps3 = map (second $ second $ getPackages pkgs) mps2+>       tms = map mm mps3+>   -- add the transitive local dependencies+>       ldeps = map (\((_,mf),(lds,_)) ->+>                      (repSlash (dropExtension mf), lds)) mps3+>       allDeps :: String -> [String]+>       allDeps f = sort $ nub+>                   $ maybe []+>                   (\x -> x ++ concatMap allDeps x)+>                   $ lookup f ldeps+>       tmslds = map (second $ \m -> m {miLocalTransitiveDependencies =+>                                       map (("",""),) $ allDeps (miModuleName m)}) tms+>   -- add the transitive packages+>       packm :: [(String,[String])]+>       packm = map (\((_,mf),(_,ps)) ->+>                      (repSlash (dropExtension mf), ps)) mps3+>       packs s = fromMaybe [] $ lookup s packm+>       tmspacks = map (second $ \m -> m {miTransitivePackages =+>                                         sort $ nub+>                                         $ concatMap packs (miModuleName m+>                                                            : map snd (miLocalTransitiveDependencies m))})+>                      tmslds+>       lmFile (_,m) =+>           maybe (error $ "couldn't get filename for " ++ m)+>           (\(r,f) -> ((r, f), m))+>           $ find ((==m) . repSlash . dropExtension . snd) lms+>       ff x = x {miLocalDependencies = map lmFile $ miLocalDependencies x+>                ,miLocalTransitiveDependencies = map lmFile $ miLocalTransitiveDependencies x}+>   --putStrLn $ intercalate "\n\n" $ map (\(n,is) -> show n ++ "\n" ++ groom is) mps3+>       t2 = map (second ff) tmspacks+>   return t2+>   where+>     mm ((r,f),(lds,ps)) = (r </> f+>                           ,ModuleInfo {miFileName = r </> f+>                                       ,miFilePrefix = r+>                                       ,miModuleFile = f+>                                       ,miModuleName = repSlash (dropExtension f)+>                                       ,miLocalDependencies = map (("",""),) lds+>                                       ,miLocalTransitiveDependencies = []+>                                       ,miPackages = ps+>                                       ,miTransitivePackages = []})+>     repSlash = map $ \c -> case c of+>                              '/' -> '.'+>                              _ -> c+>     getPackages :: [(String,[String])] -> [String] -> [String]+>     getPackages pkgs ms =+>        let pkg m = fst `fmap` find (\(_,pms) -> m `elem` pms) pkgs+>            p1 = mapMaybe pkg ms+>        in sort $ nub p1++> -- | helper to filter the two module lists according to some function+> filterModules :: (String -> Bool) -> ModuleInfo -> ModuleInfo+> filterModules f mi = mi {miPackages = filter f $ miPackages mi+>                         ,miTransitivePackages = filter f $ miTransitivePackages mi}+++> showmi :: [(FilePath,ModuleInfo)] -> String+> showmi = intercalate "\n\n" . map (\(f,i) -> f ++ "\n" ++ groom i)
+ Distribution/Pot/Packages.lhs view
@@ -0,0 +1,38 @@++> module Distribution.Pot.Packages (readPackages) where++> import Data.List+> import System.Process+> import Text.Groom+++> -- | returns a map from package name to the names of the modules in+> --   that package. The information is from the output of ghc-pkg dump, so+> --   only includes information from installed packages+> readPackages :: IO [(String,[String])]+> readPackages = do+>   inf <- readProcess "ghc-pkg" ["dump"] ""+>   return $ kludgePackages $ parsePackages [] $ lines inf+>   where+>     parsePackages acc (f:v) | "name: " `isPrefixOf` f =+>         parseModules acc (drop (length "name: ") f) v+>     parsePackages acc (_:v) = parsePackages acc v+>     parsePackages acc [] = acc+>     parseModules acc nm (f:v) | "exposed-modules:" `isPrefixOf` f =+>       parseMoreModules acc nm [drop (length "exposed-modules:") f] v+>     parseModules acc nm (_:v) = parseModules acc nm v+>     parseModules _ nm [] = error $ "didn't find exposed-modules for package " ++ nm+>     parseMoreModules acc nm macc ((' ':f):v) = parseMoreModules acc nm (f:macc) v+>     parseMoreModules acc nm macc v =+>       let ms = (nm, words $ unwords macc)+>       in parsePackages (ms:acc) v++> kludgePackages :: [(String,[String])] -> [(String,[String])]+>     -- lots of modules appear in base, haskell98, haskell2010+>     -- just use base for now.+> kludgePackages = filter ((`notElem` ["haskell98"+>                                     ,"haskell2010"]) . fst)+++> _s :: [(String,[String])] -> String+> _s = intercalate "\n\n" . map (\(n,ms) -> n ++ "\n" ++ groom ms ++ "\n")
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2012, Jake Wheat++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Jake Wheat nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Makefile view
@@ -0,0 +1,59 @@++# Example makefile which can compile the source for this project.+# Look in the autorules.mk to see the automatically generated+# support. You can regenerate the autorules.mk using the autorules+# rule++# the source directories where the haskell source roots are (paths+# relative to this Makefile)+SRC_DIRS = . exe-src++# the names of exe files to compile (these need to be the full paths+# from the Makefile). You have to use ./ prefix if it is in the root folder+EXE_FILES = exe-src/Makefilerize exe-src/Dump exe-src/DumpPackageDB \+        exe-src/ShowPackages exe-src/CabalLint++# folder to put build and exe files in+BUILD = build++# the command and options used to compile .hs/.lhs to .o+HC              = ghc+HC_BASIC_OPTS   = -Wall++space :=+space +=+comma := ,+HC_INCLUDE_DIRS = -i$(subst $(space),:,$(SRC_DIRS))++HC_OPTS = $(HC_BASIC_OPTS) $(HC_INCLUDE_DIRS)++# the command and options used to link .o files to an executable+# usually the same as the compile commands+# you could put options which are needed to link all the exes+# here+# there is also a variable per exe to add link specific commands+# for that exe (e.g. some of your exes need to link to a .so+# and some don't)+HL = $(HC)+HL_OPTS = $(HC_OPTS)+++# create an all rule which builds all the exes+# (the exes are all created directly in the $(BUILD) folder+EXE_FILES_TARGETS = $(addprefix $(BUILD)/, $(notdir $(EXE_FILES)))+all : $(EXE_FILES_TARGETS)++# include the autogenerated rules+-include autorules.mk++# regenerate the dependency and rules for exe compiles+# use cabal configure && cabal build to make the Makefilerize exe+.PHONY : autorules+autorules :+	Makefilerize package-o-tron FLDS $(SRC_DIRS) EXES $(EXE_FILES) > \+            autorules.mk++.PHONY : clean+clean :+	-rm -Rf dist/+	-rm -Rf build/
+ README view
@@ -0,0 +1,107 @@+Package-o-tron is a collection of utilities to help managing cabal+files for your projects, maintaining Makefiles and other build+systems, and also some which help with your package database.+++The central code is a function which takes a list of folders, then+parses all the imports in all the haskell source in these folders. It+then creates the dependency information between the different files,+and the dependency on packages information (using ghc-pkg dump)+++Currently implemented:++The Makefile in the package-o-tron package gives an example of how to+use package-o-tron to help manage a makefile for haskell projects,+using the Makefilerize command.++You could use a Makefile:++* to quickly develop when you have multiple .cabal projects and don't+  want to spend time reinstalling them when you do a rebuild (this can+  also be much faster if you use -j and have lots of executables)++* if you have files to compile as part of the development which aren't+  in a cabal package, or if you want to integrate with existing+  Makefiles, e.g. for mixed haskell/c projects.++See the Makefile and autorules.mk in the repo (link below) for an+example of how this works. This tool is used in the hssqlppp project+Makefile (https://github.com/JakeWheat/hssqlppp), see the Makefile and+autorules.mk there for another example.+++CabalLint++CabalLint will check the following issues in your cabal file:++*  missing and superfluous other-modules and build-deps in library,exe+   and test sections++*  version ranges which exclude the latest versions of a build-dep+   (just uses packdeps from hackage)++run it like this:+CabalLint package-o-tron.cabal+No output means everything OK+++ShowPackages++Run on a set of source folders, and it will show you all the packages+referenced by the source in those folders++++Planned utils:++Showpackages: extend to show indirectly depended on packages as well++blessed package set creation: run on some folders to get a package+list. Then it follows the package dependencies to get all the needed+non-system packages. Then it looks in your .cabal and copies out the+tarballs for all these packages. Now you can create a fresh install in+a sandbox or fresh machine without needing an internet connection, or+worrying about if hackage is down, or if the latest set of packages+don't install.++Cabal build testing++Use sandboxing to check the sdists from a .cabal install without error+and if there are tests they run and pass. The sandboxing is used to+check a range of versions of ghc crossed with the lowest and latest+versions of the dependencies listed in the .cabal. Later, maybe this+can be extended to search earlier versions of dependencies to get more+accurate lower bounds.++Package database lint:++check your ghc package database for the following issues:+duplicate packages installed+packages which aren't the latest versions installed+not sure how to automatically help with these situations though++Third party cabal install checker:++run a wrapper around cabal-install ... --dry-run. reports:+any reinstalls (easy since cabal already does this)+any different versions of already installed packages would be+  installed+any versions of packages which aren't the latest of those packages+  would be installed++Third party cabal file hacker:++when you try to install a lot of packages, and some of them have+version constraints on their dependencies which lead to another+package being installed not at the latest version: this will cabal+unpack the offending packages and alter their constraints to allow all+the latest versions of packages automatically. Not completely safe of+course, but I always end up doing this manually and it is really+tedious.++++Repository: https://github.com/JakeWheat/package-o-tron++Contact: jakewheatmail@gmail.com
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ autorules.mk view
@@ -0,0 +1,156 @@+$(BUILD)/Distribution/Pot/Modules.o : ./Distribution/Pot/Modules.lhs \+    $(BUILD)/Distribution/Pot/Packages.hi+	-mkdir -p $(BUILD)/Distribution/Pot/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -package filemanip -package filepath -package groom -c $< -o $(BUILD)/Distribution/Pot/Modules.o \+        -i$(BUILD)/++$(BUILD)/Distribution/Pot/Packages.o : ./Distribution/Pot/Packages.lhs+	-mkdir -p $(BUILD)/Distribution/Pot/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -package groom -package process -c $< -o $(BUILD)/Distribution/Pot/Packages.o \+        -i$(BUILD)/++$(BUILD)/Setup.o : ./Setup.hs+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -package Cabal -c $< -o $(BUILD)/Setup.o \+        -i$(BUILD)/++$(BUILD)/exe-src/CabalLint.o : ./exe-src/CabalLint.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/exe-src/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package Cabal -package base -package filepath -package packdeps -c $< -o $(BUILD)/exe-src/CabalLint.o \+        -i$(BUILD)/++$(BUILD)/exe-src/Dump.o : ./exe-src/Dump.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/exe-src/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/exe-src/Dump.o \+        -i$(BUILD)/++$(BUILD)/exe-src/DumpPackageDB.o : ./exe-src/DumpPackageDB.lhs \+    $(BUILD)/Distribution/Pot/Packages.hi+	-mkdir -p $(BUILD)/exe-src/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/exe-src/DumpPackageDB.o \+        -i$(BUILD)/++$(BUILD)/exe-src/Makefilerize.o : ./exe-src/Makefilerize.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/exe-src/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -package filepath -c $< -o $(BUILD)/exe-src/Makefilerize.o \+        -i$(BUILD)/++$(BUILD)/exe-src/ShowPackages.o : ./exe-src/ShowPackages.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/exe-src/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/exe-src/ShowPackages.o \+        -i$(BUILD)/++$(BUILD)/CabalLint.o : exe-src/CabalLint.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package Cabal -package base -package filepath -package packdeps -c $< -o $(BUILD)/CabalLint.o \+        -i$(BUILD)/++$(BUILD)/Dump.o : exe-src/Dump.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/Dump.o \+        -i$(BUILD)/++$(BUILD)/DumpPackageDB.o : exe-src/DumpPackageDB.lhs \+    $(BUILD)/Distribution/Pot/Packages.hi+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/DumpPackageDB.o \+        -i$(BUILD)/++$(BUILD)/Makefilerize.o : exe-src/Makefilerize.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -package filepath -c $< -o $(BUILD)/Makefilerize.o \+        -i$(BUILD)/++$(BUILD)/ShowPackages.o : exe-src/ShowPackages.lhs \+    $(BUILD)/Distribution/Pot/Modules.hi+	-mkdir -p $(BUILD)/+	$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ -package base -c $< -o $(BUILD)/ShowPackages.o \+        -i$(BUILD)/+$(BUILD)/Makefilerize : $(BUILD)/Makefilerize.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o+	-mkdir -p $(BUILD)/+	$(HL) $(HL_OPTS) $(MAKEFILERIZE_EXTRA) \+    -o $(BUILD)/Makefilerize \+    $(BUILD)/Makefilerize.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o \+    -hide-all-packages \+    -package base \+    -package filemanip \+    -package filepath \+    -package groom \+    -package process++$(BUILD)/Dump : $(BUILD)/Dump.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o+	-mkdir -p $(BUILD)/+	$(HL) $(HL_OPTS) $(DUMP_EXTRA) \+    -o $(BUILD)/Dump \+    $(BUILD)/Dump.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o \+    -hide-all-packages \+    -package base \+    -package filemanip \+    -package filepath \+    -package groom \+    -package process++$(BUILD)/DumpPackageDB : $(BUILD)/DumpPackageDB.o \+    $(BUILD)/Distribution/Pot/Packages.o+	-mkdir -p $(BUILD)/+	$(HL) $(HL_OPTS) $(DUMPPACKAGEDB_EXTRA) \+    -o $(BUILD)/DumpPackageDB \+    $(BUILD)/DumpPackageDB.o \+    $(BUILD)/Distribution/Pot/Packages.o \+    -hide-all-packages \+    -package base \+    -package groom \+    -package process++$(BUILD)/ShowPackages : $(BUILD)/ShowPackages.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o+	-mkdir -p $(BUILD)/+	$(HL) $(HL_OPTS) $(SHOWPACKAGES_EXTRA) \+    -o $(BUILD)/ShowPackages \+    $(BUILD)/ShowPackages.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o \+    -hide-all-packages \+    -package base \+    -package filemanip \+    -package filepath \+    -package groom \+    -package process++$(BUILD)/CabalLint : $(BUILD)/CabalLint.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o+	-mkdir -p $(BUILD)/+	$(HL) $(HL_OPTS) $(CABALLINT_EXTRA) \+    -o $(BUILD)/CabalLint \+    $(BUILD)/CabalLint.o \+    $(BUILD)/Distribution/Pot/Modules.o \+    $(BUILD)/Distribution/Pot/Packages.o \+    -hide-all-packages \+    -package Cabal \+    -package base \+    -package filemanip \+    -package filepath \+    -package groom \+    -package packdeps \+    -package process+++%.hi : %.o+	@:
+ exe-src/CabalLint.lhs view
@@ -0,0 +1,124 @@++Cabal lint checks your cabal file++It currently reports:++missing other modules and build-deps (build-deps missing is usually+  hard to miss!)+superfluous other modules and build-deps+it checks library,exe, and v10 test sections+it also runs the packdeps check to check your upper bounds on the+  build-deps+++TODO:+check for duplicates in other-modules and build-depends+  and other-modules include root modules (already does this?)+list files in project which aren't included in .cabal+verbose mode++> import System.Environment+> import Distribution.PackDeps+> import Distribution.PackageDescription.Parse+> import Distribution.Verbosity+> import Distribution.PackageDescription+> import Distribution.Pot.Modules+> import Control.Applicative+> import Data.List+> import Distribution.ModuleName hiding (main)+> import Control.Monad+> import Distribution.Package+> import System.FilePath+> import Data.Maybe+> import System.Exit++> data SectionInformation =+>   SI+>   {siSrcDirs :: [FilePath]+>   ,siSectionName :: String+>   ,siModRoots :: [ModuleName]+>   ,siOtherMods :: [ModuleName]+>   ,siBuildDeps :: [Dependency]+>   }++> main :: IO ()+> main = do+>   [fp] <- getArgs+>   di <- readPackageDescription normal fp+>   --putStrLn $ groom di+>   let -- get the source dirs, add "." if empty list+>       -- not sure if "." should always be added?+>       sd bi = map (dropFileName fp </>) $+>               let x = hsSourceDirs bi+>               in if null x+>                  then ["."]+>                  else x+>       libSi = do+>          cnd <- condLibrary di+>          let ctd = condTreeData cnd+>              srcDirs = sd $ libBuildInfo ctd+>          return $ SI srcDirs "library" (exposedModules ctd)+>                         (otherModules $ libBuildInfo ctd)+>                         (condTreeConstraints cnd)+>       exeSis = flip map (condExecutables di) $ \(n,cnd) ->+>          let ctd = condTreeData cnd+>              srcDirs = sd $ buildInfo ctd+>          in SI srcDirs ("Executable: " ++ n)+>                        [fromString $ dropExtension $ modulePath ctd]+>                        (otherModules $ buildInfo ctd)+>                        (condTreeConstraints cnd)+>       testsSis = flip map (condTestSuites di) $ \(n,cnd) ->+>          let ctd = condTreeData cnd+>              srcDirs = sd $ testBuildInfo ctd+>              modName = case testInterface ctd of+>                            TestSuiteExeV10 _ p -> [fromString $ dropExtension p]+>                            x -> error $ "test suite type not supported: " ++ show x+>          in SI srcDirs ("Executable: " ++ n)+>                        modName+>                        (otherModules $ testBuildInfo ctd)+>                        (condTreeConstraints cnd)+>       benchmarksSis = [] -- TODO+>       sis = maybeToList libSi ++ exeSis ++ testsSis ++ benchmarksSis++>   allMis <- modulesInfo $ nub $ concatMap siSrcDirs sis+>   psGood <- and <$> mapM (checkModulesAndPackages allMis) sis+>   vsGood <- checkNewestVersions fp+>   if psGood && vsGood+>       then exitSuccess+>       else exitFailure+>   where+>     moduleString = intercalate "." . components+>     dependencyName (Dependency (PackageName s) _) = s+>     checkLists section field cab fil = do+>           let cab' = nub cab+>               fil' = nub fil+>               extraCab = cab' \\ fil'+>               missingCab = fil' \\ cab'+>           unless (null extraCab) $ putStrLn $ "extra unneeded " ++ field ++ " in " ++ section ++ ":\n" ++ intercalate "\n" extraCab+>           unless (null missingCab) $ putStrLn $ "missing " ++ field ++ " in " ++ section ++ ":\n" ++ intercalate "\n" missingCab+>           return $ null extraCab && null missingCab+>     checkModulesAndPackages allMis si = do+>          let rootModules = map moduleString $ siModRoots si+>              mis = filter ((`elem` rootModules) . miModuleName . snd) allMis+>              filesModules = sort $ nub $ concatMap (map snd . miLocalTransitiveDependencies . snd) mis+>              filesPackages = sort $ nub $ concatMap (miTransitivePackages . snd) mis+>              cabalOms = map moduleString (siOtherMods si)+>              cabalPackages = map dependencyName (siBuildDeps si)+>          a <- checkLists (siSectionName si) "other-modules" cabalOms (filesModules \\ rootModules)+>          b <- checkLists (siSectionName si) "build-depends" cabalPackages filesPackages+>          return $ a && b++> checkNewestVersions :: FilePath -> IO Bool+> checkNewestVersions fp = do+>   newest <- loadNewest+>   mdi <- loadPackage fp+>   di2 <- case mdi of+>                  Just di2 -> return di2+>                  Nothing -> error $ "Could not parse cabal file: " ++ fp+>   case checkDeps newest di2 of+>             (_pn, _v, AllNewest) ->+>                 return True+>             (_pn, _v, WontAccept p _) -> do+>                 putStrLn "Cannot accept the following packages"+>                 forM_ p $ \(x, y) -> putStrLn $ x ++ " " ++ y+>                 return False
+ exe-src/Makefilerize.lhs view
@@ -0,0 +1,92 @@+Example of calling this file:++Makefilerize package-o-tron FLDS . exe-src EXES exe-src/Makefilerize exe-src/ShowPackages exe-src/CabalLint++write the packages to ignore first the the text 'FLDS'+then write the folders which source appears in (same folders you would+pass to -i with ghc) then the text 'EXES'+write the paths to the exes++It will generate rules to compile all the .o files and link the exes,+with explicit package lists.++See the included Makefile, autorules.mk file for an example of how to+use this, and an example of what is output.++TODO:++support two stage .o, .dyn_o to get creation of .so with source that+uses template haskell++> import Distribution.Pot.Modules+> import Data.List+> import System.FilePath+> import System.Environment+> import Control.Arrow+> import Data.Char+> import Data.Maybe++> moduleCompile :: ModuleInfo -> String+> moduleCompile mi =+>   objOf mi+>   ++ " : " ++ intercalate " \\\n    " (miFileName mi : map (fhiOf . fst) (miLocalDependencies mi))+>   ++ "\n\t-mkdir -p " ++ dropFileName (objOf mi)+>   ++ "\n\t$(HC) $(HC_OPTS) -hide-all-packages -outputdir $(BUILD)/ "+>   ++ unwords (map ("-package " ++) $ addBase $ miPackages mi)+>   ++ " -c $< -o " ++ objOf mi+>   ++ " \\\n        -i$(BUILD)/"+++> objOf :: ModuleInfo -> FilePath+> objOf = ("$(BUILD)/" ++) . flip replaceExtension "o" . miModuleFile+> fobjOf :: (FilePath,FilePath) -> FilePath+> fobjOf = ("$(BUILD)/" ++) . flip replaceExtension "o" . snd+> fhiOf :: (FilePath,FilePath) -> FilePath+> fhiOf = ("$(BUILD)/" ++) . flip replaceExtension "hi" . snd+> exeOf :: ModuleInfo -> FilePath+> exeOf = ("$(BUILD)/" ++) . takeFileName . dropExtension . miModuleFile++> addBase :: [String] -> [String]+> addBase x | "base" `elem` x = x+> addBase x = "base" : x++> exeLink :: ModuleInfo -> String+> exeLink mi =+>   exeOf mi ++ " : "+>   ++ intercalate " \\\n    " (objOf mi : map (fobjOf . fst) (miLocalTransitiveDependencies mi))+>   ++ "\n\t-mkdir -p $(BUILD)/"+>   ++ "\n\t$(HL) $(HL_OPTS) $(" ++ mangledExeName (miFileName mi)+>   ++ ") \\\n    "+>   ++ intercalate " \\\n    "+>      (["-o " ++ exeOf mi, objOf mi]+>       ++ map (fobjOf . fst) (miLocalTransitiveDependencies mi)+>       ++ ["-hide-all-packages"]+>       ++ map ("-package " ++) (addBase $ miTransitivePackages mi))+>   where+>     mangledExeName = (++ "_EXTRA")+>                      . map toUpper+>                      . map (\c -> case c of+>                                       '/' -> '_'+>                                       _ -> c)+>                      . takeFileName+>                      . dropExtension++> main :: IO ()+> main = do+>   args <- getArgs+>   let (hidepacks,args') = second (drop 1) $ break (=="FLDS") args+>       (modules,exes) = second (drop 1) $ break (=="EXES") args'+>   mis <- map (second $ hidePackage hidepacks) `fmap` modulesInfo modules+>   putStrLn $ intercalate "\n\n" $ map (moduleCompile . snd) mis+>   let exeMis = map exeMi exes+>       exeMi exe = fromMaybe+>                   (error $ "source file for exe not found: " ++ show exe+>                    ++ " in\n"+>                    ++ intercalate "\n" (map (dropExtension . miFileName . snd) mis))+>                   $ find ((== exe) . dropExtension . miFileName . snd) mis+>   putStrLn $ intercalate "\n\n" $ map (exeLink . snd) exeMis+>   putStrLn "\n\n%.hi : %.o\n\t@:"+>   where+>     hidePackage ps m = m {miPackages = filter (`notElem` ps) $ miPackages m+>                          ,miTransitivePackages = filter (`notElem` ps) $ miTransitivePackages m}+
+ exe-src/ShowPackages.lhs view
@@ -0,0 +1,23 @@++input a set of folders++finds all the haskell source in these folders and follows all the+imports of other source in these folders, and outputs the complete+list of directly referenced packages++TODO: option to include all the indirectly depended packages+to output package versions as well+to exclude system packages+to collect the tarballs for all these packages++> import Distribution.Pot.Modules+> import System.Environment+> import Control.Applicative+> import Data.List++> main :: IO ()+> main = do+>   args <- getArgs+>   mi <- map snd <$> modulesInfo args+>   let ps = sort $ nub $ concatMap miPackages mi+>   putStrLn $ intercalate "\n" ps
+ package-o-tron.cabal view
@@ -0,0 +1,57 @@+name:                package-o-tron+version:             0.1.0.0+synopsis:            Utilities for working with cabal packages and your package database++description:         Utility to help managing Makefiles for Haskell projects, a cabal lint+                     which can check the other-modules and build-deps+                     sections in your cabal files, and a quick command+                     that can show the direct package dependencies of+                     a set of Haskell source files. See the README in+                     the repo for more information:+                     <https://github.com/JakeWheat/package-o-tron>.+++license:             BSD3+license-file:        LICENSE+author:              Jake Wheat+maintainer:          jakewheatmail@gmail.com+copyright:           Jake Wheat 2012+category:            Development+build-type:          Simple+cabal-version:       >=1.8++extra-source-files:  autorules.mk+                     LICENSE+                     README+                     Makefile+                     todo++source-repository head+  type:     git+  location: https://github.com/JakeWheat/package-o-tron.git++library+  exposed-modules:  Distribution.Pot.Packages, Distribution.Pot.Modules+  build-depends:    base >= 4 && < 5,+                    groom,process,filepath,filemanip++executable Makefilerize+  build-depends:    base >= 4 && < 5,+                    filepath,groom,process,filemanip+  main-is:          Makefilerize.lhs+  hs-source-dirs:   .,exe-src+  other-modules:    Distribution.Pot.Packages, Distribution.Pot.Modules++executable CabalLint+  build-depends:    base >= 4 && < 5,+                    filepath,groom,process,filemanip,Cabal,packdeps+  main-is:          CabalLint.lhs+  hs-source-dirs:   .,exe-src+  other-modules:    Distribution.Pot.Packages, Distribution.Pot.Modules++executable ShowPackages+  build-depends:    base >= 4 && < 5,+                    filepath,groom,process,filemanip+  main-is:          ShowPackages.lhs+  hs-source-dirs:   .,exe-src+  other-modules:    Distribution.Pot.Packages, Distribution.Pot.Modules
+ todo view
@@ -0,0 +1,21 @@+find a better name for 'Makefilerize'+lint: duplicate listing, unreferenced files, extensions, benchmark+   sections+fix the dump exes++blessed .tar.gz set generation++check cabal --dry-run for dups/ not latest version++package database checker: dup versions, non latest versions++tester: use sandboxing to:+    compile and run tests -> successful compile and successful test+      run is the validation+    start with the sdist tarball+    check ghc versions: target 7.0.x through 7.6.x+    check it works with all the latest package versions in the+      dependency ranges on each ghc+    check it works with all the earliest "++third party package hacker