@@ -1,210 +0,0 @@
1−#!/usr/bin/env runghc
2−
3−-- NB: This code deliberately avoids relying on non-standard packages
4−
5−import Control.Monad
6−import Data.List
7−import Data.Version
8−import System.Environment
9−import System.Exit
10−import System.IO
11−
12−import Distribution.PackageDescription.Parse (readPackageDescription)
13−import Distribution.PackageDescription (packageDescription, testedWith)
14−import Distribution.Compiler (CompilerFlavor(..))
15−import Distribution.Version
16−import Distribution.Text
17−
18−putStrLnErr :: String -> IO ()
19−putStrLnErr m = hPutStrLn stderr ("*ERROR* " ++ m) >> exitFailure
20−
21−putStrLnWarn :: String -> IO ()
22−putStrLnWarn m = hPutStrLn stderr ("*WARNING* " ++ m)
23−
24−putStrLnInfo :: String -> IO ()
25−putStrLnInfo m = hPutStrLn stderr ("*INFO* " ++ m)
26−
27−main :: IO ()
28−main = do
29− args <- getArgs
30− case args of
31− (cabfn:xpkgs) -> do genTravisFromCabalFile cabfn xpkgs
32− _ -> putStrLnErr (unlines $ [ "expected .cabal file as command-line argument"
33− , "Usage: make_travis_yml.hs <cabal-file> <extra-apt-packages...>"
34− , ""
35− , "Example: make_travis_yml.hs someProject.cabal alex-3.1.4 liblzma-dev > .travis.yml"
36− ])
37−
38−genTravisFromCabalFile :: FilePath -> [String] -> IO ()
39−genTravisFromCabalFile fn xpkgs = do
40− gpd <- readPackageDescription maxBound fn
41−
42− let compilers = testedWith $ packageDescription $ gpd
43−
44− let unknownComps = nub [ c | (c,_) <- compilers, c /= GHC ]
45− ghcVerConstrs = [ vc | (GHC,vc) <- compilers ]
46− ghcVerConstrs' = simplifyVersionRange $ foldr unionVersionRanges noVersion ghcVerConstrs
47−
48− when (null compilers) $ do
49− putStrLnErr "empty or missing 'tested-with:' definition in .cabal file"
50−
51− unless (null unknownComps) $ do
52− putStrLnWarn $ "ignoring unsupported compilers mentioned in tested-with: " ++ show unknownComps
53−
54− when (null ghcVerConstrs) $ do
55− putStrLnErr "'tested-with:' doesn't mention any 'GHC' version"
56−
57− when (isNoVersion ghcVerConstrs') $ do
58− putStrLnErr "'tested-with:' describes an empty version range for 'GHC'"
59−
60− when (isAnyVersion ghcVerConstrs') $ do
61− putStrLnErr "'tested-with:' allows /any/ 'GHC' version"
62−
63− let testedGhcVersions = filter (`withinRange` ghcVerConstrs') knownGhcVersions
64−
65− when (null testedGhcVersions) $ do
66− putStrLnErr "no known GHC version is allowed by the 'tested-with' specification"
67−
68− putStrLnInfo $ "Generating Travis-CI config for testing for GHC versions: " ++ (unwords $ map disp' $ testedGhcVersions)
69−
70− ----------------------------------------------------------------------------
71− -- travis.yml generation starts here
72−
73− putStrLn "# This file has been generated -- see https://github.com/hvr/multi-ghc-travis"
74− putStrLn "language: c"
75− putStrLn "sudo: false"
76− putStrLn ""
77− putStrLn "cache:"
78− putStrLn " directories:"
79− putStrLn " - $HOME/.cabsnap"
80− putStrLn " - $HOME/.cabal/packages"
81− putStrLn ""
82− putStrLn "before_cache:"
83− putStrLn " - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log"
84− putStrLn " - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar"
85− putStrLn ""
86− putStrLn "matrix:"
87− putStrLn " include:"
88−
89− forM_ testedGhcVersions $ \gv -> do
90− let cvs = disp' (lookupCabVer gv)
91− gvs = disp' gv
92− ghcopts = if gv >= Version [7,10,0] []
93− then "-Werror"
94− else "-Werror"
95−
96− xpkgs' = concatMap (',':) xpkgs
97−
98− putStrLn $ concat [ " - env: CABALVER=", cvs, " GHCVER=", gvs,
99− " GHCOPTS=", ghcopts]
100− putStrLn $ concat [ " compiler: \": #GHC ", gvs, "\"" ]
101− putStrLn $ concat [ " addons: {apt: {packages: [cabal-install-", cvs, ",ghc-", gvs, xpkgs'
102− , "], sources: [hvr-ghc]}}" ]
103− return ()
104−
105− let headGhcVers = filter isHead testedGhcVersions
106−
107− unless (null headGhcVers) $ do
108− putStrLn ""
109− putStrLn " allow_failures:"
110−
111− forM_ headGhcVers $ \gv -> do
112− let cvs = disp' (lookupCabVer gv)
113− gvs = disp' gv
114− putStrLn $ concat [ " - env: CABALVER=", cvs, " GHCVER=", gvs ]
115−
116− putStrLn ""
117− putStrLn "before_install:"
118− putStrLn " - unset CC"
119− putStrLn " - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH"
120−
121− putStrLn ""
122−
123− putStr $ unlines
124− [ "install:"
125− , " - cabal --version"
126− , " - echo \"$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]\""
127− , " - if [ -f $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz ];"
128− , " then"
129− , " zcat $HOME/.cabal/packages/hackage.haskell.org/00-index.tar.gz >"
130− , " $HOME/.cabal/packages/hackage.haskell.org/00-index.tar;"
131− , " fi"
132− , " - travis_retry cabal update -v"
133− , " - sed -i 's/^jobs:/-- jobs:/' ${HOME}/.cabal/config"
134− , " - cabal install --only-dependencies --enable-tests --enable-benchmarks --dry -v > installplan.txt"
135− , " - sed -i -e '1,/^Resolving /d' installplan.txt; cat installplan.txt"
136− , ""
137− , "# check whether current requested install-plan matches cached package-db snapshot"
138− , " - if diff -u installplan.txt $HOME/.cabsnap/installplan.txt;"
139− , " then"
140− , " echo \"cabal build-cache HIT\";"
141− , " rm -rfv .ghc;"
142− , " cp -a $HOME/.cabsnap/ghc $HOME/.ghc;"
143− , " cp -a $HOME/.cabsnap/lib $HOME/.cabsnap/share $HOME/.cabsnap/bin $HOME/.cabal/;"
144− , " else"
145− , " echo \"cabal build-cache MISS\";"
146− , " rm -rf $HOME/.cabsnap;"
147− , " mkdir -p $HOME/.ghc $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin;"
148− , " cabal install --only-dependencies --enable-tests --enable-benchmarks;"
149− , " fi"
150− , " "
151− , "# snapshot package-db on cache miss"
152− , " - if [ ! -d $HOME/.cabsnap ];"
153− , " then"
154− , " echo \"snapshotting package-db to build-cache\";"
155− , " mkdir $HOME/.cabsnap;"
156− , " cp -a $HOME/.ghc $HOME/.cabsnap/ghc;"
157− , " cp -a $HOME/.cabal/lib $HOME/.cabal/share $HOME/.cabal/bin installplan.txt $HOME/.cabsnap/;"
158− , " fi"
159− , ""
160− , "# Here starts the actual work to be performed for the package under test;"
161− , "# any command which exits with a non-zero exit code causes the build to fail."
162− , "script:"
163− , " - if [ -f configure.ac ]; then autoreconf -i; fi"
164− , " - cabal configure --enable-tests --enable-benchmarks -v2 # -v2 provides useful information for debugging"
165− , " - cabal build --ghc-options=$GHCOPTS # this builds all libraries and executables (including tests/benchmarks)"
166− , " - cabal test"
167− , " - cabal check"
168− , "# Test that a source-distribution can be generated"
169− , "# (with cabal >= 1.18 'cabal sdist' would work too):"
170− , " - ./dist/setup/setup sdist"
171− , ""
172− , "# Check that the resulting source distribution can be built & installed."
173− , "# If there are no other `.tar.gz` files in `dist`, this can be even simpler:"
174− , "# `cabal install --force-reinstalls dist/*-*.tar.gz`"
175− , " - SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&"
176− , " (cd dist && cabal install --force-reinstalls \"$SRC_TGZ\")"
177− , ""
178− , "# EOF"
179− ]
180−
181− return ()
182− where
183− knownGhcVersions :: [Version]
184− knownGhcVersions = fmap (`Version` [])
185− [ [7,0,1], [7,0,2], [7,0,3], [7,0,4]
186− , [7,2,1], [7,2,2]
187− , [7,4,1], [7,4,2]
188− , [7,6,1], [7,6,2], [7,6,3]
189− , [7,8,1], [7,8,2], [7,8,3], [7,8,4]
190− , [7,10,1], [7,10,2], [7,10,3]
191− , [7,11] -- HEAD
192− ]
193−
194− lookupCabVer :: Version -> Version
195− lookupCabVer (Version (x:y:_) _) = maybe (error "internal error") id $ lookup (x,y) cabalVerMap
196− where
197− cabalVerMap = fmap (fmap (`Version` []))
198− [ ((7, 0), [1,16])
199− , ((7, 2), [1,16])
200− , ((7, 4), [1,16])
201− , ((7, 6), [1,16])
202− , ((7, 8), [1,18])
203− , ((7,10), [1,22])
204− , ((7,11), [1,23]) -- HEAD
205− ]
206−
207− isHead (Version (_:y:_) _) = odd (y :: Int)
208−
209− disp' v | isHead v = "head"
210− | otherwise = display v