git.iko.soy/typeable/servant
on master help sign in
Make servant buildable with cabal new-build
commitd5e73bf577294376fb12c4c9d3c20d47ba772b63 authorOleg Grenrus <oleg.grenrus@iki.fi> dateMon 16 Jan 2017, 09:06 (10 years ago) parent8822c12
13 files changed+471−89
.gitignore+1 cabal.project+7 doc/tutorial/tutorial.cabal+1 servant-server/Setup.hs−2 servant-server/Setup.lhs+165 servant-server/servant-server.cabal+5−2 servant-server/test/Doctests.hs−41 servant-server/test/doctests.hsc+61 servant/Setup.hs−2 servant/Setup.lhs+165 servant/servant.cabal+7−2 servant/test/Doctests.hs−40 servant/test/doctests.hsc+59
.gitignore+1
@@ -1,4 +1,5 @@
11**/*/dist
2+dist-newstyle
23/bin
34/lib
45/share
cabal.projectnew file+7
@@ -0,0 +1,7 @@
1+packages:
2+ servant/
3+ servant-client/
4+ servant-docs/
5+ servant-foreign/
6+ servant-server/
7+ doc/tutorial/
doc/tutorial/tutorial.cabal+1
@@ -47,6 +47,7 @@ library
4747 , http-client
4848 default-language: Haskell2010
4949 ghc-options: -Wall -pgmL markdown-unlit
50+ build-tool-depends: markdown-unlit:markdown-unlit
5051
5152test-suite spec
5253 type: exitcode-stdio-1.0
servant-server/Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
servant-server/Setup.lhsnew file+165
@@ -0,0 +1,165 @@
1+\begin{code}
2+{-# LANGUAGE CPP #-}
3+#ifndef MIN_VERSION_Cabal
4+#define MIN_VERSION_Cabal(x,y,z) 0
5+#endif
6+#ifndef MIN_VERSION_directory
7+#define MIN_VERSION_directory(x,y,z) 0
8+#endif
9+#if MIN_VERSION_Cabal(1,24,0)
10+#define InstalledPackageId UnitId
11+#endif
12+module Main (main) where
13+
14+import Control.Monad ( when )
15+import Data.List ( nub )
16+import Distribution.Package ( InstalledPackageId )
17+import Distribution.Package ( PackageId, Package (..), packageVersion )
18+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) , Library (..), BuildInfo (..))
19+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )
20+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )
21+import Distribution.Simple.BuildPaths ( autogenModulesDir )
22+import Distribution.Simple.Setup ( BuildFlags(buildDistPref, buildVerbosity), fromFlag)
23+import Distribution.Simple.LocalBuildInfo ( withPackageDB, withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps), compiler )
24+import Distribution.Simple.Compiler ( showCompilerId , PackageDB (..))
25+import Distribution.Text ( display , simpleParse )
26+import System.FilePath ( (</>) )
27+
28+#if MIN_VERSION_Cabal(1,25,0)
29+import Distribution.Simple.BuildPaths ( autogenComponentModulesDir )
30+#endif
31+
32+#if MIN_VERSION_directory(1,2,2)
33+import System.Directory (makeAbsolute)
34+#else
35+import System.Directory (getCurrentDirectory)
36+import System.FilePath (isAbsolute)
37+
38+makeAbsolute :: FilePath -> IO FilePath
39+makeAbsolute p | isAbsolute p = return p
40+ | otherwise = do
41+ cwd <- getCurrentDirectory
42+ return $ cwd </> p
43+#endif
44+
45+main :: IO ()
46+main = defaultMainWithHooks simpleUserHooks
47+ { buildHook = \pkg lbi hooks flags -> do
48+ generateBuildModule flags pkg lbi
49+ buildHook simpleUserHooks pkg lbi hooks flags
50+ }
51+
52+generateBuildModule :: BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
53+generateBuildModule flags pkg lbi = do
54+ let verbosity = fromFlag (buildVerbosity flags)
55+ let distPref = fromFlag (buildDistPref flags)
56+
57+ -- Package DBs
58+ let dbStack = withPackageDB lbi ++ [ SpecificPackageDB $ distPref </> "package.conf.inplace" ]
59+ let dbFlags = "-hide-all-packages" : packageDbArgs dbStack
60+
61+ withLibLBI pkg lbi $ \lib libcfg -> do
62+ let libBI = libBuildInfo lib
63+
64+ -- modules
65+ let modules = exposedModules lib ++ otherModules libBI
66+ -- it seems that doctest is happy to take in module names, not actual files!
67+ let module_sources = modules
68+
69+ -- We need the directory with library's cabal_macros.h!
70+#if MIN_VERSION_Cabal(1,25,0)
71+ let libAutogenDir = autogenComponentModulesDir lbi libcfg
72+#else
73+ let libAutogenDir = autogenModulesDir lbi
74+#endif
75+
76+ -- Lib sources and includes
77+ iArgs <- mapM (fmap ("-i"++) . makeAbsolute) $ libAutogenDir : hsSourceDirs libBI
78+ includeArgs <- mapM (fmap ("-I"++) . makeAbsolute) $ includeDirs libBI
79+
80+ -- CPP includes, i.e. include cabal_macros.h
81+ let cppFlags = map ("-optP"++) $
82+ [ "-include", libAutogenDir ++ "/cabal_macros.h" ]
83+ ++ cppOptions libBI
84+
85+ -- Actually we need to check whether testName suite == "doctests"
86+ -- pending https://github.com/haskell/cabal/pull/4229 getting into GHC HEAD tree
87+ withTestLBI pkg lbi $ \suite suitecfg -> when (testName suite == "doctests") $ do
88+
89+ -- get and create autogen dir
90+#if MIN_VERSION_Cabal(1,25,0)
91+ let testAutogenDir = autogenComponentModulesDir lbi suitecfg
92+#else
93+ let testAutogenDir = autogenModulesDir lbi
94+#endif
95+ createDirectoryIfMissingVerbose verbosity True testAutogenDir
96+
97+ -- write autogen'd file
98+ rewriteFile (testAutogenDir </> "Build_doctests.hs") $ unlines
99+ [ "module Build_doctests where"
100+ , ""
101+ -- -package-id etc. flags
102+ , "pkgs :: [String]"
103+ , "pkgs = " ++ (show $ formatDeps $ testDeps libcfg suitecfg)
104+ , ""
105+ , "flags :: [String]"
106+ , "flags = " ++ show (iArgs ++ includeArgs ++ dbFlags ++ cppFlags)
107+ , ""
108+ , "module_sources :: [String]"
109+ , "module_sources = " ++ show (map display module_sources)
110+ ]
111+ where
112+ -- we do this check in Setup, as then doctests don't need to depend on Cabal
113+ isOldCompiler = maybe False id $ do
114+ a <- simpleParse $ showCompilerId $ compiler lbi
115+ b <- simpleParse "7.5"
116+ return $ packageVersion (a :: PackageId) < b
117+
118+ formatDeps = map formatOne
119+ formatOne (installedPkgId, pkgId)
120+ -- The problem is how different cabal executables handle package databases
121+ -- when doctests depend on the library
122+ | packageId pkg == pkgId = "-package=" ++ display pkgId
123+ | otherwise = "-package-id=" ++ display installedPkgId
124+
125+ -- From Distribution.Simple.Program.GHC
126+ packageDbArgs :: [PackageDB] -> [String]
127+ packageDbArgs | isOldCompiler = packageDbArgsConf
128+ | otherwise = packageDbArgsDb
129+
130+ -- GHC <7.6 uses '-package-conf' instead of '-package-db'.
131+ packageDbArgsConf :: [PackageDB] -> [String]
132+ packageDbArgsConf dbstack = case dbstack of
133+ (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs
134+ (GlobalPackageDB:dbs) -> ("-no-user-package-conf")
135+ : concatMap specific dbs
136+ _ -> ierror
137+ where
138+ specific (SpecificPackageDB db) = [ "-package-conf=" ++ db ]
139+ specific _ = ierror
140+ ierror = error $ "internal error: unexpected package db stack: "
141+ ++ show dbstack
142+
143+ -- GHC >= 7.6 uses the '-package-db' flag. See
144+ -- https://ghc.haskell.org/trac/ghc/ticket/5977.
145+ packageDbArgsDb :: [PackageDB] -> [String]
146+ -- special cases to make arguments prettier in common scenarios
147+ packageDbArgsDb dbstack = case dbstack of
148+ (GlobalPackageDB:UserPackageDB:dbs)
149+ | all isSpecific dbs -> concatMap single dbs
150+ (GlobalPackageDB:dbs)
151+ | all isSpecific dbs -> "-no-user-package-db"
152+ : concatMap single dbs
153+ dbs -> "-clear-package-db"
154+ : concatMap single dbs
155+ where
156+ single (SpecificPackageDB db) = [ "-package-db=" ++ db ]
157+ single GlobalPackageDB = [ "-global-package-db" ]
158+ single UserPackageDB = [ "-user-package-db" ]
159+ isSpecific (SpecificPackageDB _) = True
160+ isSpecific _ = False
161+
162+testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]
163+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys
164+
165+\end{code}
servant-server/servant-server.cabal+5−2
@@ -19,7 +19,7 @@ author: Servant Contributors
1919maintainer: haskell-servant-maintainers@googlegroups.com
2020copyright: 2014-2016 Zalora South East Asia Pte Ltd, Servant Contributors
2121category: Web
22−build-type: Simple
22+build-type: Custom
2323cabal-version: >=1.10
2424tested-with: GHC >= 7.8
2525extra-source-files:
@@ -31,6 +31,9 @@ source-repository head
3131 type: git
3232 location: http://github.com/haskell-servant/servant.git
3333
34+custom-setup
35+ setup-depends:
36+ Cabal >=1.14, base, filepath, directory
3437
3538library
3639 exposed-modules:
@@ -144,7 +147,7 @@ test-suite doctests
144147 , directory
145148 , filepath
146149 type: exitcode-stdio-1.0
147− main-is: test/Doctests.hs
150+ main-is: test/doctests.hs
148151 buildable: True
149152 default-language: Haskell2010
150153 ghc-options: -Wall -threaded
servant-server/test/Doctests.hsdeleted−41
@@ -1,41 +0,0 @@
1−module Main where
2−
3−import Data.List (isPrefixOf)
4−import System.Directory
5−import System.FilePath
6−import System.FilePath.Find
7−import Test.DocTest
8−
9−main :: IO ()
10−main = do
11− files <- find always (extension ==? ".hs") "src"
12− mCabalMacrosFile <- getCabalMacrosFile
13− doctest $ "-isrc" : "-Iinclude" :
14− (maybe [] (\ f -> ["-optP-include", "-optP" ++ f]) mCabalMacrosFile) ++
15− "-XOverloadedStrings" :
16− "-XFlexibleInstances" :
17− "-XMultiParamTypeClasses" :
18− "-XDataKinds" :
19− "-XTypeOperators" :
20− files
21−
22−getCabalMacrosFile :: IO (Maybe FilePath)
23−getCabalMacrosFile = do
24− exists <- doesDirectoryExist "dist"
25− if exists
26− then do
27− contents <- getDirectoryContents "dist"
28− let rest = "build" </> "autogen" </> "cabal_macros.h"
29− whenExists $ case filter ("dist-sandbox-" `isPrefixOf`) contents of
30− [x] -> "dist" </> x </> rest
31− [] -> "dist" </> rest
32− xs -> error $ "ran doctests with multiple dist/dist-sandbox-xxxxx's: \n"
33− ++ show xs ++ "\nTry cabal clean"
34− else return Nothing
35− where
36− whenExists :: FilePath -> IO (Maybe FilePath)
37− whenExists file = do
38− exists <- doesFileExist file
39− return $ if exists
40− then Just file
41− else Nothing
servant-server/test/doctests.hscnew file+61
@@ -0,0 +1,61 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ForeignFunctionInterface #-}
3+-----------------------------------------------------------------------------
4+-- |
5+-- Module : Main (doctests)
6+-- Copyright : (C) 2012-14 Edward Kmett
7+-- License : BSD-style (see the file LICENSE)
8+-- Maintainer : Edward Kmett <ekmett@gmail.com>
9+-- Stability : provisional
10+-- Portability : portable
11+--
12+-- This module provides doctests for a project based on the actual versions
13+-- of the packages it was built with. It requires a corresponding Setup.lhs
14+-- to be added to the project
15+-----------------------------------------------------------------------------
16+module Main where
17+
18+import Build_doctests (flags, pkgs, module_sources)
19+import Data.Foldable (traverse_)
20+import Test.DocTest
21+
22+##if defined(mingw32_HOST_OS)
23+##if defined(i386_HOST_ARCH)
24+##define USE_CP
25+import Control.Applicative
26+import Control.Exception
27+import Foreign.C.Types
28+foreign import stdcall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
29+foreign import stdcall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
30+##elif defined(x86_64_HOST_ARCH)
31+##define USE_CP
32+import Control.Applicative
33+import Control.Exception
34+import Foreign.C.Types
35+foreign import ccall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
36+foreign import ccall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
37+##endif
38+##endif
39+
40+-- | Run in a modified codepage where we can print UTF-8 values on Windows.
41+withUnicode :: IO a -> IO a
42+##ifdef USE_CP
43+withUnicode m = do
44+ cp <- c_GetConsoleCP
45+ (c_SetConsoleCP 65001 >> m) `finally` c_SetConsoleCP cp
46+##else
47+withUnicode m = m
48+##endif
49+
50+main :: IO ()
51+main = withUnicode $ do
52+ traverse_ putStrLn args
53+ doctest args
54+ where
55+ args =
56+ "-XOverloadedStrings" :
57+ "-XFlexibleInstances" :
58+ "-XMultiParamTypeClasses" :
59+ "-XDataKinds" :
60+ "-XTypeOperators" :
61+ flags ++ pkgs ++ module_sources
servant/Setup.hsdeleted−2
@@ -1,2 +0,0 @@
1−import Distribution.Simple
2−main = defaultMain
servant/Setup.lhsnew file+165
@@ -0,0 +1,165 @@
1+\begin{code}
2+{-# LANGUAGE CPP #-}
3+#ifndef MIN_VERSION_Cabal
4+#define MIN_VERSION_Cabal(x,y,z) 0
5+#endif
6+#ifndef MIN_VERSION_directory
7+#define MIN_VERSION_directory(x,y,z) 0
8+#endif
9+#if MIN_VERSION_Cabal(1,24,0)
10+#define InstalledPackageId UnitId
11+#endif
12+module Main (main) where
13+
14+import Control.Monad ( when )
15+import Data.List ( nub )
16+import Distribution.Package ( InstalledPackageId )
17+import Distribution.Package ( PackageId, Package (..), packageVersion )
18+import Distribution.PackageDescription ( PackageDescription(), TestSuite(..) , Library (..), BuildInfo (..))
19+import Distribution.Simple ( defaultMainWithHooks, UserHooks(..), simpleUserHooks )
20+import Distribution.Simple.Utils ( rewriteFile, createDirectoryIfMissingVerbose )
21+import Distribution.Simple.BuildPaths ( autogenModulesDir )
22+import Distribution.Simple.Setup ( BuildFlags(buildDistPref, buildVerbosity), fromFlag)
23+import Distribution.Simple.LocalBuildInfo ( withPackageDB, withLibLBI, withTestLBI, LocalBuildInfo(), ComponentLocalBuildInfo(componentPackageDeps), compiler )
24+import Distribution.Simple.Compiler ( showCompilerId , PackageDB (..))
25+import Distribution.Text ( display , simpleParse )
26+import System.FilePath ( (</>) )
27+
28+#if MIN_VERSION_Cabal(1,25,0)
29+import Distribution.Simple.BuildPaths ( autogenComponentModulesDir )
30+#endif
31+
32+#if MIN_VERSION_directory(1,2,2)
33+import System.Directory (makeAbsolute)
34+#else
35+import System.Directory (getCurrentDirectory)
36+import System.FilePath (isAbsolute)
37+
38+makeAbsolute :: FilePath -> IO FilePath
39+makeAbsolute p | isAbsolute p = return p
40+ | otherwise = do
41+ cwd <- getCurrentDirectory
42+ return $ cwd </> p
43+#endif
44+
45+main :: IO ()
46+main = defaultMainWithHooks simpleUserHooks
47+ { buildHook = \pkg lbi hooks flags -> do
48+ generateBuildModule flags pkg lbi
49+ buildHook simpleUserHooks pkg lbi hooks flags
50+ }
51+
52+generateBuildModule :: BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
53+generateBuildModule flags pkg lbi = do
54+ let verbosity = fromFlag (buildVerbosity flags)
55+ let distPref = fromFlag (buildDistPref flags)
56+
57+ -- Package DBs
58+ let dbStack = withPackageDB lbi ++ [ SpecificPackageDB $ distPref </> "package.conf.inplace" ]
59+ let dbFlags = "-hide-all-packages" : packageDbArgs dbStack
60+
61+ withLibLBI pkg lbi $ \lib libcfg -> do
62+ let libBI = libBuildInfo lib
63+
64+ -- modules
65+ let modules = exposedModules lib ++ otherModules libBI
66+ -- it seems that doctest is happy to take in module names, not actual files!
67+ let module_sources = modules
68+
69+ -- We need the directory with library's cabal_macros.h!
70+#if MIN_VERSION_Cabal(1,25,0)
71+ let libAutogenDir = autogenComponentModulesDir lbi libcfg
72+#else
73+ let libAutogenDir = autogenModulesDir lbi
74+#endif
75+
76+ -- Lib sources and includes
77+ iArgs <- mapM (fmap ("-i"++) . makeAbsolute) $ libAutogenDir : hsSourceDirs libBI
78+ includeArgs <- mapM (fmap ("-I"++) . makeAbsolute) $ includeDirs libBI
79+
80+ -- CPP includes, i.e. include cabal_macros.h
81+ let cppFlags = map ("-optP"++) $
82+ [ "-include", libAutogenDir ++ "/cabal_macros.h" ]
83+ ++ cppOptions libBI
84+
85+ -- Actually we need to check whether testName suite == "doctests"
86+ -- pending https://github.com/haskell/cabal/pull/4229 getting into GHC HEAD tree
87+ withTestLBI pkg lbi $ \suite suitecfg -> when (testName suite == "doctests") $ do
88+
89+ -- get and create autogen dir
90+#if MIN_VERSION_Cabal(1,25,0)
91+ let testAutogenDir = autogenComponentModulesDir lbi suitecfg
92+#else
93+ let testAutogenDir = autogenModulesDir lbi
94+#endif
95+ createDirectoryIfMissingVerbose verbosity True testAutogenDir
96+
97+ -- write autogen'd file
98+ rewriteFile (testAutogenDir </> "Build_doctests.hs") $ unlines
99+ [ "module Build_doctests where"
100+ , ""
101+ -- -package-id etc. flags
102+ , "pkgs :: [String]"
103+ , "pkgs = " ++ (show $ formatDeps $ testDeps libcfg suitecfg)
104+ , ""
105+ , "flags :: [String]"
106+ , "flags = " ++ show (iArgs ++ includeArgs ++ dbFlags ++ cppFlags)
107+ , ""
108+ , "module_sources :: [String]"
109+ , "module_sources = " ++ show (map display module_sources)
110+ ]
111+ where
112+ -- we do this check in Setup, as then doctests don't need to depend on Cabal
113+ isOldCompiler = maybe False id $ do
114+ a <- simpleParse $ showCompilerId $ compiler lbi
115+ b <- simpleParse "7.5"
116+ return $ packageVersion (a :: PackageId) < b
117+
118+ formatDeps = map formatOne
119+ formatOne (installedPkgId, pkgId)
120+ -- The problem is how different cabal executables handle package databases
121+ -- when doctests depend on the library
122+ | packageId pkg == pkgId = "-package=" ++ display pkgId
123+ | otherwise = "-package-id=" ++ display installedPkgId
124+
125+ -- From Distribution.Simple.Program.GHC
126+ packageDbArgs :: [PackageDB] -> [String]
127+ packageDbArgs | isOldCompiler = packageDbArgsConf
128+ | otherwise = packageDbArgsDb
129+
130+ -- GHC <7.6 uses '-package-conf' instead of '-package-db'.
131+ packageDbArgsConf :: [PackageDB] -> [String]
132+ packageDbArgsConf dbstack = case dbstack of
133+ (GlobalPackageDB:UserPackageDB:dbs) -> concatMap specific dbs
134+ (GlobalPackageDB:dbs) -> ("-no-user-package-conf")
135+ : concatMap specific dbs
136+ _ -> ierror
137+ where
138+ specific (SpecificPackageDB db) = [ "-package-conf=" ++ db ]
139+ specific _ = ierror
140+ ierror = error $ "internal error: unexpected package db stack: "
141+ ++ show dbstack
142+
143+ -- GHC >= 7.6 uses the '-package-db' flag. See
144+ -- https://ghc.haskell.org/trac/ghc/ticket/5977.
145+ packageDbArgsDb :: [PackageDB] -> [String]
146+ -- special cases to make arguments prettier in common scenarios
147+ packageDbArgsDb dbstack = case dbstack of
148+ (GlobalPackageDB:UserPackageDB:dbs)
149+ | all isSpecific dbs -> concatMap single dbs
150+ (GlobalPackageDB:dbs)
151+ | all isSpecific dbs -> "-no-user-package-db"
152+ : concatMap single dbs
153+ dbs -> "-clear-package-db"
154+ : concatMap single dbs
155+ where
156+ single (SpecificPackageDB db) = [ "-package-db=" ++ db ]
157+ single GlobalPackageDB = [ "-global-package-db" ]
158+ single UserPackageDB = [ "-user-package-db" ]
159+ isSpecific (SpecificPackageDB _) = True
160+ isSpecific _ = False
161+
162+testDeps :: ComponentLocalBuildInfo -> ComponentLocalBuildInfo -> [(InstalledPackageId, PackageId)]
163+testDeps xs ys = nub $ componentPackageDeps xs ++ componentPackageDeps ys
164+
165+\end{code}
servant/servant.cabal+7−2
@@ -15,7 +15,7 @@ author: Servant Contributors
1515maintainer: haskell-servant-maintainers@googlegroups.com
1616copyright: 2014-2016 Zalora South East Asia Pte Ltd, Servant Contributors
1717category: Web
18−build-type: Simple
18+build-type: Custom
1919cabal-version: >=1.10
2020tested-with: GHC >= 7.8
2121extra-source-files:
@@ -25,6 +25,10 @@ source-repository head
2525 type: git
2626 location: http://github.com/haskell-servant/servant.git
2727
28+custom-setup
29+ setup-depends:
30+ Cabal >=1.14, base, filepath, directory
31+
2832library
2933 exposed-modules:
3034 Servant.API
@@ -134,8 +138,9 @@ test-suite doctests
134138 , directory
135139 , filepath
136140 type: exitcode-stdio-1.0
137− main-is: test/Doctests.hs
141+ main-is: test/doctests.hs
138142 buildable: True
139143 default-language: Haskell2010
140144 ghc-options: -Wall -threaded
145+ build-tools: hsc2hs
141146 include-dirs: include
servant/test/Doctests.hsdeleted−40
@@ -1,40 +0,0 @@
1−module Main where
2−
3−import Data.List (isPrefixOf)
4−import System.Directory
5−import System.FilePath
6−import System.FilePath.Find
7−import Test.DocTest
8−
9−main :: IO ()
10−main = do
11− files <- find always (extension ==? ".hs") "src"
12− tfiles <- find always (extension ==? ".hs") "test/Servant"
13− mCabalMacrosFile <- getCabalMacrosFile
14− doctest $ "-isrc" : "-Iinclude" :
15− (maybe [] (\ f -> ["-optP-include", "-optP" ++ f]) mCabalMacrosFile) ++
16− "-XOverloadedStrings" :
17− "-XFlexibleInstances" :
18− "-XMultiParamTypeClasses" :
19− (files ++ tfiles)
20−
21−getCabalMacrosFile :: IO (Maybe FilePath)
22−getCabalMacrosFile = do
23− exists <- doesDirectoryExist "dist"
24− if exists
25− then do
26− contents <- getDirectoryContents "dist"
27− let rest = "build" </> "autogen" </> "cabal_macros.h"
28− whenExists $ case filter ("dist-sandbox-" `isPrefixOf`) contents of
29− [x] -> "dist" </> x </> rest
30− [] -> "dist" </> rest
31− xs -> error $ "ran doctests with multiple dist/dist-sandbox-xxxxx's: \n"
32− ++ show xs ++ "\nTry cabal clean"
33− else return Nothing
34− where
35− whenExists :: FilePath -> IO (Maybe FilePath)
36− whenExists file = do
37− exists <- doesFileExist file
38− return $ if exists
39− then Just file
40− else Nothing
servant/test/doctests.hscnew file+59
@@ -0,0 +1,59 @@
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE ForeignFunctionInterface #-}
3+-----------------------------------------------------------------------------
4+-- |
5+-- Module : Main (doctests)
6+-- Copyright : (C) 2012-14 Edward Kmett
7+-- License : BSD-style (see the file LICENSE)
8+-- Maintainer : Edward Kmett <ekmett@gmail.com>
9+-- Stability : provisional
10+-- Portability : portable
11+--
12+-- This module provides doctests for a project based on the actual versions
13+-- of the packages it was built with. It requires a corresponding Setup.lhs
14+-- to be added to the project
15+-----------------------------------------------------------------------------
16+module Main where
17+
18+import Build_doctests (flags, pkgs, module_sources)
19+import Data.Foldable (traverse_)
20+import Test.DocTest
21+
22+##if defined(mingw32_HOST_OS)
23+##if defined(i386_HOST_ARCH)
24+##define USE_CP
25+import Control.Applicative
26+import Control.Exception
27+import Foreign.C.Types
28+foreign import stdcall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
29+foreign import stdcall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
30+##elif defined(x86_64_HOST_ARCH)
31+##define USE_CP
32+import Control.Applicative
33+import Control.Exception
34+import Foreign.C.Types
35+foreign import ccall "windows.h SetConsoleCP" c_SetConsoleCP :: CUInt -> IO Bool
36+foreign import ccall "windows.h GetConsoleCP" c_GetConsoleCP :: IO CUInt
37+##endif
38+##endif
39+
40+-- | Run in a modified codepage where we can print UTF-8 values on Windows.
41+withUnicode :: IO a -> IO a
42+##ifdef USE_CP
43+withUnicode m = do
44+ cp <- c_GetConsoleCP
45+ (c_SetConsoleCP 65001 >> m) `finally` c_SetConsoleCP cp
46+##else
47+withUnicode m = m
48+##endif
49+
50+main :: IO ()
51+main = withUnicode $ do
52+ traverse_ putStrLn args
53+ doctest args
54+ where
55+ args =
56+ "-XOverloadedStrings" :
57+ "-XFlexibleInstances" :
58+ "-XMultiParamTypeClasses" :
59+ flags ++ pkgs ++ module_sources