#!/usr/bin/runghc
\begin{code}
import Control.Monad(when)
import Control.OldException(try)
import System.Directory(removeFile,findExecutable)
import System.Exit(ExitCode(ExitSuccess) ,exitWith)
import System.IO(hClose, hGetContents, hPutStr, stderr)
import System.Process(runInteractiveProcess, waitForProcess)
import Distribution.PackageDescription
(PackageDescription ,HookedBuildInfo ,emptyHookedBuildInfo
,BuildInfo(extraLibs ,extraLibDirs ,ldOptions ,includeDirs ,ccOptions)
,emptyBuildInfo)
import Distribution.PackageDescription.Parse(writeHookedBuildInfo)
import Distribution.Simple(UserHooks(preConf,postConf) ,simpleUserHooks
,defaultMainWithHooks)
import Distribution.Simple.LocalBuildInfo(LocalBuildInfo)
import Distribution.Simple.Setup(ConfigFlags(configVerbosity),Flag)
import Distribution.Verbosity(Verbosity)
main:: IO ()
main = defaultMainWithHooks simpleUserHooks{ preConf=preConf
, postConf=postConf}
where
preConf:: [String] -> ConfigFlags -> IO HookedBuildInfo
preConf args flags = do
try (removeFile "SQLite3.buildinfo")
return emptyHookedBuildInfo
postConf:: [String] -> ConfigFlags -> PackageDescription -> LocalBuildInfo
-> IO ()
postConf args flags _ localbuildinfo = do
mb_bi <- pkgConfigBuildInfo (configVerbosity flags) "sqlite3"
let bi = case mb_bi of
Just bi -> bi
Nothing -> emptyBuildInfo{ extraLibs=["sqlite3"] }
writeHookedBuildInfo "SQLite3.buildinfo" (Just bi,[])
\end{code}
The following code is derived from Distribution.Simple.Configure
\begin{code}
findProgram:: String -- ^ program name
-> Maybe FilePath -- ^ optional explicit path
-> IO (Maybe FilePath)
findProgram name Nothing = do
mb_path <- findExecutable name
case mb_path of
Nothing -> message ("No " ++ name ++ " found")
Just path -> message ("Using " ++ name ++ ": " ++ path)
return mb_path
findProgram name (Just path) = do
message ("Using " ++ name ++ ": " ++ path)
return (Just path)
-- |
rawSystemGrabOutput:: Int -> FilePath -> [String] -> IO String
rawSystemGrabOutput verbose path args = do
when (verbose > 0) $
putStrLn (path ++ concatMap (' ':) args)
(inp,out,err,pid) <- runInteractiveProcess path args Nothing Nothing
exitCode <- waitForProcess pid
if exitCode /= ExitSuccess
then do errMsg <- hGetContents err
hPutStr stderr errMsg
exitWith exitCode
else return ()
hClose inp
hClose err
hGetContents out
-- |
message:: String -> IO ()
message s = putStrLn $ "configure: " ++ s
\end{code}
Populate BuildInfo using pkg-config tool.
\begin{code}
pkgConfigBuildInfo:: Flag Verbosity -> String -> IO (Maybe BuildInfo)
pkgConfigBuildInfo verbosity pkgName = do
let verbose= -1
mb_pkg_config_path <- findProgram "pkg-config" Nothing
case mb_pkg_config_path of
Just pkg_config_path -> do
message ("configuring "++pkgName++" package using pkg-config")
res <- rawSystemGrabOutput verbose pkg_config_path
[pkgName, "--libs-only-l"]
let libs = map (tail.tail) (words res)
res <- rawSystemGrabOutput verbose pkg_config_path
[pkgName, "--libs-only-L"]
let lib_dirs = map (tail.tail) (words res)
res <- rawSystemGrabOutput verbose pkg_config_path
[pkgName, "--libs-only-other"]
let ld_opts = words res
res <- rawSystemGrabOutput verbose pkg_config_path
[pkgName, "--cflags-only-I"]
let inc_dirs = map (tail.tail) (words res)
res <- rawSystemGrabOutput verbose pkg_config_path
[pkgName, "--cflags-only-other"]
let cc_opts = words res
let bi = emptyBuildInfo{ extraLibs=libs
, extraLibDirs=lib_dirs
, ldOptions=ld_opts
, includeDirs=inc_dirs
, ccOptions=cc_opts}
return (Just bi)
Nothing -> do
message ("The package will be built using default settings for "++pkgName)
return Nothing
\end{code}