From 71dcc642edcfc3bfeef2619d66183cc08ae90a43 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Wed, 29 Apr 2009 18:19:09 +0000 Subject: [PATCH] Add special support for haskeline The library uses stuff in Setup.hs to determine whether or not it needs to use -liconv. This patch replicates that logic in ghc-cabal. This isn't pretty, and we should find a better way to do it, but it works for now. --- utils/ghc-cabal/ghc-cabal.hs | 84 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 2 deletions(-) diff --git a/utils/ghc-cabal/ghc-cabal.hs b/utils/ghc-cabal/ghc-cabal.hs index c806d3c..c19217e 100644 --- a/utils/ghc-cabal/ghc-cabal.hs +++ b/utils/ghc-cabal/ghc-cabal.hs @@ -1,6 +1,7 @@ module Main (main) where +import Distribution.Compat.Exception import qualified Distribution.ModuleName as ModuleName import Distribution.PackageDescription import Distribution.PackageDescription.Configuration @@ -9,9 +10,10 @@ import Distribution.Simple import Distribution.Simple.Configure import Distribution.Simple.LocalBuildInfo import Distribution.Simple.Program -import Distribution.Simple.Utils (defaultPackageDesc) +import Distribution.Simple.Utils (defaultPackageDesc, withTempFile) import Distribution.Simple.Build (writeAutogenFiles) import Distribution.Simple.Register (writeInstalledConfig) +import Distribution.Simple.PackageIndex import Distribution.Text import Distribution.Verbosity import qualified Distribution.InstalledPackageInfo as Installed @@ -19,6 +21,7 @@ import qualified Distribution.InstalledPackageInfo as Installed import qualified Distribution.Simple.PackageIndex as PackageIndex ( topologicalOrder, lookupPackageName, insert ) +import Control.Exception import Control.Monad import Data.Maybe import System.IO @@ -148,7 +151,7 @@ doInstall ghcpkg ghcpkgconf directory distDir myDestDir myPrefix myLibdir myDocd generate :: [String] -> FilePath -> FilePath -> IO () generate config_args distdir directory = withCurrentDirectory directory - $ do let verbosity = verbose + $ do let verbosity = normal gpdFile <- defaultPackageDesc verbosity gpd <- readPackageDescription verbosity gpdFile @@ -164,6 +167,17 @@ generate config_args distdir directory lbi <- getPersistBuildConfig distdir let pd0 = localPkgDescr lbi + -- Sigh, haskeline proper uses stuff in Setup.hs to handle whether + -- or not -liconv is used. We don't use Setup.hs, so we replicate + -- what it does here. We should do this better somehow. + when (display (pkgName (package pd0)) == "haskeline") $ + case library pd0 of + Nothing -> fail "Can't happen: No haskeline library" + Just lib -> do + d <- getCurrentDirectory + print d + maybeSetLibiconv verbosity (libBuildInfo lib) lbi + hooked_bi <- if (buildType pd0 == Just Configure) then do @@ -244,3 +258,69 @@ generate config_args distdir directory writeFile (distdir ++ "/package-data.mk") $ unlines xs where escape = foldr (\c xs -> if c == '#' then '\\':'#':xs else c:xs) [] + +---------------------------------------------------------------------- +-- haskeline-specific hacks + +-- Sigh, haskeline proper uses stuff in Setup.hs to handle whether +-- or not -liconv is used. We don't use Setup.hs, so we replicate +-- what it does here. We should do this better somehow. + +-- Test whether compiling a c program that links against libiconv needs -liconv. +maybeSetLibiconv :: Verbosity -> BuildInfo -> LocalBuildInfo -> IO () +maybeSetLibiconv verb bi lbi = do + let biWithIconv = addIconv bi + worksWithout <- tryCompile iconv_prog bi lbi verb + if worksWithout + then writeBuildInfo "" + else do + worksWith <- tryCompile iconv_prog biWithIconv lbi verb + if worksWith + then do + writeBuildInfo "iconv" + else fail "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] + +tryCompile :: String -> BuildInfo -> LocalBuildInfo -> Verbosity -> IO Bool +tryCompile program bi lbi verb = flip catchIO processException $ flip catchExit processExit $ do + tempDir <- getTemporaryDirectory + withTempFile tempDir ".c" $ \fname h -> do + hPutStr h program + hClose h + -- TODO take verbosity from the args. + rawSystemProgramStdoutConf verb gccProgram (withPrograms lbi) (fname : args) + return True + where + processException :: IOException -> IO Bool + processException _ = return False + processExit = return . (==ExitSuccess) + -- Mimicing Distribution.Simple.Configure + deps = topologicalOrder (installedPkgs lbi) + args = concat + [ ccOptions bi + , cppOptions bi + , ldOptions bi + -- --extra-include-dirs and --extra-lib-dirs are included + -- in the below fields. + -- Also sometimes a dependency like rts points to a nonstandard + -- include/lib directory where iconv can be found. + , map ("-I" ++) (includeDirs bi ++ concatMap Installed.includeDirs deps) + , map ("-L" ++) (extraLibDirs bi ++ concatMap Installed.libraryDirs deps) + , map ("-l" ++) (extraLibs bi) + ] + +addIconv :: BuildInfo -> BuildInfo +addIconv bi = bi {extraLibs = "iconv" : extraLibs bi} + +iconv_prog :: String +iconv_prog = unlines $ + [ "#include " + , "int main(void) {" + , " iconv_t t = iconv_open(\"UTF-8\", \"UTF-8\");" + , " return 0;" + , "}" + ] + -- 1.7.10.4