1 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
2 {-# OPTIONS_GHC -fno-warn-missing-signatures #-}
6 import Control
.Concurrent
.MVar
7 import Development
.Shake
8 import Development
.Shake
.Util
9 import Development
.Shake
.Config
()
10 import Development
.Shake
.Classes
11 import Development
.Shake
.FilePath
13 newtype OcamlOrdOracle
= OcamlOrdOracle
String
14 deriving (Show,Typeable
,Eq
,Hashable
,Binary
,NFData
)
15 newtype OcamlCmdLineOracle
= OcamlCmdLineOracle
String
16 deriving (Show,Typeable
,Eq
,Hashable
,Binary
,NFData
)
17 newtype CCmdLineOracle
= CCmdLineOracle
String
18 deriving (Show,Typeable
,Eq
,Hashable
,Binary
,NFData
)
19 newtype GitDescribeOracle
= GitDescribeOracle
()
20 deriving (Show,Typeable
,Eq
,Hashable
,Binary
,NFData
)
24 mudir
= "/home/malc/x/rcs/git/mupdf"
25 inOutDir s
= outdir
</> s
28 ocamldep
= "ocamldep.opt"
29 ocamlflags
= "-warn-error +a -w +a -g -safe-string"
30 ocamlflagstbl
= [("main.cmo", ("-I lablGL", "sed -f pp.sed"))
31 ,("config.cmo", ("-I lablGL", ""))
33 cflags
= "-Wall -Werror -D_GNU_SOURCE -O\
34 \ -g -std=c99 -pedantic-errors\
35 \ -Wunused-parameter -Wsign-compare -Wshadow"
38 ,"-I " ++ mudir
++ "/include -I "
39 ++ mudir
++ "/thirdparty/freetype/include -Wextra")
41 cclib
= "-lGL -lX11 -lmupdf -lz -lfreetype -ljpeg \
42 \-ljbig2dec -lopenjpeg -lmujs \
43 \-lpthread -L" ++ mudir
++ "/build/native -lcrypto"
45 getincludes
:: [String] -> [String]
47 getincludes
("-I":arg
:tl
) = arg
: getincludes tl
48 getincludes
(_
:tl
) = getincludes tl
50 isabsinc
:: String -> Bool
52 isabsinc
(hd
:_
) = hd
== '+' || hd
== '/'
55 fixincludes
("-I":d
:tl
)
56 | isabsinc d
= "-I":d
:fixincludes tl
57 |
otherwise = "-I":inOutDir d
:fixincludes tl
58 fixincludes
(e
:tl
) = e
:fixincludes tl
60 ocamlKey key |
"lablGL/" `
isPrefixOf` key
= (ocamlc
, "-I lablGL", [])
61 |
otherwise = case lookup key ocamlflagstbl
of
62 Nothing
-> (ocamlc
, ocamlflags
, [])
63 Just
(f
, []) -> (ocamlc
, ocamlflags
++ " " ++ f
, [])
64 Just
(f
, pp
) -> (ocamlc
, ocamlflags
++ " " ++ f
, ["-pp", pp
])
66 cKey key |
"lablGL/" `
isPrefixOf` key
= "-Wno-pointer-sign -O2"
67 |
otherwise = case lookup key cflagstbl
of
69 Just f
-> f
++ " " ++ cflags
71 fixppfile
:: String -> [String] -> [String]
72 fixppfile s
("File":_
:tl
) = ("File \"" ++ s
++ "\","):tl
75 fixpp
:: String -> String -> String
76 fixpp r s
= unlines [unwords $ fixppfile r
$ words x | x
<- lines s
]
78 cm
' t oracle ordoracle
=
79 target `op`
\out
-> do
80 let key
= dropDirectory1 out
81 let src
' = key
-<.> suffix
82 let src
= if src
' == "help.ml" then inOutDir src
' else src
'
84 (comp
, flags
, ppflags
) <- oracle
$ OcamlCmdLineOracle key
85 let flagl
= words flags
86 let incs
= unwords ["-I " ++ d | d
<- getincludes flagl
88 (Stdout
stdout, Stderr emsg
, Exit ex
) <-
89 cmd ocamldep
"-one-line" incs ppflags src
91 let depo
= deps
++ [dep
-<.> ".cmo" | dep
<- deps
, fit dep
]
93 deps
= deplist
$ parseMakefile
stdout
94 fit dep
= ext
== ".cmi" && base
/= baseout
95 where (base
, ext
) = splitExtension dep
96 baseout
= dropExtension out
98 let fixedflags
= fixincludes flagl
99 (Stderr emsg2
, Exit ex2
) <-
100 cmd comp
"-c -I" outdir fixedflags
"-o" out ppflags src
102 unit
$ ordoracle
$ OcamlOrdOracle out
104 where (target
, suffix
, op
) = case t
of
105 CMO
-> ("//*.cmo", ".ml", (%>))
106 CMI
-> ("//*.cmi", ".mli", (%>))
108 deplist
((_
, reqs
) : _
) =
109 [if takeDirectory1 n
== outdir
then n
else inOutDir n | n
<- reqs
]
110 ppppe ExitSuccess _ _
= return ()
111 ppppe _ src emsg
= error $ fixpp src emsg
114 depl
<- newMVar
([] :: [String])
115 shakeArgs shakeOptions
{ shakeFiles
= outdir
116 , shakeVerbosity
= Normal
117 , shakeChange
= ChangeModtimeAndDigest
} $ do
120 gitDescribeOracle
<- addOracle
$ \(GitDescribeOracle
()) -> do
121 Stdout out
<- cmd
"git describe --tags --dirty"
122 return (out
:: String)
124 ocamlOracle
<- addOracle
$ \(OcamlCmdLineOracle s
) ->
127 ocamlOrdOracle
<- addOracle
$ \(OcamlOrdOracle s
) -> do
128 unless (takeExtension s
== ".cmi") $
129 liftIO
$ modifyMVar_ depl
$ \l
-> return $ s
:l
131 cOracle
<- addOracle
$ \(CCmdLineOracle s
) -> return $ cKey s
133 inOutDir
"help.ml" %> \out
-> do
134 version
<- gitDescribeOracle
$ GitDescribeOracle
()
135 need
["mkhelp.sh", "KEYS"]
136 Stdout f
<- cmd
"/bin/sh mkhelp.sh KEYS" version
137 writeFileChanged out f
139 "//*.o" %> \out
-> do
140 let key
= dropDirectory1 out
141 flags
<- cOracle
$ CCmdLineOracle key
142 let src
= key
-<.> ".c"
143 let dep
= out
-<.> ".d"
144 unit
$ cmd ocamlc
"-ccopt"
145 [flags
++ " -MMD -MF " ++ dep
++ " -o " ++ out
] "-c" src
146 needMakefileDependencies dep
148 inOutDir
"llpp" %> \out
-> do
149 let objs
= map (inOutDir
. (++) "lablGL/ml_") ["gl.o", "glarray.o", "raw.o"]
150 need
(objs
++ map inOutDir
["link.o", "main.cmo", "help.cmo"])
151 cmos
<- liftIO
$ readMVar depl
152 unit
$ cmd ocamlc
"-g -custom -I lablGL -o " out
153 "unix.cma str.cma" (reverse cmos
)
154 (inOutDir
"link.o") "-cclib" (cclib
: objs
)
156 cm
' CMI ocamlOracle ocamlOrdOracle
157 cm
' CMO ocamlOracle ocamlOrdOracle