import Control.Monad import Data.List (isPrefixOf, (\\)) import Data.Map (Map) import qualified Data.Map as Map import Distribution.Simple import Distribution.Simple.Program import Distribution.Simple.Setup import Distribution.Simple.LocalBuildInfo import Distribution.PackageDescription import System.Environment import System.SetEnv import Distribution.System -- define these selectively in C files (where _not_ using HsFFI.h), -- rather than universally in the ccOptions, because HsFFI.h currently defines them -- without checking they're already defined and so causes warnings. uncheckedHsFFIDefines = ["__STDC_LIMIT_MACROS"] llvmProgram = simpleProgram "llvm-config" main = do let (ldLibraryPathVar, ldLibraryPathSep) = case buildOS of OSX -> ("DYLD_LIBRARY_PATH",":") _ -> ("LD_LIBRARY_PATH",":") addToLdLibraryPath s = do v <- lookupEnv ldLibraryPathVar setEnv ldLibraryPathVar (s ++ maybe "" (ldLibraryPathSep ++) v) getLLVMConfig configFlags = do let verbosity = fromFlag $ configVerbosity configFlags -- preconfigure the configuration-generating program "llvm-config" programDb <- configureProgram verbosity llvmProgram . userSpecifyPaths (configProgramPaths configFlags) . userSpecifyArgss (configProgramArgs configFlags) $ configPrograms configFlags let llvmConfig :: [String] -> IO String llvmConfig = getDbProgramOutput verbosity llvmProgram programDb return llvmConfig addLLVMToLdLibraryPath configFlags = do llvmConfig <- getLLVMConfig configFlags [libDir] <- liftM lines $ llvmConfig ["--libdir"] addToLdLibraryPath libDir defaultMainWithHooks simpleUserHooks { hookedPrograms = [ llvmProgram ], confHook = \(genericPackageDescription, hookedBuildInfo) configFlags -> do llvmConfig <- getLLVMConfig configFlags cppflags <- llvmConfig ["--cppflags"] let useCppFlags = (filter ("-D" `isPrefixOf`) $ words cppflags) \\ (map ("-D"++) uncheckedHsFFIDefines) includeDirs <- liftM lines $ llvmConfig ["--includedir"] libDirs@[libDir] <- liftM lines $ llvmConfig ["--libdir"] let genericPackageDescription' = genericPackageDescription { condLibrary = do libraryCondTree <- condLibrary genericPackageDescription return libraryCondTree { condTreeData = let library = condTreeData libraryCondTree in library { libBuildInfo = let buildInfo = libBuildInfo library in buildInfo { ccOptions = ccOptions buildInfo ++ useCppFlags } } } } configFlags' = configFlags { configExtraLibDirs = libDirs ++ configExtraLibDirs configFlags, configExtraIncludeDirs = includeDirs ++ configExtraIncludeDirs configFlags } addLLVMToLdLibraryPath configFlags' confHook simpleUserHooks (genericPackageDescription', hookedBuildInfo) configFlags', buildHook = \packageDescription localBuildInfo userHooks buildFlags -> do addLLVMToLdLibraryPath (configFlags localBuildInfo) buildHook simpleUserHooks packageDescription localBuildInfo userHooks buildFlags, testHook = \packageDescription localBuildInfo userHooks testFlags -> do addLLVMToLdLibraryPath (configFlags localBuildInfo) testHook simpleUserHooks packageDescription localBuildInfo userHooks testFlags }