-- Setup.hs
import Control.Exception (bracket)
import Control.Monad (filterM, forM_)
import Data.List (nub)
import Data.Maybe (catMaybes, isJust, listToMaybe)
import Distribution.PackageDescription (
GenericPackageDescription (..),
PackageDescription (..),
extraLibDirs,
libBuildInfo,
library,
package,
)
import Distribution.Simple
import Distribution.Simple.Compiler (compilerInfo)
import Distribution.Simple.InstallDirs (absoluteInstallDirs, dynlibdir, libdir)
import Distribution.Simple.LocalBuildInfo (LocalBuildInfo (..), localUnitId)
import Distribution.Simple.Setup (configExtraLibDirs, configVerbosity, copyDest, defaultCopyFlags, fromFlag)
import Distribution.Simple.Utils (copyFileVerbose, createDirectoryIfMissingVerbose, createTempDirectory, info)
import Distribution.Verbosity (Verbosity)
import System.Directory (
doesDirectoryExist,
doesFileExist,
findFile,
getCurrentDirectory,
getTemporaryDirectory,
removeDirectoryRecursive,
)
import System.Environment (lookupEnv)
import System.FilePath ((</>), splitSearchPath)
import System.Process (callProcess)
main :: IO ()
main =
defaultMainWithHooks
simpleUserHooks
{ preConf = \args flags -> do
ensureDuckDBAvailable (fromFlag (configVerbosity flags))
preConf simpleUserHooks args flags
}
systemLibraryCandidates :: [FilePath]
systemLibraryCandidates =
[ "libduckdb.so"
, "libduckdb.so.1"
, "libduckdb.so.1.4"
, "libduckdb.so.1.4.0"
, "libduckdb.so.1.4.1"
]
ensureDuckDBAvailable :: Verbosity -> IO ()
ensureDuckDBAvailable verb = do
available <- systemDuckDBAvailable
if available
then info verb "libduckdb found"
else error "libduckdb not found, please install libduckdb (available at https://duckdb.org/install/)"
systemDuckDBAvailable :: IO Bool
systemDuckDBAvailable = do
header <- findDuckDBHeader
lib <- findDuckDBLibrary
pure (isJust header && isJust lib)
findDuckDBHeader :: IO (Maybe FilePath)
findDuckDBHeader = do
paths <- headerSearchPaths
findFile paths "duckdb.h"
findDuckDBLibrary :: IO (Maybe FilePath)
findDuckDBLibrary = do
paths <- librarySearchPaths
listToMaybe . catMaybes <$> mapM (findFile paths) systemLibraryCandidates
headerSearchPaths :: IO [FilePath]
headerSearchPaths = do
envPaths <- gatherEnvPaths ["C_INCLUDE_PATH", "CPATH", "INCLUDE"]
let defaults =
[ "/usr/include"
, "/usr/local/include"
, "/usr/include/x86_64-linux-gnu"
, "/usr/include/aarch64-linux-gnu"
, "/opt/homebrew/include"
, "/opt/local/include"
]
pure (nub (envPaths ++ defaults))
librarySearchPaths :: IO [FilePath]
librarySearchPaths = do
envPaths <- gatherEnvPaths ["LIBRARY_PATH", "LD_LIBRARY_PATH", "DYLD_LIBRARY_PATH", "LIB"]
let defaults =
[ "/usr/lib"
, "/usr/local/lib"
, "/usr/lib64"
, "/usr/local/lib64"
, "/usr/lib/x86_64-linux-gnu"
, "/usr/lib/aarch64-linux-gnu"
, "/opt/homebrew/lib"
, "/opt/local/lib"
]
pure (nub (envPaths ++ defaults))
gatherEnvPaths :: [String] -> IO [FilePath]
gatherEnvPaths names = do
vals <- mapM lookupEnv names
let paths = concatMap splitSearchPath (catMaybes vals)
pure (filter (not . null) paths)