hoppy-runtime 0.8.0 → 0.9.0
raw patch · 4 files changed
+316/−66 lines, 4 filesdep ~Cabaldep ~basedep ~hoppy-generatorsetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: Cabal, base, hoppy-generator
API changes (from Hackage documentation)
- Foreign.Hoppy.Setup: [cppSourcesDir] :: ProjectConfig -> FilePath
- Foreign.Hoppy.Setup: [hsSourcesDir] :: ProjectConfig -> FilePath
+ Foreign.Hoppy.Runtime: fromContentsToGc :: (Deletable c, FromContents c e) => [e] -> IO c
+ Foreign.Hoppy.Setup: GenerateInAutogenDir :: FilePath -> GenerateLocation
+ Foreign.Hoppy.Setup: GenerateInSourcesDir :: FilePath -> GenerateLocation
+ Foreign.Hoppy.Setup: [cppGeneratedSourcesLocation] :: ProjectConfig -> GenerateLocation
+ Foreign.Hoppy.Setup: [cppPackagedSourcesLocation] :: ProjectConfig -> Maybe FilePath
+ Foreign.Hoppy.Setup: combinedMain :: ProjectConfig -> IO ()
+ Foreign.Hoppy.Setup: combinedUserHooks :: ProjectConfig -> UserHooks
+ Foreign.Hoppy.Setup: data GenerateLocation
- Foreign.Hoppy.Setup: ProjectConfig :: Either String Interface -> String -> FilePath -> FilePath -> ProjectConfig
+ Foreign.Hoppy.Setup: ProjectConfig :: Either String Interface -> String -> Maybe FilePath -> GenerateLocation -> ProjectConfig
Files
- Setup.hs +1/−1
- hoppy-runtime.cabal +6/−6
- src/Foreign/Hoppy/Runtime.hs +30/−3
- src/Foreign/Hoppy/Setup.hs +279/−56
Setup.hs view
@@ -1,6 +1,6 @@ -- This file is part of Hoppy. ----- Copyright 2015-2021 Bryan Gardiner <bog@khumba.net>+-- Copyright 2015-2024 Bryan Gardiner <bog@khumba.net> -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License.
hoppy-runtime.cabal view
@@ -1,12 +1,12 @@ name: hoppy-runtime-version: 0.8.0+version: 0.9.0 synopsis: C++ FFI generator - Runtime support-homepage: http://khumba.net/projects/hoppy+homepage: https://khumba.net/projects/hoppy license: Apache-2.0 license-file: LICENSE author: Bryan Gardiner <bog@khumba.net> maintainer: Bryan Gardiner <bog@khumba.net>-copyright: Copyright 2015-2021 Bryan Gardiner+copyright: Copyright 2015-2024 Bryan Gardiner category: Foreign build-type: Simple cabal-version: 1.24@@ -30,12 +30,12 @@ , MultiParamTypeClasses , ScopedTypeVariables build-depends:- base >=4.7 && <5- , Cabal >=1.24 && <3.3+ base >=4.10 && <5+ , Cabal >=1.24 && <3.11 , containers >=0.5 && <0.7 , directory >=1.2 && <1.4 , filepath >=1.3 && <1.5- , hoppy-generator >=0.8 && <0.9+ , hoppy-generator >=0.9 && <0.10 hs-source-dirs: src ghc-options: -W -fwarn-incomplete-patterns -fwarn-unused-do-bind default-language: Haskell2010
src/Foreign/Hoppy/Runtime.hs view
@@ -1,6 +1,6 @@ -- This file is part of Hoppy. ----- Copyright 2015-2021 Bryan Gardiner <bog@khumba.net>+-- Copyright 2015-2024 Bryan Gardiner <bog@khumba.net> -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License.@@ -41,6 +41,7 @@ -- * Containers HasContents (..), FromContents (..),+ fromContentsToGc, -- * Internal CCallback (..), freeHaskellFunPtrFunPtr,@@ -53,6 +54,7 @@ ) where import Control.Exception (Exception, bracket, catch, throwIO)+import Control.Monad ((<=<)) import Data.Int (Int8, Int16, Int32, Int64) import qualified Data.Map as M import Data.Map (Map)@@ -496,13 +498,13 @@ -- | Containers whose contents can be convered to a list. -- -- For a container @Cont@ holding values with C-side type @Foo@ and Haskell-side--- type @Bar@, if the container uses 'Foreign.Hoppy.Generator.Std.ConvertPtr'+-- type @Bar@, if the container uses @Foreign.Hoppy.Generator.Std.ConvertPtr@ -- then the following instances are recommended: -- -- > instance HasContents ContConst FooConst -- > instance HasContents Cont Foo ----- If the container uses 'Foreign.Hoppy.Generator.Std.ConvertValue' then the+-- If the container uses @Foreign.Hoppy.Generator.Std.ConvertValue@ then the -- following instances are recommended: -- -- > instance HasContents ContConst Bar@@ -528,7 +530,32 @@ -- resulting collection to a const pointer. class FromContents c e | c -> e where -- | Creates and returns a new container holding the given elements.+ --+ -- The new container is not managed by the garbage collector. If this is+ -- desired, use 'fromContentsToGc'. fromContents :: [e] -> IO c++-- | Creates and returns a new container holding the given elements, like+-- 'fromContents', and additionally assigns ownership to the garbage collector.+--+-- This function is useful if the object being created is only needed as a+-- temporary for passing into another function, for example:+--+-- > processBlobs $ fromContentsToGc [Blob 1, Blob 2] :: IO BlobContainer+--+-- In this example, @processBlobs@ inspects all of the blobs but does not take+-- ownership of the container, so the Haskell code has to release the container+-- itself. This is done via the garbage collector.+--+-- In a simple case like this, we can also write it a bit more efficiently like+-- below, since we don't truly need the garbage collector:+--+-- > withScopedPtr (fromContents [Blob 1, Blob 2] :: IO BlobContainer) processBlobs+--+-- In this second example, the container is freed immediately when+-- @processBlobs@ returns.+fromContentsToGc :: (Deletable c, FromContents c e) => [e] -> IO c+fromContentsToGc = toGc <=< fromContents -- | Internal type that represents a pointer to a C++ callback object (callback -- impl object, specifically).
src/Foreign/Hoppy/Setup.hs view
@@ -1,6 +1,6 @@ -- This file is part of Hoppy. ----- Copyright 2015-2021 Bryan Gardiner <bog@khumba.net>+-- Copyright 2015-2024 Bryan Gardiner <bog@khumba.net> -- -- Licensed under the Apache License, Version 2.0 (the "License"); -- you may not use this file except in compliance with the License.@@ -37,23 +37,28 @@ -- -- main = -- cppMain $--- ProjectConfig+-- 'ProjectConfig' -- { generatorExecutableName = \"foobar-generator\" -- , cppPackageName = \"foobar-cpp\"--- , cppSourcesDir = \"cpp\"--- , hsSourcesDir = \"src\"+-- , cppPackagedSourcesLocation = Nothing+-- , cppSourcesDir = 'GenerateInAutogenDir' \"\"+-- , hsSourcesDir = 'GenerateInAutogenDir' \"\" -- } -- @ -- -- The Haskell gateway uses the same code, except calling 'hsMain' instead of--- 'cppMain'. This causes C++ sources to be generated in @foobar-cpp\/cpp@ and--- (assuming the Haskell gateway is at @foobar\/@) the Haskell sources to be--- generated in @foobar\/src@.+-- 'cppMain'. This causes all (C++, Haskell) generated sources to be placed in+-- the \"autogen\" directories provided by Cabal, which keeps the source+-- directory clean. See the documentation of the fields of 'ProjectConfig' for+-- more information on how to set up your project's build process. -- -- The gateway packages need to set @build-type: Custom@ in their @.cabal@ files -- to use these setup files. module Foreign.Hoppy.Setup ( ProjectConfig (..),+ GenerateLocation (..),+ combinedMain,+ combinedUserHooks, cppMain, cppUserHooks, hsMain,@@ -62,7 +67,9 @@ import Control.Monad (unless, when) import Data.List (isInfixOf)+import qualified Data.Map as M import Distribution.InstalledPackageInfo (libraryDirs)+import qualified Distribution.ModuleName as ModuleName #if MIN_VERSION_Cabal(2,0,0) import Distribution.Package (mkPackageName) #else@@ -71,10 +78,12 @@ import Distribution.PackageDescription ( HookedBuildInfo, PackageDescription,+ autogenModules, emptyBuildInfo, extraLibDirs, ) import Distribution.Simple (defaultMainWithHooks, simpleUserHooks)+import Distribution.Simple.BuildPaths (autogenComponentModulesDir) import Distribution.Simple.LocalBuildInfo ( LocalBuildInfo, absoluteInstallDirs,@@ -87,6 +96,7 @@ import Distribution.Simple.Program ( runDbProgram, runProgram,+ simpleProgram, ) import Distribution.Simple.Program.Find ( ProgramSearchPathEntry (ProgramSearchPathDefault),@@ -97,7 +107,6 @@ Program, ProgramLocation (FoundOnSystem), simpleConfiguredProgram,- simpleProgram, ) import Distribution.Simple.Setup ( CopyDest (CopyTo, NoCopyDest),@@ -113,6 +122,8 @@ installVerbosity, regInPlace, regVerbosity,+ replVerbosity,+ testVerbosity, ) import Distribution.Simple.UserHooks ( UserHooks (@@ -137,10 +148,16 @@ import Distribution.Simple.Utils (die) #endif import Distribution.Simple.Utils (installOrdinaryFile)+import Distribution.Types.ComponentName (ComponentName (CLibName))+#if MIN_VERSION_Cabal(3,0,0)+import Distribution.Types.LibraryName (LibraryName (LMainLibName))+#endif+import Distribution.Types.LocalBuildInfo (componentNameCLBIs) import Distribution.Verbosity (Verbosity, normal)+import Foreign.Hoppy.Generator.Language.Haskell (getModuleName) import Foreign.Hoppy.Generator.Main (run)-import Foreign.Hoppy.Generator.Spec (Interface)-import System.Directory (createDirectoryIfMissing, doesFileExist)+import Foreign.Hoppy.Generator.Spec (Interface, interfaceModules)+import System.Directory (createDirectoryIfMissing, doesFileExist, getCurrentDirectory) import System.FilePath ((</>), takeDirectory) -- | Configuration parameters for a project using Hoppy.@@ -149,16 +166,51 @@ -- ^ The interface to run the generator with. This result is returned from -- @Foreign.Hoppy.Generator.Spec.interface@ and some may have failed; the -- string is a message indicating the problem.+ , cppPackageName :: String -- ^ The name of the C++ gateway package.- , cppSourcesDir :: FilePath- -- ^ The directory into which to generate C++ sources, under the C++ gateway- -- package root.- , hsSourcesDir :: FilePath- -- ^ The directory into which to generate Haskell sources, under the Haskell- -- gateway package root.+ --+ -- When using separate Cabal packages for the C++ and Haskell gateway+ -- packages, this must be nonempty. When using a single combined gateway+ -- package with 'combinedMain', this must be empty.++ , cppPackagedSourcesLocation :: Maybe FilePath+ -- ^ If the C++ gateway package includes C++ files needed for compliation+ -- (either sources or headers), then this should point to the base directory+ -- holding these files, relative to the root of the project. The project+ -- root itself may be specified with @Just \"\"@.+ --+ -- When present, this is passed to the C++ package's makefile in the+ -- environment variable @HOPPY_CPP_PKG_DIR@. A value of @Just \"\"@ is+ -- passed with @HOPPY_CPP_PKG_DIR@ set to the base directory of the Cabal+ -- package (equivalent to @Just \".\"@).+ --+ -- This is also added automatically as a system include path (i.e. @gcc -I@)+ -- for the C++ compiler when compiling the test program for enum+ -- autodetection.++ , cppGeneratedSourcesLocation :: GenerateLocation+ -- ^ Specifies the directory where C++ sources will be generated.+ --+ -- This is passed to the C++ package's makefile in the environment variable+ -- @HOPPY_CPP_GEN_DIR@. } +-- | Where to generate sources for binding packages.+data GenerateLocation =+ GenerateInAutogenDir FilePath+ -- ^ Generate sources in the package's autogen directory provided by Cabal.+ -- This is preferrable as it keeps the source directory clean.+ --+ -- Sources are generated below the given @FilePath@ if nonempty, otherwise+ -- sources are generated directly in the autogen directory.+ | GenerateInSourcesDir FilePath+ -- ^ Generate sources in the package's root source directory, i.e. the+ -- directory with the @.cabal@ file.+ --+ -- Sources are generated below the given @FilePath@ if nonempty, otherwise+ -- sources are generated directly in the root directory.+ -- | The name of the file we'll use to hold the enum evaluation cache. enumEvalCacheFileName :: FilePath enumEvalCacheFileName = "hoppy-enum-eval-cache"@@ -176,6 +228,89 @@ "Error initializing interface: " ++ errorMsg Right iface -> return iface +-- | A @main@ implementation to be used in the @Setup.hs@ of a single Hoppy+-- binding package that combined both the C++ and Haskell gateway code in one+-- package.+--+-- @combinedMain project = 'defaultMainWithHooks' $ 'combinedUserHooks' project@+combinedMain :: ProjectConfig -> IO ()+combinedMain project = defaultMainWithHooks $ combinedUserHooks project++-- | Cabal user hooks for a combined gateway package. When overriding+-- overriding fields in the result, be sure to call the previous hook.+--+-- The following hooks are defined:+--+-- - 'postConf': Runs the generator to generate C++ and Haskell sources.+combinedUserHooks :: ProjectConfig -> UserHooks+combinedUserHooks project =+ simpleUserHooks+ { postConf = \args flags pkgDesc localBuildInfo -> do+ let verbosity = fromFlagOrDefault normal $ configVerbosity flags++ when (not $ null $ cppPackageName project) $+ die' verbosity $+ "combinedMain expects an empty cppPackageName, found \"" +++ cppPackageName project ++ "\"."++ iface <- case interfaceResult project of+ Left errorMsg ->+ die' verbosity $+ "Error initializing interface: " ++ errorMsg+ Right iface -> return iface++ genCpp project verbosity localBuildInfo iface+ genHs verbosity localBuildInfo iface+ postConf simpleUserHooks args flags pkgDesc localBuildInfo++ , preBuild = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ buildVerbosity flags)+ , preTest = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ testVerbosity flags)+ , preCopy = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ copyVerbosity flags)+ , preInst = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ installVerbosity flags)+ , preReg = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ regVerbosity flags)+ , preRepl = \_ flags -> myHsPreHook project (fromFlagOrDefault normal $ replVerbosity flags)+ }++ where genCpp :: ProjectConfig -> Verbosity -> LocalBuildInfo -> Interface -> IO ()+ genCpp project verbosity localBuildInfo iface = do+ (_, cppGenDir) <-+ getAutogenAndCppGenDir project verbosity localBuildInfo+ cppPackagedSourcesDir <- case cppPackagedSourcesLocation project of+ Nothing -> return ""+ Just subpath -> fmap (</> subpath) getCurrentDirectory+ createDirectoryIfMissing True cppGenDir+ createDirectoryIfMissing True $ buildDir localBuildInfo+ _ <- run [iface]+ [ "--enum-eval-cache-mode", "refresh"+ , "--enum-eval-cache-path", buildDir localBuildInfo </> enumEvalCacheFileName+ , "--gen-cpp", cppGenDir, cppPackagedSourcesDir+ ]+ return ()++ genHs :: Verbosity -> LocalBuildInfo -> Interface -> IO ()+ genHs verbosity localBuildInfo iface = do+ (_, hsGenDir) <- getAutogenAndHsGenDir verbosity localBuildInfo+ createDirectoryIfMissing True hsGenDir+ _ <- run [iface]+ [ "--enum-eval-cache-mode", "must-exist"+ , "--enum-eval-cache-path", buildDir localBuildInfo </> enumEvalCacheFileName+ , "--gen-hs", hsGenDir+ ]+ return ()++ -- See also hsPreHook.+ myHsPreHook :: ProjectConfig -> Verbosity -> IO HookedBuildInfo+ myHsPreHook project verbosity = do+ iface <- getInterface project verbosity+ let moduleNames =+ map (ModuleName.fromString . getModuleName iface) $+ M.elems (interfaceModules iface)++ -- Injected autogenerated modules here works for most commands, however sdist+ -- is not hookable, so autogen-modules should still be written out manually in+ -- your Cabal file! (See Cabal issue #6180.)+ return (Just emptyBuildInfo { autogenModules = moduleNames }, [])+ -- | A @main@ implementation to be used in the @Setup.hs@ of a C++ gateway -- package. --@@ -212,25 +347,25 @@ , buildHook = \pkgDesc localBuildInfo hooks flags -> do buildHook simpleUserHooks pkgDesc localBuildInfo hooks flags let verbosity = fromFlagOrDefault normal $ buildVerbosity flags- cppBuild verbosity localBuildInfo+ cppBuild project verbosity localBuildInfo , copyHook = \pkgDesc localBuildInfo hooks flags -> do copyHook simpleUserHooks pkgDesc localBuildInfo hooks flags let verbosity = fromFlagOrDefault normal $ copyVerbosity flags dest = fromFlagOrDefault NoCopyDest $ copyDest flags- cppInstall verbosity pkgDesc localBuildInfo dest+ cppInstall project verbosity pkgDesc localBuildInfo dest , instHook = \pkgDesc localBuildInfo hooks flags -> do instHook simpleUserHooks pkgDesc localBuildInfo hooks flags let verbosity = fromFlagOrDefault normal $ installVerbosity flags dest = maybe NoCopyDest CopyTo $ flagToMaybe $ installDistPref flags- cppInstall verbosity pkgDesc localBuildInfo dest+ cppInstall project verbosity pkgDesc localBuildInfo dest , regHook = \pkgDesc localBuildInfo hooks flags -> do regHook simpleUserHooks pkgDesc localBuildInfo hooks flags let verbosity = fromFlagOrDefault normal $ regVerbosity flags- cppRegister verbosity localBuildInfo flags+ cppRegister project verbosity localBuildInfo flags , cleanHook = \pkgDesc z hooks flags -> do cleanHook simpleUserHooks pkgDesc z hooks flags@@ -241,17 +376,79 @@ makeProgram :: Program makeProgram = simpleProgram "make" +defaultLibComponentName :: ComponentName+defaultLibComponentName =+#if MIN_VERSION_Cabal(3,0,0)+ CLibName LMainLibName+#else+ CLibName+#endif++-- | Locates the autogen directory for the library component.+getAutogenDir :: Verbosity -> LocalBuildInfo -> IO FilePath+getAutogenDir verbosity localBuildInfo = do+ let libCLBIs = componentNameCLBIs localBuildInfo defaultLibComponentName+#if MIN_VERSION_Cabal(2,0,0)+ dieFn = die' verbosity+#else+ dieFn = die+#endif++ case libCLBIs of+ [libCLBI] -> return $ autogenComponentModulesDir localBuildInfo libCLBI+ _ ->+ -- TODO Show interface name, and "C++" or "Haskell"?+ dieFn $ concat+ ["Expected one library ComponentLocalBuildInfo, found ",+ show $ length libCLBIs, "."]++getAutogenAndGenDir :: GenerateLocation+ -> Verbosity+ -> LocalBuildInfo+ -> IO (FilePath, FilePath)+getAutogenAndGenDir genLoc verbosity localBuildInfo = do+ autogenDir <- getAutogenDir verbosity localBuildInfo+ case genLoc of+ GenerateInAutogenDir subpath ->+ return (autogenDir, autogenDir </> subpath)+ GenerateInSourcesDir subpath -> do+ curDir <- getCurrentDirectory+ return (autogenDir, curDir </> subpath)++getAutogenAndCppGenDir :: ProjectConfig -> Verbosity -> LocalBuildInfo -> IO (FilePath, FilePath)+getAutogenAndCppGenDir project verbosity localBuildInfo =+ getAutogenAndGenDir (cppGeneratedSourcesLocation project) verbosity localBuildInfo++getAutogenAndHsGenDir :: Verbosity -> LocalBuildInfo -> IO (FilePath, FilePath)+getAutogenAndHsGenDir verbosity localBuildInfo =+ getAutogenAndGenDir (GenerateInAutogenDir "") verbosity localBuildInfo++getCppDirEnvVars :: ProjectConfig -> Verbosity -> LocalBuildInfo -> IO [String]+getCppDirEnvVars project verbosity localBuildInfo = do+ (autogenDir, cppGenDir) <- getAutogenAndCppGenDir project verbosity localBuildInfo+ return $+ [ "HOPPY_AUTOGEN_DIR=" ++ autogenDir+ , "HOPPY_CPP_GEN_DIR=" ++ cppGenDir+ ] +++ (case cppPackagedSourcesLocation project of+ Just "" -> ["HOPPY_CPP_PKG_DIR=."]+ Just subpath -> ["HOPPY_CPP_PKG_DIR=" ++ subpath]+ Nothing -> [])+ cppConfigure :: ProjectConfig -> Verbosity -> LocalBuildInfo -> IO () cppConfigure project verbosity localBuildInfo = do -- Invoke the generator to create C++ code.- let sourcesDir = cppSourcesDir project+ (_, cppGenDir) <- getAutogenAndCppGenDir project verbosity localBuildInfo+ cppPackagedSourcesDir <- case cppPackagedSourcesLocation project of+ Nothing -> return ""+ Just subpath -> fmap (</> subpath) getCurrentDirectory iface <- getInterface project verbosity- createDirectoryIfMissing True sourcesDir+ createDirectoryIfMissing True cppGenDir createDirectoryIfMissing True $ buildDir localBuildInfo _ <- run [iface] [ "--enum-eval-cache-mode", "refresh" , "--enum-eval-cache-path", buildDir localBuildInfo </> enumEvalCacheFileName- , "--gen-cpp", sourcesDir+ , "--gen-cpp", cppGenDir, cppPackagedSourcesDir ] -- When there is a configure script, then run it.@@ -267,8 +464,8 @@ then Just $ simpleConfiguredProgram "configure" $ FoundOnSystem "./configure" else Nothing -cppBuild :: Verbosity -> LocalBuildInfo -> IO ()-cppBuild verbosity localBuildInfo = do+cppBuild :: ProjectConfig -> Verbosity -> LocalBuildInfo -> IO ()+cppBuild project verbosity localBuildInfo = do hasMakefile <- doesFileExist "Makefile" unless hasMakefile $ #if MIN_VERSION_Cabal(2,0,0)@@ -277,11 +474,19 @@ die #endif "No Makefile found."++ cppDirEnvVars <- getCppDirEnvVars project verbosity localBuildInfo+ let programDb = withPrograms localBuildInfo- runDbProgram verbosity makeProgram programDb []+ runDbProgram verbosity makeProgram programDb cppDirEnvVars -cppInstall :: Verbosity -> PackageDescription -> LocalBuildInfo -> CopyDest -> IO ()-cppInstall verbosity pkgDesc localBuildInfo dest = do+cppInstall :: ProjectConfig+ -> Verbosity+ -> PackageDescription+ -> LocalBuildInfo+ -> CopyDest+ -> IO ()+cppInstall project verbosity pkgDesc localBuildInfo dest = do hasMakefile <- doesFileExist "Makefile" unless hasMakefile $ #if MIN_VERSION_Cabal(2,0,0)@@ -293,7 +498,9 @@ let programDb = withPrograms localBuildInfo libDir = libdir $ absoluteInstallDirs pkgDesc localBuildInfo dest createDirectoryIfMissing True libDir- runDbProgram verbosity makeProgram programDb ["install", "libdir=" ++ libDir]+ cppDirEnvVars <- getCppDirEnvVars project verbosity localBuildInfo+ runDbProgram verbosity makeProgram programDb $+ ["install", "libdir=" ++ libDir] ++ cppDirEnvVars -- We're doing an old-style install, so copy the enum eval cache file from the -- build directory to the library directory where the Haskell side of the@@ -305,8 +512,8 @@ enumEvalCacheFilePath (libDir </> enumEvalCacheFileName) -cppRegister :: Verbosity -> LocalBuildInfo -> RegisterFlags -> IO ()-cppRegister verbosity localBuildInfo flags = do+cppRegister :: ProjectConfig -> Verbosity -> LocalBuildInfo -> RegisterFlags -> IO ()+cppRegister project verbosity localBuildInfo flags = do hasMakefile <- doesFileExist "Makefile" unless hasMakefile $ #if MIN_VERSION_Cabal(2,0,0)@@ -319,12 +526,25 @@ let programDb = withPrograms localBuildInfo libDir = buildDir localBuildInfo createDirectoryIfMissing True libDir- runDbProgram verbosity makeProgram programDb ["install", "libdir=" ++ libDir]+ cppDirEnvVars <- getCppDirEnvVars project verbosity localBuildInfo+ runDbProgram verbosity makeProgram programDb $+ ["install", "libdir=" ++ libDir] ++ cppDirEnvVars cppClean :: ProjectConfig -> Verbosity -> IO () cppClean project verbosity = do iface <- getInterface project verbosity- _ <- run [iface] ["--clean-cpp", cppSourcesDir project]+ -- We can remove generated sources if we wrote them to the source directory.+ -- We don't have access to the autogen directory from this hook though.+ -- Although, Cabal ought to remove the autogen directory already when+ -- cleaning...+ case cppGeneratedSourcesLocation project of+ GenerateInAutogenDir _ -> return ()+ GenerateInSourcesDir subpath -> do+ cppPackagedSourcesDir <- case cppPackagedSourcesLocation project of+ Nothing -> return ""+ Just subpath -> fmap (</> subpath) getCurrentDirectory+ _ <- run [iface] ["--clean-cpp", subpath, cppPackagedSourcesDir]+ return () hasMakefile <- doesFileExist "Makefile" unless hasMakefile $@@ -335,7 +555,7 @@ #endif "No Makefile found." make <- findSystemProgram verbosity "make"- runProgram verbosity make ["clean"]+ runProgram verbosity make ["clean"] -- No Hoppy directories passed in here! findSystemProgram :: Verbosity -> FilePath -> IO ConfiguredProgram findSystemProgram verbosity basename = do@@ -383,17 +603,12 @@ let verbosity = fromFlagOrDefault normal $ configVerbosity flags hsConfigure project verbosity localBuildInfo - , preBuild = \_ _ -> addLibDir- , preTest = \_ _ -> addLibDir- , preCopy = \_ _ -> addLibDir -- Not sure if necessary, but doesn't hurt.- , preInst = \_ _ -> addLibDir -- Not sure if necessary, but doesn't hurt.- , preReg = \_ _ -> addLibDir -- Necessary.- , preRepl = \_ _ -> addLibDir -- Necessary.-- , cleanHook = \pkgDesc z hooks flags -> do- cleanHook simpleUserHooks pkgDesc z hooks flags- let verbosity = fromFlagOrDefault normal $ cleanVerbosity flags- hsClean project verbosity+ , preBuild = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ buildVerbosity flags)+ , preTest = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ testVerbosity flags)+ , preCopy = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ copyVerbosity flags)+ , preInst = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ installVerbosity flags)+ , preReg = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ regVerbosity flags)+ , preRepl = \_ flags -> hsPreHook project (fromFlagOrDefault normal $ replVerbosity flags) } hsCppLibDirFile :: FilePath@@ -444,22 +659,30 @@ writeFile hsCppLibDirFile libDir generateSources iface libDir = do- let sourcesDir = hsSourcesDir project- createDirectoryIfMissing True sourcesDir+ (_, hsGenDir) <- getAutogenAndHsGenDir verbosity localBuildInfo+ createDirectoryIfMissing True hsGenDir _ <- run [iface] [ "--enum-eval-cache-mode", "must-exist" , "--enum-eval-cache-path", libDir </> enumEvalCacheFileName- , "--gen-hs", sourcesDir+ , "--gen-hs", hsGenDir ] return () -addLibDir :: IO HookedBuildInfo-addLibDir = do+-- See also myHsPreHook.+hsPreHook :: ProjectConfig -> Verbosity -> IO HookedBuildInfo+hsPreHook project verbosity = do+ iface <- getInterface project verbosity+ let moduleNames =+ map (ModuleName.fromString . getModuleName iface) $+ M.elems (interfaceModules iface)+ libDir <- readFile hsCppLibDirFile- return (Just emptyBuildInfo {extraLibDirs = [libDir]}, []) -hsClean :: ProjectConfig -> Verbosity -> IO ()-hsClean project verbosity = do- iface <- getInterface project verbosity- _ <- run [iface] ["--clean-hs", hsSourcesDir project]- return ()+ -- Injected autogenerated modules here works for most commands, however sdist+ -- is not hookable, so autogen-modules should still be written out manually in+ -- your Cabal file! (See Cabal issue #6180.)+ return (Just emptyBuildInfo+ { autogenModules = moduleNames+ , extraLibDirs = [libDir]+ }+ , [])