diff --git a/Distribution/Pot/Modules.lhs b/Distribution/Pot/Modules.lhs
new file mode 100644
--- /dev/null
+++ b/Distribution/Pot/Modules.lhs
@@ -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)
diff --git a/Distribution/Pot/Packages.lhs b/Distribution/Pot/Packages.lhs
new file mode 100644
--- /dev/null
+++ b/Distribution/Pot/Packages.lhs
@@ -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")
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -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.
diff --git a/Makefile b/Makefile
new file mode 100644
--- /dev/null
+++ b/Makefile
@@ -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/
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -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
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/autorules.mk b/autorules.mk
new file mode 100644
--- /dev/null
+++ b/autorules.mk
@@ -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
+	@:
diff --git a/exe-src/CabalLint.lhs b/exe-src/CabalLint.lhs
new file mode 100644
--- /dev/null
+++ b/exe-src/CabalLint.lhs
@@ -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
diff --git a/exe-src/Makefilerize.lhs b/exe-src/Makefilerize.lhs
new file mode 100644
--- /dev/null
+++ b/exe-src/Makefilerize.lhs
@@ -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}
+
diff --git a/exe-src/ShowPackages.lhs b/exe-src/ShowPackages.lhs
new file mode 100644
--- /dev/null
+++ b/exe-src/ShowPackages.lhs
@@ -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
diff --git a/package-o-tron.cabal b/package-o-tron.cabal
new file mode 100644
--- /dev/null
+++ b/package-o-tron.cabal
@@ -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
diff --git a/todo b/todo
new file mode 100644
--- /dev/null
+++ b/todo
@@ -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
