132 lines
4.1 KiB
Haskell
132 lines
4.1 KiB
Haskell
|
import Control.Exception (throw)
|
||
|
import Control.Monad (forM_, when)
|
||
|
import Data.Maybe (isNothing)
|
||
|
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 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
|
||
|
prepDeps (fromFlag $ configVerbosity flags)
|
||
|
pure emptyHookedBuildInfo
|
||
|
--, confHook = \a flags -> confHook simpleUserHooks a flags >>= rsAddDirs
|
||
|
}
|
||
|
|
||
|
execCargo :: Verbosity -> String -> [String] -> IO ()
|
||
|
execCargo verbosity command args = do
|
||
|
cargoPath <-
|
||
|
findProgramOnSearchPath Verbosity.silent 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" []
|
||
|
|
||
|
prepDeps :: Verbosity -> IO ()
|
||
|
prepDeps verbosity = do
|
||
|
ldPath <- lookupEnv "LD_LIBRARY_PATH"
|
||
|
pkgPath <- lookupEnv "PKG_CONFIG_PATH"
|
||
|
if maybe False (matchTest (mkRegex ".*zcash-haskell.*")) ldPath &&
|
||
|
maybe False (matchTest (mkRegex ".*zcash-haskell.*")) pkgPath
|
||
|
then do
|
||
|
execCargo verbosity "cbuild" []
|
||
|
localData <- getXdgDirectory XdgData "zcash-haskell"
|
||
|
createDirectoryIfMissing True localData
|
||
|
dir <- getCurrentDirectory
|
||
|
let rustLibDir =
|
||
|
dir </> rsFolder </> "target/x86_64-unknown-linux-gnu/debug"
|
||
|
copyDir rustLibDir localData
|
||
|
else throw $
|
||
|
userError "Paths not set correctly, please run the 'configure' script."
|
||
|
|
||
|
rsFolder :: FilePath
|
||
|
rsFolder = "zcash-haskell/librustzcash-wrapper"
|
||
|
|
||
|
rsAddDirs :: LocalBuildInfo -> IO LocalBuildInfo
|
||
|
rsAddDirs lbi' = do
|
||
|
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
|
||
|
}
|
||
|
pure $ updateLbi lbi'
|
||
|
|
||
|
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
|