Skip to content

Commit 094f28b

Browse files
authored
Merge pull request #664 from phadej/new-build
Make servant buildable with cabal new-build
2 parents 8822c12 + d62865a commit 094f28b

File tree

13 files changed

+472
-89
lines changed

13 files changed

+472
-89
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
**/*/dist
2+
dist-newstyle
23
/bin
34
/lib
45
/share

cabal.project

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5152
test-suite spec
5253
type: exitcode-stdio-1.0

servant-server/Setup.hs

Lines changed: 0 additions & 2 deletions
This file was deleted.

servant-server/Setup.lhs

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ author: Servant Contributors
1919
maintainer: [email protected]
2020
copyright: 2014-2016 Zalora South East Asia Pte Ltd, Servant Contributors
2121
category: Web
22-
build-type: Simple
22+
build-type: Custom
2323
cabal-version: >=1.10
2424
tested-with: GHC >= 7.8
2525
extra-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

3538
library
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.hs

Lines changed: 0 additions & 41 deletions
This file was deleted.

servant-server/test/doctests.hsc

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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 <[email protected]>
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.hs

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)