{- cp ~/unstable64/ghc6/new/*.deb /home/ian/public_html/haskell_deb_archive/ cp ~/unstable64/haskell-utils/new/*.deb /home/ian/public_html/haskell_deb_archive/ find /home/ian/public_html/haskell_deb_archive/ -type f \( \! -name "ghc6*" -a \! -name "haskell-utils*" \) -exec rm {} \; Either: for i in packages/*; do cd $i; dpkg-source -x *.dsc; cd ../..; done Or: for i in packages/*/*; do ( cd $i && fakeroot debian/rules clean ) ; done ./Build packages/*/*/ 2>&1 | tee log runghc Build.hs packages/*/*/ 2>&1 | tee log runghc -f/home/ian/ghc/6.8-branch/ghc/compiler/stage2/ghc-inplace Build.hs packages/*/*/ 2>&1 | tee log -} -- We make no attempt at efficiency here. In particular, after building -- any package we re-sort the whole list of packages to be built. -- We assume that each package appears only in the arguments, and that -- there are no overlaps with packages that come with GHC. module Main (main) where import Control.Monad import Distribution.Package import Distribution.PackageDescription import Distribution.Simple.Utils import Distribution.Verbosity import Distribution.Version import Data.List import Data.Ord import System.Cmd import System.Environment import System.Exit import System.IO type Command = String -- XXX security! type PackageName = String type Directory = FilePath data Package = Package GenericPackageDescription Directory deriving Show data PackageDeps = PackageDeps Package [PackageName] deriving Show -- XXX Can we get this from somewhere sensible? packagesThatComeWithGHC :: [PackageName] packagesThatComeWithGHC = [ "array", "base", "bytestring", "Cabal", "containers", "directory", "filepath", "haskell98", "hpc", "old-locale", "old-time", "packedstring", "pretty", "process", "random", "readline", "template-haskell", "unix", "Win32" ] extraPackagesDone :: [PackageName] extraPackagesDone = [] archiveDir :: Directory archiveDir = "/home/ian/public_html/haskell_deb_archive/" main :: IO () main = do hSetBuffering stdout LineBuffering dirs <- getArgs buildAll (packagesThatComeWithGHC ++ extraPackagesDone) dirs buildAll :: [PackageName] -> [Directory] -> IO () buildAll prebuilt dirs = do let verbosity = flagToVerbosity Nothing packages <- mapM (mkPackage verbosity) dirs let packageDepss = map mkPackagesDeps packages packageDepss' = foldr markBuilts packageDepss prebuilt doBuilds [] [] packageDepss' mkPackage :: Verbosity -> Directory -> IO Package mkPackage verbosity dir = do fp <- findPackageDesc verbosity dir pd <- readPackageDescription verbosity (dir ++ "/" ++ fp) return (Package pd dir) mkPackagesDeps :: Package -> PackageDeps mkPackagesDeps p@(Package gpd _) = PackageDeps p ps where pd = flattenPackageDescription gpd ps = nub $ map getDepPackageName $ buildDepends pd getDepPackageName :: Dependency -> PackageName getDepPackageName (Dependency pn _) = pn markBuilts :: PackageName -> [PackageDeps] -> [PackageDeps] markBuilts pn = sortPackageDeps . map (markBuilt pn) markBuilt :: PackageName -> PackageDeps -> PackageDeps markBuilt pn (PackageDeps pd pns) = PackageDeps pd (delete pn pns) sortPackageDeps :: [PackageDeps] -> [PackageDeps] sortPackageDeps = sortBy (comparing numDeps) where numDeps (PackageDeps _ deps) = length deps doBuilds :: [PackageName] -- Done (in reverse order) -> [PackageName] -- Failed (in reverse order) -> [PackageDeps] -- To build -> IO () doBuilds done fails pds = do printStatus fails pds case pds of (PackageDeps (Package gpd dir) []):pds' -> do built <- doBuild dir let pn = packageName $ packageDescription gpd if built then doBuilds (pn:done) fails $ markBuilts pn pds' else doBuilds done (pn:fails) pds' _ -> putStrLn ("Done: " ++ unwords (reverse done)) -- XXX We trust dir to not be nasty doBuild :: Directory -> IO Bool doBuild dir = runCommands [ -- so that we know when to make changelog entries. -- Get the package ready to be built inChroot (inDir dir "debian/rules update-generated-files"), "find " ++ dir ++ "/../ -name \"*.dsc\" -exec rm {} \\;", -- Running setup-ghc clean outside the chroot might fail due to -- (presumably) libc differences, so we make the source package in -- the chroot inChroot (inDir dir "dpkg-buildpackage -S -rfakeroot -us -uc"), -- Make a clean build result directory "rm -rf buildres", "mkdir buildres", -- Get the archive ready inDir archiveDir "dpkg-scanpackages . . > Packages", inDir archiveDir "gzip -f Packages", -- Make sure pbuilder knows about the archive asRoot "pbuilder update", -- Go for it! asRoot ("pbuilder build --buildresult buildres " ++ dir ++ "/../*.dsc"), -- And put the result in the archive "mv buildres/* " ++ archiveDir ] inChrootLocation :: FilePath inChrootLocation = "debian_packages/extralibs" inChroot :: Command -> Command inChroot c = "dchroot -c unstable64 \"cd " ++ inChrootLocation ++ " && " ++ c ++ "\"" inDir :: Directory -> Command -> Command inDir dir c = "cd " ++ dir ++ " && " ++ c asRoot :: Command -> Command asRoot cmd = "sudo " ++ cmd runCommands :: [Command] -> IO Bool runCommands [] = return True {- runCommands (c:cs) = do putStrLn c runCommands cs -} runCommands (c:cs) = do putStrLn ("Executing: " ++ c) res <- system c case res of ExitSuccess -> do putStrLn "Success" runCommands cs _ -> do putStrLn "Failed" return False printStatus :: [PackageName] -> [PackageDeps] -> IO () printStatus fails pds = do let nullFails = null fails nullPds = null pds unless nullFails $ putStrLn ("Failed: " ++ unwords fails) unless nullPds $ do putStrLn "Still to do:" mapM_ (putStrLn . f) pds unless (nullFails && nullPds) $ putStrLn "---" where f (PackageDeps (Package gpd _) deps) = let pn = packageName $ packageDescription gpd in case length deps of 0 -> "Ready: " ++ pn 1 -> "1 dep for " ++ pn ++ ": " ++ unwords deps n -> show n ++ " deps for " ++ pn ++ ": " ++ unwords deps packageName :: PackageDescription -> PackageName packageName pd = pkgName $ package pd