-- | Allow to use cabal configuration (generated via the configure action of cabal).-- Source directories and compilation options will be reused by Shaker.moduleShaker.Cabal.CabalInfo(defaultCabalInput)whereimportShaker.TypeimportShaker.ConfigimportDistribution.Simple.BuildimportDistribution.VerbosityimportDistribution.Simple.Configure(getPersistBuildConfig)importDistribution.Simple.LocalBuildInfo(LocalBuildInfo,localPkgDescr)importDistribution.ModuleNameimportDistribution.PackageDescription(BuildInfo,targetBuildDepends,options,libBuildInfo,library,Library,hsSourceDirs,exposedModules,extensions,Executable,buildInfo,modulePath,executables,exeName)importDynFlags(DynFlags,verbosity,ghcLink,packageFlags,outputFile,hiDir,objectDir,importPaths,PackageFlag(ExposePackage),GhcLink(NoLink))importSystem.FilePath((</>))importSystem.Directory(doesFileExist)importDistribution.Compiler(CompilerFlavor(GHC))importDistribution.Package(Dependency(Dependency),PackageName(PackageName))importData.MaybeimportData.List(nub,isSuffixOf)importControl.Monad-- | Read the build information from cabal and output a shakerInput from itdefaultCabalInput::IOShakerInputdefaultCabalInput=readConf>>=\lbi->generatePreprocessFilelbi>>localBuildInfoToShakerInputlbi>>=checkInvalidMaingeneratePreprocessFile::LocalBuildInfo->IO()generatePreprocessFilelbi=writeAutogenFilesnormal(localPkgDescrlbi)lbireadConf::IOLocalBuildInforeadConf=getPersistBuildConfig"dist"-- | Extract useful information from localBuildInfo to a ShakerInputlocalBuildInfoToShakerInput::LocalBuildInfo->IOShakerInputlocalBuildInfoToShakerInputlbi=dodefInput<-defaultInputInitializedreturndefInput{compileInputs=cplInputs,listenerInput=compileInputsToListenerInputcplInputs}wherecplInputs=localBuildInfoToCompileInputslbicompileInputsToListenerInput::[CompileInput]->ListenerInputcompileInputsToListenerInputcplInputs=defaultListenerInput{fileListenInfo=nub$map(\a->FileListenInfoadefaultExcludedefaultHaskellPatterns)concatSources}whereconcatSources=concatMapcfSourceDirscplInputs-- * Converter to CompileInput-- | Extract informations : Convert executable and library to -- compile inputslocalBuildInfoToCompileInputs::LocalBuildInfo->[CompileInput]localBuildInfoToCompileInputslbi=executableAndLibToCompileInput(librarypkgDescription)(executablespkgDescription)wherepkgDescription=localPkgDescrlbi-- | Dispatch the processing depending of the library contentexecutableAndLibToCompileInput::MaybeLibrary->[Executable]->[CompileInput]executableAndLibToCompileInputNothingexes=mapexecutableToCompileInputexesexecutableAndLibToCompileInput(Justlib)exes=libraryToCompileInputlib:mapexecutableToCompileInputexes-- | Convert a cabal executable to a compileInput-- The target of compilation will the main fileexecutableToCompileInput::Executable->CompileInputexecutableToCompileInputexecutable=defaultCompileInput{cfSourceDirs=mySourceDir,cfDescription="Executable : "++exeNameexecutable,cfCommandLineFlags=getCompileOptionsbldInfo,cfTargetFiles=map(</>modulePathexecutable)mySourceDir,cfDynFlags=toDynFlagsmySourceDir(getLibDependenciesbldInfo)}wherebldInfo=buildInfoexecutablemySourceDir="dist/build/autogen":hsSourceDirsbldInfo-- | Convert a cabal library to a compileInput-- The target of compilation will be all exposed moduleslibraryToCompileInput::Library->CompileInputlibraryToCompileInputlib=defaultCompileInput{cfSourceDirs=mySourceDir,cfDescription="Library : "++showmyModules,cfCommandLineFlags=getCompileOptionsbldInfo,cfTargetFiles=myModules,cfDynFlags=toDynFlagsmySourceDir(getLibDependenciesbldInfo)}wherebldInfo=libBuildInfolibmyModules=mapconvertModuleNameToString$exposedModuleslibmySourceDir="dist/build/autogen":hsSourceDirsbldInfo-- | Create a dynFlags for ghc from a source directory and -- a liste of packagestoDynFlags::[String]->[String]->DynFlags->DynFlagstoDynFlagssourceDirspackagesToExposednFlags=dnFlags{importPaths=nub$oldImportPaths++sourceDirs,outputFile=Just"dist/shakerTarget/Main",objectDir=Just"dist/shakerTarget",hiDir=Just"dist/shakerTarget",verbosity=1,ghcLink=NoLink,packageFlags=nub$mapExposePackagepackagesToExpose++oldPackageFlags}whereoldPackageFlags=packageFlagsdnFlagsoldImportPaths=importPathsdnFlags-- * Helper methodsgetCompileOptions::BuildInfo->[String]getCompileOptionsmyLibBuildInfo=hideAllPackagesOption:ghcOptions++ghcExtensionswhereghcOptions=fromMaybe[]$lookupGHC(optionsmyLibBuildInfo)ghcExtensions=map(\a->"-X"++showa)(extensionsmyLibBuildInfo)hideAllPackagesOption="-hide-all-packages"getLibDependencies::BuildInfo->[String]getLibDependenciesbi=mapgetPackageName$targetBuildDependsbigetPackageName::Dependency->StringgetPackageName(Dependency(PackageNamepn)_)=pnconvertModuleNameToString::ModuleName->StringconvertModuleNameToStringmodName|nullmodArr=""|otherwise=foldr1(\ws->w++'.':s)modArrwheremodArr=componentsmodName-- | Check and filter all invalid main definissioncheckInvalidMain::ShakerInput->IOShakerInputcheckInvalidMainshIn=mapMcheckInvalidMain'(compileInputsshIn)>>=\newCplInp->return$shIn{compileInputs=newCplInp}checkInvalidMain'::CompileInput->IOCompileInputcheckInvalidMain'cplInput|any(".hs"`isSuffixOf`)oldTargets=donewTargets<-filterMdoesFileExistoldTargetsreturncplInput{cfTargetFiles=newTargets}|otherwise=returncplInputwhereoldTargets=cfTargetFilescplInput