cabal-bundle-clib (empty) → 0.1.0
raw patch · 7 files changed
+215/−0 lines, 7 filesdep +Cabaldep +basedep +bytestringsetup-changed
Dependencies added: Cabal, base, bytestring, directory, filepath, process, temporary, text, time
Files
- CHANGELOG.md +0/−0
- LICENSE +26/−0
- Setup.hs +2/−0
- cabal-bundle-clib.cabal +38/−0
- src/Development/CabalBundleCLib.hs +94/−0
- src/Development/CabalBundleCLib/CMake.hs +32/−0
- src/Development/CabalBundleCLib/Types.hs +23/−0
+ CHANGELOG.md view
+ LICENSE view
@@ -0,0 +1,26 @@+Copyright 2018-2019 Isumi Feng++Redistribution and use in source and binary forms, with or without modification,+are permitted provided that the following conditions are met:++1. Redistributions of source code must retain the above copyright notice, this+list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation and/or+other materials provided with the distribution.++3. Neither the name of the copyright holder nor the names of its contributors+may be used to endorse or promote products derived from this software without+specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ cabal-bundle-clib.cabal view
@@ -0,0 +1,38 @@+cabal-version: 2.4+-- Initial package description 'cabal-bundle-clib.cabal' generated by+-- 'cabal init'. For further documentation, see+-- http://haskell.org/cabal/users-guide/++name: cabal-bundle-clib+version: 0.1.0+synopsis: Bundling C/C++ projects in Cabal package made easy+license: BSD-3-Clause+license-file: LICENSE+author: Isumi Feng+maintainer: contact@zelinf.net+copyright: 2019, Isumi Feng+category: Development+stability: alpha+homepage: https://github.com/isumif/cabal-bundle-clib+bug-reports: https://github.com/isumif/cabal-bundle-clib/issues+description: Please see the [README](https://github.com/isumif/cabal-bundle-clib)+extra-source-files: CHANGELOG.md++library+ hs-source-dirs: src+ default-language: Haskell2010+ ghc-options: -Wall+ exposed-modules:+ Development.CabalBundleCLib+ , Development.CabalBundleCLib.Types+ , Development.CabalBundleCLib.CMake+ build-depends:+ base ^>=4.12.0.0+ , Cabal ^>=2.4.1.0+ , text+ , time+ , temporary+ , directory+ , process+ , filepath+ , bytestring
+ src/Development/CabalBundleCLib.hs view
@@ -0,0 +1,94 @@+module Development.CabalBundleCLib+ ( mainWithCLib+ , module Development.CabalBundleCLib.Types+ ) where++import Data.Time.Clock (getCurrentTime)+import Development.CabalBundleCLib.Types+import qualified Distribution.Compat.Lens as Lens+import qualified Distribution.PackageDescription as Cabal hiding+ (Flag)+import qualified Distribution.Simple as Cabal+import qualified Distribution.Simple.Setup as Cabal+import qualified Distribution.Types.BuildInfo.Lens as CabalLens+import qualified Distribution.Types.Library.Lens as CabalLens+import qualified Distribution.Types.LocalBuildInfo as Cabal+import qualified Distribution.Types.PackageDescription.Lens as CabalLens+import System.Directory (removeFile)+import System.FilePath ((</>))+import System.IO.Temp (writeTempFile)++mainWithCLib :: FilePath -- ^c project root+ -> [String] -- ^bundled libraries+ -> [FilePath] -- ^parent dirs of libraries (relative to build root)+ -> (BuildAction -> BuildDirs -> IO ()) -- ^builder+ -- The three 'FilePath's are source dir, build dir and installation+ -- dir, respectively+ -> IO ()+mainWithCLib cProjRoot bundledLibs bundledLibDirs builder =+ Cabal.defaultMainWithHooks Cabal.simpleUserHooks+ { Cabal.confHook = customConfigure bundledLibs+ , Cabal.postConf = \_ _ _ _ -> pure () -- remove the check for foreign libs+ , Cabal.buildHook = customBuild cProjRoot bundledLibs bundledLibDirs builder+ }++customConfigure :: [String]+ -> (Cabal.GenericPackageDescription, Cabal.HookedBuildInfo)+ -> Cabal.ConfigFlags+ -> IO Cabal.LocalBuildInfo+customConfigure bundledLibs gpkgDesc configFlags = do+ lbi <- Cabal.confHook Cabal.simpleUserHooks gpkgDesc configFlags+ let localPkgDescr = Cabal.localPkgDescr lbi+ localPkgDescr' = Lens.over CabalLens.library updateLibrary localPkgDescr+ pure $ lbi { Cabal.localPkgDescr = localPkgDescr' }+ where+ updateLibrary :: Maybe Cabal.Library -> Maybe Cabal.Library+ updateLibrary = fmap $ Lens.over CabalLens.libBuildInfo updateBuildInfo+ updateBuildInfo :: Cabal.BuildInfo -> Cabal.BuildInfo+ updateBuildInfo bi = bi+ { Cabal.extraLibs = bundledLibs ++ Cabal.extraLibs bi+ , Cabal.extraBundledLibs = bundledLibs ++ Cabal.extraBundledLibs bi+ }++customBuild :: FilePath -- ^c project root+ -> [String] -- ^bundled libs+ -> [FilePath] -- bundled lib dirs+ -> (BuildAction -> BuildDirs -> IO ())+ -> Cabal.PackageDescription+ -> Cabal.LocalBuildInfo+ -> Cabal.UserHooks+ -> Cabal.BuildFlags+ -> IO ()+customBuild cProjRoot bundledLibs bundledLibDirs builder packageDesc localBuildInfo userHooks buildFlags = do+ currentTime <- getCurrentTime+ let versionInfo = "const char *clibver = \"" ++ show currentTime ++ "\";\n"+ let buildDir = Cabal.buildDir localBuildInfo+ clibVersionFile <- writeTempFile buildDir "clibver.c" versionInfo+ let updateLibrary :: Cabal.Library -> Cabal.Library+ updateLibrary lib =+ let lib' = Lens.over (CabalLens.libBuildInfo . CabalLens.cSources) (clibVersionFile :) lib+ lib'' = Lens.over (CabalLens.libBuildInfo . CabalLens.extraLibDirs)+ ((fmap (\dir -> buildDir </> dir) bundledLibDirs) ++) lib'+ in Lens.over (CabalLens.libBuildInfo . CabalLens.extraLibs) (bundledLibs ++) lib''+ let packageDesc' = Lens.over CabalLens.library (fmap updateLibrary) packageDesc+ builder+ (BuildActionBuild (getBuildMode localBuildInfo))+ (BuildDirs cProjRoot (buildDir </> "clibbuild") buildDir) -- TODO use some unique build dir name+ simpleBuildHook packageDesc' localBuildInfo userHooks buildFlags+ removeFile clibVersionFile++getBuildMode :: Cabal.LocalBuildInfo -> BuildMode+getBuildMode localBuildInfo =+ case Cabal.configOptimization . Cabal.configFlags $ localBuildInfo of+ Cabal.Flag level ->+ case level of+ Cabal.MaximumOptimisation -> BuildModeRelease+ _ -> BuildModeDebug+ _ -> BuildModeDebug++simpleBuildHook :: Cabal.PackageDescription+ -> Cabal.LocalBuildInfo+ -> Cabal.UserHooks+ -> Cabal.BuildFlags+ -> IO ()+simpleBuildHook = Cabal.buildHook Cabal.simpleUserHooks
+ src/Development/CabalBundleCLib/CMake.hs view
@@ -0,0 +1,32 @@+{-# LANGUAGE RecordWildCards #-}++module Development.CabalBundleCLib.CMake+ ( simpleCMakeBuilder+ ) where++import Development.CabalBundleCLib.Types+import System.Directory (withCurrentDirectory)+import System.FilePath ((</>))+import System.Process (callCommand, callProcess)++simpleCMakeBuilder :: BuildAction -> BuildDirs -> IO ()+simpleCMakeBuilder BuildActionClean BuildDirs{..} =+ withCurrentDirectory buildDirsBuild $+ callProcess "make" ["clean"]+simpleCMakeBuilder (BuildActionBuild mode) BuildDirs{..} = do+ callProcess "cmake" ["-S", buildDirsSource, "-B", buildDirsBuild, (buildModeToFlag mode)]+ callProcess "cmake" ["--build", buildDirsBuild]+ callCommand $ "cp " ++ buildDirsBuild </> "*.a" ++ " " ++ buildDirsInstall++buildModeToFlag :: BuildMode -> String+buildModeToFlag buildMode = "-DCMAKE_BUILD_TYPE=" ++ mode+ where+ mode = case buildMode of+ BuildModeDebug -> "Debug"+ BuildModeRelease -> "Release"++{-+cmake -S $SOURCE_DIR -B $BUILD_DIR+cmake --build $BUILD_DIR+cp $BUILD_DIR/*.a $BUILD_DIR/*.so.* $INSTALL_DIR+-}
+ src/Development/CabalBundleCLib/Types.hs view
@@ -0,0 +1,23 @@+module Development.CabalBundleCLib.Types+ ( BuildAction(..)+ , BuildMode(..)+ , BuildDirs(..)+ , Builder+ ) where++-- |Type for build actions.+data BuildAction =+ BuildActionBuild BuildMode+ | BuildActionClean+ deriving (Show, Eq)++data BuildMode = BuildModeDebug | BuildModeRelease+ deriving (Show, Eq)++data BuildDirs = BuildDirs+ { buildDirsSource :: FilePath+ , buildDirsBuild :: FilePath+ , buildDirsInstall :: FilePath+ } deriving (Show, Eq)++type Builder = BuildAction -> BuildDirs -> IO ()