137 lines
4.2 KiB
Haskell
137 lines
4.2 KiB
Haskell
import Control.Exception (throw)
|
|
import Control.Monad (forM_, when)
|
|
import Data.Maybe (fromMaybe)
|
|
import Distribution.PackageDescription
|
|
import Distribution.Simple
|
|
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..), localPkgDescr)
|
|
import Distribution.Simple.PreProcess
|
|
import Distribution.Simple.Program.Find
|
|
( defaultProgramSearchPath
|
|
, findProgramOnSearchPath
|
|
)
|
|
import Distribution.Simple.Setup
|
|
import Distribution.Simple.Utils
|
|
( IODataMode(IODataModeBinary)
|
|
, maybeExit
|
|
, rawSystemStdInOut
|
|
)
|
|
import Distribution.Verbosity (Verbosity)
|
|
import qualified Distribution.Verbosity as Verbosity
|
|
import GHC.Generics
|
|
import System.Directory
|
|
( XdgDirectory(..)
|
|
, copyFile
|
|
, createDirectory
|
|
, createDirectoryIfMissing
|
|
, doesDirectoryExist
|
|
, doesFileExist
|
|
, getCurrentDirectory
|
|
, getDirectoryContents
|
|
, getHomeDirectory
|
|
, getXdgDirectory
|
|
)
|
|
import System.Environment
|
|
import System.FilePath ((</>))
|
|
import Text.Regex
|
|
import Text.Regex.Base
|
|
|
|
main :: IO ()
|
|
main = defaultMainWithHooks hooks
|
|
where
|
|
hooks =
|
|
simpleUserHooks
|
|
{ preConf =
|
|
\_ flags -> do
|
|
rsMake (fromFlag $ configVerbosity flags)
|
|
pure emptyHookedBuildInfo
|
|
, hookedPreProcessors = knownSuffixHandlers
|
|
, confHook = \a flags -> confHook simpleUserHooks a flags >>= rsAddDirs
|
|
, postClean = \_ flags _ _ -> rsClean (fromFlag $ cleanVerbosity flags)
|
|
}
|
|
|
|
rsFolder :: FilePath
|
|
rsFolder = "librustzcash-wrapper"
|
|
|
|
execCargo :: Verbosity -> String -> [String] -> IO ()
|
|
execCargo verbosity command args = do
|
|
cargoPath <-
|
|
findProgramOnSearchPath Verbosity.normal defaultProgramSearchPath "cargo"
|
|
dir <- getCurrentDirectory
|
|
let cargoExec =
|
|
case cargoPath of
|
|
Just (p, _) -> p
|
|
Nothing -> "cargo"
|
|
cargoArgs = command : args
|
|
workingDir = Just (dir </> rsFolder)
|
|
thirdComponent (_, _, c) = c
|
|
maybeExit . fmap thirdComponent $
|
|
rawSystemStdInOut
|
|
verbosity
|
|
cargoExec
|
|
cargoArgs
|
|
workingDir
|
|
Nothing
|
|
Nothing
|
|
IODataModeBinary
|
|
|
|
rsMake :: Verbosity -> IO ()
|
|
rsMake verbosity = do
|
|
execCargo verbosity "cbuild" []
|
|
|
|
rsAddDirs :: LocalBuildInfo -> IO LocalBuildInfo
|
|
rsAddDirs lbi' = do
|
|
localData <- getXdgDirectory XdgData "zcash-haskell"
|
|
createDirectoryIfMissing True localData
|
|
dir <- getCurrentDirectory
|
|
let rustIncludeDir =
|
|
dir </> rsFolder </> "target/x86_64-unknown-linux-gnu/debug"
|
|
rustLibDir = dir </> rsFolder </> "target/x86_64-unknown-linux-gnu/debug"
|
|
updateLbi lbi = lbi {localPkgDescr = updatePkgDescr (localPkgDescr lbi)}
|
|
updatePkgDescr pkgDescr =
|
|
pkgDescr {library = updateLib <$> library pkgDescr}
|
|
updateLib lib = lib {libBuildInfo = updateLibBi (libBuildInfo lib)}
|
|
updateLibBi libBuild =
|
|
libBuild
|
|
{ includeDirs = rustIncludeDir : includeDirs libBuild
|
|
, extraLibDirs = rustLibDir : extraLibDirs libBuild
|
|
}
|
|
copyDir rustLibDir localData
|
|
pure $ updateLbi lbi'
|
|
|
|
rsClean :: Verbosity -> IO ()
|
|
rsClean verbosity = execCargo verbosity "clean" []
|
|
|
|
cabalFlag :: FlagName -> ConfigFlags -> Bool
|
|
cabalFlag name =
|
|
fromMaybe False . lookupFlagAssignment name . configConfigurationsFlags
|
|
|
|
unlessFlagM :: FlagName -> ConfigFlags -> IO () -> IO ()
|
|
unlessFlagM name flags action
|
|
| cabalFlag name flags = pure ()
|
|
| otherwise = action
|
|
|
|
applyUnlessM :: FlagName -> ConfigFlags -> (a -> IO a) -> a -> IO a
|
|
applyUnlessM name flags apply a
|
|
| cabalFlag name flags = pure a
|
|
| otherwise = apply a
|
|
|
|
copyDir :: FilePath -> FilePath -> IO ()
|
|
copyDir src dst = do
|
|
whenM (not <$> doesDirectoryExist src) $
|
|
throw (userError "source does not exist")
|
|
--whenM (doesFileOrDirectoryExist dst) $
|
|
--throw (userError "destination already exists")
|
|
createDirectoryIfMissing True dst
|
|
content <- getDirectoryContents src
|
|
let xs = filter (`notElem` [".", ".."]) content
|
|
forM_ xs $ \name -> do
|
|
let srcPath = src </> name
|
|
let dstPath = dst </> name
|
|
isDirectory <- doesDirectoryExist srcPath
|
|
if isDirectory
|
|
then copyDir srcPath dstPath
|
|
else copyFile srcPath dstPath
|
|
where
|
|
doesFileOrDirectoryExist x = orM [doesDirectoryExist x, doesFileExist x]
|
|
orM xs = or <$> sequence xs
|
|
whenM s r = s >>= flip when r
|