2 module Main (main) where
4 import Distribution.Compat.Exception
5 import qualified Distribution.ModuleName as ModuleName
6 import Distribution.PackageDescription
7 import Distribution.PackageDescription.Configuration
8 import Distribution.PackageDescription.Parse
9 import Distribution.Simple
10 import Distribution.Simple.Configure
11 import Distribution.Simple.LocalBuildInfo
12 import Distribution.Simple.Program
13 import Distribution.Simple.Utils (defaultPackageDesc, withTempFile)
14 import Distribution.Simple.Build (writeAutogenFiles)
15 import Distribution.Simple.Register (writeInstalledConfig)
16 import Distribution.Simple.PackageIndex
17 import Distribution.Text
18 import Distribution.Verbosity
19 import qualified Distribution.InstalledPackageInfo as Installed
20 ( InstalledPackageInfo_(..) )
21 import qualified Distribution.Simple.PackageIndex as PackageIndex
22 ( topologicalOrder, lookupPackageName, insert )
24 import Control.Exception
28 import System.Directory
29 import System.Environment
31 import System.FilePath
34 main = do args <- getArgs
36 "haddock" : distDir : dir : args' ->
37 runHaddock distDir dir args'
38 "install" : ghcpkg : ghcpkgconfig : directory : distDir
39 : myDestDir : myPrefix : myLibdir : myDocdir : args' ->
40 doInstall ghcpkg ghcpkgconfig directory distDir
41 myDestDir myPrefix myLibdir myDocdir args'
42 "configure" : args' -> case break (== "--") args' of
43 (config_args, "--" : distdir : directories) ->
44 mapM_ (generate config_args distdir) directories
48 syntax_error :: [String]
50 ["syntax: ghc-cabal configure <configure-args> -- <distdir> <directory>...",
51 " ghc-cabal install <ghc-pkg> <directory> <distdir> <destdir> <prefix> <args>...",
52 " ghc-cabal haddock <distdir> <directory> <args>..."]
54 die :: [String] -> IO ()
55 die errs = do mapM_ (hPutStrLn stderr) errs
56 exitWith (ExitFailure 1)
58 -- XXX Should use bracket
59 withCurrentDirectory :: FilePath -> IO a -> IO a
60 withCurrentDirectory directory io
61 = do curDirectory <- getCurrentDirectory
62 setCurrentDirectory directory
64 setCurrentDirectory curDirectory
67 -- We need to use the autoconfUserHooks, as the packages that use
68 -- configure can create a .buildinfo file, and we need any info that
70 userHooks :: UserHooks
71 userHooks = autoconfUserHooks
73 runHaddock :: FilePath -> FilePath -> [String] -> IO ()
74 runHaddock distdir directory args
75 = withCurrentDirectory directory
76 $ defaultMainWithHooksArgs hooks ("haddock" : "--builddir" : distdir : args)
79 haddockHook = modHook (haddockHook userHooks)
81 modHook f pd lbi us flags
82 | packageName pd == PackageName "ghc-prim"
83 = let pd' = case library pd of
85 let ghcPrim = fromJust (simpleParse "GHC.Prim")
86 ems = filter (ghcPrim /=)
88 lib' = lib { exposedModules = ems }
89 in pd { library = Just lib' }
91 error "Expected a library, but none found"
93 pc' = userSpecifyArgs "haddock"
94 ["dist-install/build/autogen/GHC/Prim.hs"] pc
95 lbi' = lbi { withPrograms = pc' }
96 in f pd' lbi' us flags
100 doInstall :: FilePath -> FilePath -> FilePath -> FilePath -> FilePath
101 -> FilePath -> FilePath -> FilePath -> [String] -> IO ()
102 doInstall ghcpkg ghcpkgconf directory distDir myDestDir myPrefix myLibdir myDocdir args
103 = withCurrentDirectory directory $ do
104 defaultMainWithHooksArgs hooks (["copy", "--builddir", distDir]
105 ++ (if null myDestDir then []
106 else ["--destdir", myDestDir])
108 defaultMainWithHooksArgs hooks ("register" : "--builddir" : distDir : args)
111 copyHook = modHook (copyHook userHooks),
112 regHook = modHook (regHook userHooks)
115 modHook f pd lbi us flags
118 | packageName pd == PackageName "ghc-prim" =
121 let ghcPrim = fromJust (simpleParse "GHC.Prim")
122 ems = filter (ghcPrim /=) (exposedModules lib)
123 lib' = lib { exposedModules = ems }
124 in pd { library = Just lib' }
126 error "Expected a library, but none found"
128 idts = installDirTemplates lbi
129 idts' = idts { prefix = toPathTemplate myPrefix,
130 libdir = toPathTemplate myLibdir,
131 libsubdir = toPathTemplate "$pkgid",
132 docdir = toPathTemplate (myDocdir </> "$pkgid"),
133 htmldir = toPathTemplate "$docdir" }
134 progs = withPrograms lbi
135 prog = ConfiguredProgram {
136 programId = programName ghcPkgProgram,
137 programVersion = Nothing,
138 programArgs = ["--global-conf", ghcpkgconf]
139 ++ if not (null myDestDir)
142 programLocation = UserSpecified ghcpkg
144 progs' = updateProgram prog progs
146 installDirTemplates = idts',
147 withPrograms = progs'
149 in f pd' lbi' us flags
151 generate :: [String] -> FilePath -> FilePath -> IO ()
152 generate config_args distdir directory
153 = withCurrentDirectory directory
154 $ do let verbosity = normal
155 gpdFile <- defaultPackageDesc verbosity
156 gpd <- readPackageDescription verbosity gpdFile
158 -- XXX We shouldn't just configure with the default flags
159 -- XXX And this, and thus the "getPersistBuildConfig distdir" below,
160 -- aren't going to work when the deps aren't built yet
161 withArgs (["configure", "--distdir", distdir] ++ config_args)
162 (case buildType (flattenPackageDescription gpd) of
163 Just Configure -> defaultMainWithHooks autoconfUserHooks
164 _other -> defaultMain)
165 -- not quite right, but good enough for us
167 lbi <- getPersistBuildConfig distdir
168 let pd0 = localPkgDescr lbi
170 -- Sigh, haskeline proper uses stuff in Setup.hs to handle whether
171 -- or not -liconv is used. We don't use Setup.hs, so we replicate
172 -- what it does here. We should do this better somehow.
173 when (display (pkgName (package pd0)) == "haskeline") $
175 Nothing -> fail "Can't happen: No haskeline library"
177 d <- getCurrentDirectory
179 maybeSetLibiconv verbosity (libBuildInfo lib) lbi
182 if (buildType pd0 == Just Configure)
184 maybe_infoFile <- defaultHookedPackageDesc
185 case maybe_infoFile of
186 Nothing -> return emptyHookedBuildInfo
187 Just infoFile -> readHookedBuildInfo verbosity infoFile
189 return emptyHookedBuildInfo
191 let pd = updatePackageDescription hooked_bi pd0
193 -- generate Paths_<pkg>.hs and cabal-macros.h
194 writeAutogenFiles verbosity pd lbi
196 -- generate inplace-pkg-config
197 when (isJust $ library pd) $
198 writeInstalledConfig distdir pd lbi True Nothing
201 libBiModules lib = (libBuildInfo lib, libModules pd)
202 exeBiModules exe = (buildInfo exe, ModuleName.main : exeModules pd)
203 biModuless = (maybeToList $ fmap libBiModules $ library pd)
204 ++ (map exeBiModules $ executables pd)
205 buildableBiModuless = filter isBuildable biModuless
206 where isBuildable (bi', _) = buildable bi'
207 (bi, modules) = case buildableBiModuless of
208 [] -> error "No buildable component found"
209 [biModules] -> biModules
210 _ -> error ("XXX ghc-cabal can't handle " ++
211 "more than one buildinfo yet")
212 -- XXX Another Just...
213 Just ghcProg = lookupProgram ghcProgram (withPrograms lbi)
215 dep_pkgs = PackageIndex.topologicalOrder (packageHacks (installedPkgs lbi))
216 forDeps f = concatMap f dep_pkgs
218 -- copied from Distribution.Simple.PreProcess.ppHsc2Hs
219 packageHacks = case compilerFlavor (compiler lbi) of
220 GHC -> hackRtsPackage
222 -- We don't link in the actual Haskell libraries of our
223 -- dependencies, so the -u flags in the ldOptions of the rts
224 -- package mean linking fails on OS X (it's ld is a tad
225 -- stricter than gnu ld). Thus we remove the ldOptions for
226 -- GHC's rts package:
227 hackRtsPackage index =
228 case PackageIndex.lookupPackageName index (PackageName "rts") of
229 [rts] -> PackageIndex.insert rts { Installed.ldOptions = [] } index
230 _ -> error "No (or multiple) ghc rts package is registered!!"
232 let variablePrefix = directory ++ '_':distdir
233 let xs = [variablePrefix ++ "_VERSION = " ++ display (pkgVersion (package pd)),
234 variablePrefix ++ "_MODULES = " ++ unwords (map display modules),
235 variablePrefix ++ "_HS_SRC_DIRS = " ++ unwords (hsSourceDirs bi),
236 variablePrefix ++ "_DEPS = " ++ unwords (map display (packageDeps lbi)),
237 variablePrefix ++ "_DEP_NAMES = " ++ unwords (map (display . packageName) (packageDeps lbi)),
238 variablePrefix ++ "_INCLUDE_DIRS = " ++ unwords (includeDirs bi),
239 variablePrefix ++ "_INCLUDES = " ++ unwords (includes bi),
240 variablePrefix ++ "_INSTALL_INCLUDES = " ++ unwords (installIncludes bi),
241 variablePrefix ++ "_EXTRA_LIBRARIES = " ++ unwords (extraLibs bi),
242 variablePrefix ++ "_EXTRA_LIBDIRS = " ++ unwords (extraLibDirs bi),
243 variablePrefix ++ "_C_SRCS = " ++ unwords (cSources bi),
244 -- XXX This includes things it shouldn't, like:
245 -- -odir dist-bootstrapping/build
246 variablePrefix ++ "_HC_OPTS = " ++ escape (unwords
249 ++ extensionsToFlags (compiler lbi) (extensions bi))),
250 variablePrefix ++ "_CC_OPTS = " ++ unwords (ccOptions bi),
251 variablePrefix ++ "_CPP_OPTS = " ++ unwords (cppOptions bi),
252 variablePrefix ++ "_LD_OPTS = " ++ unwords (ldOptions bi),
253 variablePrefix ++ "_DEP_INCLUDE_DIRS = " ++ unwords (forDeps Installed.includeDirs),
254 variablePrefix ++ "_DEP_CC_OPTS = " ++ unwords (forDeps Installed.ccOptions),
255 variablePrefix ++ "_DEP_LIB_DIRS = " ++ unwords (forDeps Installed.libraryDirs),
256 variablePrefix ++ "_DEP_EXTRA_LIBS = " ++ unwords (forDeps Installed.extraLibraries),
257 variablePrefix ++ "_DEP_LD_OPTS = " ++ unwords (forDeps Installed.ldOptions)]
258 writeFile (distdir ++ "/package-data.mk") $ unlines xs
260 escape = foldr (\c xs -> if c == '#' then '\\':'#':xs else c:xs) []
262 ----------------------------------------------------------------------
263 -- haskeline-specific hacks
265 -- Sigh, haskeline proper uses stuff in Setup.hs to handle whether
266 -- or not -liconv is used. We don't use Setup.hs, so we replicate
267 -- what it does here. We should do this better somehow.
269 -- Test whether compiling a c program that links against libiconv needs -liconv.
270 maybeSetLibiconv :: Verbosity -> BuildInfo -> LocalBuildInfo -> IO ()
271 maybeSetLibiconv verb bi lbi = do
272 let biWithIconv = addIconv bi
273 worksWithout <- tryCompile iconv_prog bi lbi verb
275 then writeBuildInfo ""
277 worksWith <- tryCompile iconv_prog biWithIconv lbi verb
280 writeBuildInfo "iconv"
281 else fail "Unable to link against the iconv library."
283 -- Cabal (at least 1.6.0.1) won't parse an empty buildinfo file.
284 writeBuildInfo libs = writeFile "haskeline.buildinfo"
285 $ unlines ["extra-libraries: " ++ libs]
287 tryCompile :: String -> BuildInfo -> LocalBuildInfo -> Verbosity -> IO Bool
288 tryCompile program bi lbi verb = flip catchIO processException $ flip catchExit processExit $ do
289 tempDir <- getTemporaryDirectory
290 withTempFile tempDir ".c" $ \fname h -> do
293 -- TODO take verbosity from the args.
294 rawSystemProgramStdoutConf verb gccProgram (withPrograms lbi) (fname : args)
297 processException :: IOException -> IO Bool
298 processException _ = return False
299 processExit = return . (==ExitSuccess)
300 -- Mimicing Distribution.Simple.Configure
301 deps = topologicalOrder (installedPkgs lbi)
306 -- --extra-include-dirs and --extra-lib-dirs are included
307 -- in the below fields.
308 -- Also sometimes a dependency like rts points to a nonstandard
309 -- include/lib directory where iconv can be found.
310 , map ("-I" ++) (includeDirs bi ++ concatMap Installed.includeDirs deps)
311 , map ("-L" ++) (extraLibDirs bi ++ concatMap Installed.libraryDirs deps)
312 , map ("-l" ++) (extraLibs bi)
315 addIconv :: BuildInfo -> BuildInfo
316 addIconv bi = bi {extraLibs = "iconv" : extraLibs bi}
319 iconv_prog = unlines $
320 [ "#include <iconv.h>"
322 , " iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");"