packages feed

haskeline-0.6.1.3: Setup.hs

import Distribution.System
import Distribution.Verbosity
import Distribution.PackageDescription
import Distribution.Simple
import Distribution.Simple.Program
import Distribution.Simple.Setup
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Utils

import System.IO
import System.Exit
import System.Directory
import Control.Exception.Extensible

-- TODO: it's a hack that we use the autoconfUserHooks when we're not actually
-- using autoconf...
main :: IO ()
main = defaultMainWithHooks myHooks

myHooks :: UserHooks
myHooks
    | buildOS == Windows    = simpleUserHooks
    | otherwise = autoconfUserHooks {
            postConf = \args flags pkgDescr lbi -> do
                            let Just lib = library pkgDescr
                            let bi = libBuildInfo lib
                            bi' <- maybeSetLibiconv flags bi
                                                        (withPrograms lbi)
                            let pkgDescr' = pkgDescr {
                                                library = Just lib {
                                                    libBuildInfo = bi'}}
                            postConf simpleUserHooks args flags pkgDescr' lbi
            }

-- Test whether compiling a c program that links against libiconv needs -liconv.
maybeSetLibiconv :: ConfigFlags -> BuildInfo -> ProgramConfiguration -> IO BuildInfo
maybeSetLibiconv flags bi progConf = do
    let verb = fromFlag (configVerbosity flags)
    if hasFlagSet flags (FlagName "libiconv")
        then do
            putStrLn "Using -liconv."
            writeBuildInfo "iconv"
            return bi
        else do
    putStr "checking whether to use -liconv... "
    hFlush stdout
    worksWithout <- tryCompile iconv_prog bi progConf verb
    if worksWithout
        then do
            putStrLn "not needed."
            writeBuildInfo ""
            return bi
        else do
    let newBI = addIconv bi
    worksWith <- tryCompile iconv_prog newBI progConf verb
    if worksWith
        then do
            putStrLn "using -liconv."
            writeBuildInfo "iconv"
            return newBI
        else error "Unable to link against the iconv library."
  where
    -- Cabal (at least 1.6.0.1) won't parse an empty buildinfo file.
    writeBuildInfo libs = writeFile "haskeline.buildinfo"
                            $ unlines ["extra-libraries: " ++ libs]

hasFlagSet :: ConfigFlags -> FlagName -> Bool
hasFlagSet cflags flag = Just True == lookup flag (configConfigurationsFlags cflags)

tryCompile :: String -> BuildInfo -> ProgramConfiguration -> Verbosity -> IO Bool
tryCompile program bi progConf verb = handle processExit $ handle processException $ do
    tempDir <- getTemporaryDirectory
    withTempFile tempDir ".c" $ \fname h -> do
        hPutStr h program
        hClose h
        -- TODO take verbosity from the args.
        rawSystemProgramStdoutConf verb gccProgram progConf (fname : args)
        return True
  where
    processException :: IOException -> IO Bool
    processException e = return False
    processExit = return . (==ExitSuccess)
    args = concat [ []
                  , ccOptions bi
                  , cppOptions bi
                  , ldOptions bi
                  -- --extra-include-dirs and --extra-lib-dirs are included
                  -- in the below fields.
                  , map ("-I" ++) (includeDirs bi)
                  , map ("-L" ++) (extraLibDirs bi)
                  , map ("-l" ++) (extraLibs bi)
                  ]

addIconv :: BuildInfo -> BuildInfo
addIconv bi = bi {extraLibs = "iconv" : extraLibs bi}

iconv_prog :: String
iconv_prog = unlines $
    [ "#include <iconv.h>"
    , "int main(void) {"
    , "    iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");"
    , "    return 0;"
    , "}"
    ]