zoovisitor 0.2.5.1 → 0.2.6.1
raw patch · 8 files changed
+304/−82 lines, 8 filesdep ~asyncdep ~bytestringdep ~hspecPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: async, bytestring, hspec, uuid
API changes (from Hackage documentation)
+ ZooKeeper: StdErrLogStream :: StdLogStream
+ ZooKeeper: StdOutLogStream :: StdLogStream
+ ZooKeeper: closeFileLogStream :: FileLogStream -> IO ()
+ ZooKeeper: data FileLogStream
+ ZooKeeper: data StdLogStream
+ ZooKeeper: openFileLogStream :: CBytes -> CBytes -> IO FileLogStream
+ ZooKeeper: withZooSetFileLogStream :: CBytes -> CBytes -> IO a -> IO a
+ ZooKeeper: zooSetStdLogStream :: StdLogStream -> IO ()
+ ZooKeeper.Types: pattern ZooLogSilence :: ZooLogLevel
+ ZooKeeper.Types: pattern ZooNotconnectedState :: ZooState
+ ZooKeeper.Types: pattern ZooReadonlyState :: ZooState
Files
- cbits/hs_zk.c +41/−4
- src/ZooKeeper.hs +97/−4
- src/ZooKeeper/Internal/FFI.hsc +26/−4
- src/ZooKeeper/Internal/Types.hsc +93/−61
- src/ZooKeeper/Internal/Utils.hs +1/−1
- src/ZooKeeper/Types.hs +3/−0
- test/Spec.hs +1/−0
- zoovisitor.cabal +42/−8
cbits/hs_zk.c view
@@ -390,6 +390,18 @@ } // ----------------------------------------------------------------------------++void hs_zoo_set_std_log_stream(int s) {+ if (s == 1) {+ zoo_set_log_stream(stdout);+ } else if (s == 2) {+ zoo_set_log_stream(stderr);+ } else {+ fprintf(stderr, "hs_zoo_set_std_log_stream: invalid %d\n", s);+ }+}++// ---------------------------------------------------------------------------- // Helpers const stat_t* dup_stat(const stat_t* old_stat) {@@ -399,7 +411,7 @@ } const string_vector_t* dup_string_vector(const string_vector_t* old_strings) {- int count = old_strings->count;+ int32_t count = old_strings->count; if (count < 0) { fprintf(stderr, "dup_string_vector error: count %d\n", count); return NULL;@@ -407,7 +419,7 @@ string_vector_t* new_strings = (string_vector_t*)malloc(sizeof(string_vector_t)); char** vals = malloc(count * sizeof(char*));- for (int i = 0; i < count; ++i) {+ for (int32_t i = 0; i < count; ++i) { vals[i] = strdup(old_strings->data[i]); } new_strings->count = count;@@ -415,15 +427,28 @@ return new_strings; } +void free_string_vector(string_vector_t* strings) {+ if (strings == NULL || strings->data == NULL) {+ return;+ }++ for (int32_t i = 0; i < strings->count; ++i) {+ free(strings->data[i]);+ }+ free(strings->data);+ strings->data = NULL;+ free(strings);+}+ const acl_vector_t* dup_acl_vector(const acl_vector_t* old_acls) {- int count = old_acls->count;+ int32_t count = old_acls->count; if (count < 0) { fprintf(stderr, "dup_acl_vector error: count %d\n", count); return NULL; } acl_t* data = (acl_t*)malloc(count * sizeof(acl_t)); acl_t* old_data = old_acls->data;- for (int i = 0; i < count; ++i) {+ for (int32_t i = 0; i < count; ++i) { data[i].perms = old_data[i].perms; data[i].id.scheme = strdup(old_data[i].id.scheme); data[i].id.id = strdup(old_data[i].id.id);@@ -433,4 +458,16 @@ new_acls->count = count; new_acls->data = data; return new_acls;+}++void free_acl_vector(acl_vector_t* acls) {+ if (acls == NULL || acls->data == NULL) {+ return;+ }+ for (int32_t i = 0; i < acls->count; ++i) {+ free(acls->data[i].id.id);+ free(acls->data[i].id.scheme);+ }+ free(acls->data);+ free(acls); }
src/ZooKeeper.hs view
@@ -1,11 +1,16 @@ module ZooKeeper ( I.zooVersion- , I.zooSetDebugLevel , zookeeperResInit , U.withResource , U.Resource + , I.zooSetDebugLevel+ , StdLogStream (..)+ , zooSetStdLogStream+ , FileLogStream+ , withZooSetFileLogStream+ , zooCreate , zooCreateIfMissing , zooSet@@ -34,16 +39,18 @@ , zooRecvTimeout , isUnrecoverable - -- * Internal function (should NOT be used)+ -- * Internal function , zookeeperInit , zookeeperClose+ , openFileLogStream+ , closeFileLogStream ) where -import Control.Exception (catch)+import Control.Exception (bracket, catch, throwIO) import Control.Monad (void, when, zipWithM, (<=<)) import Data.Bifunctor (first) import Data.Maybe (fromMaybe)-import Foreign.C (CInt)+import Foreign.C (CFile, CInt) import Foreign.Ptr (FunPtr, Ptr, freeHaskellFunPtr, nullFunPtr, nullPtr, plusPtr) import GHC.Stack (HasCallStack)@@ -747,3 +754,89 @@ -- value may change after a server re-connect. zooRecvTimeout :: T.ZHandle -> IO CInt zooRecvTimeout = I.c_zoo_recv_timeout++data StdLogStream = StdOutLogStream | StdErrLogStream++newtype FileLogStream = FileLogStream (Ptr CFile)++zooSetStdLogStream :: StdLogStream -> IO ()+zooSetStdLogStream StdOutLogStream = I.hs_zoo_set_std_log_stream 1+zooSetStdLogStream StdErrLogStream = I.hs_zoo_set_std_log_stream 2++-- | Sets the file to be used by the library for logging.+--+-- The file will be closed after the computation you run, and the LogStream+-- will be set to defaut stderr.+--+-- > let res = zookeeperResInit "127.0.0.1:2181" Nothing 5000 Nothing 0+-- > withZooSetFileLogStream "/tmp/zk.log" "a+" $ do+-- > withResource res $ \zh -> do+-- > undefined+withZooSetFileLogStream+ :: CBytes+ -- ^ File name, see 'openFileLogStream'+ -> CBytes+ -- ^ Mode, see 'openFileLogStream'+ -> IO a+ -- ^ Computation to run in-between+ -> IO a+withZooSetFileLogStream filename mode = bracket acquire release . const+ where+ acquire = do+ new@(FileLogStream new') <- openFileLogStream filename mode+ I.c_zoo_set_log_stream new'+ pure new+ -- FIXME: If zookeeper export the get LogStream api, then I can set back+ -- to the original LogStream but the stderr.+ release s = I.hs_zoo_set_std_log_stream 2 >> closeFileLogStream s++-- | Open the file by filename using the given mode.+--+-- The operation may fail with IOError if open filed.+--+-- Also see: <https://man7.org/linux/man-pages/man3/fopen.3.html>+openFileLogStream+ :: CBytes+ -- ^ File name+ -> CBytes+ -- ^ Mode+ --+ -- A string beginning with one of the following sequences:+ --+ -- r Open text file for reading. The stream is positioned at+ -- the beginning of the file.+ --+ -- r+ Open for reading and writing. The stream is positioned at+ -- the beginning of the file.+ --+ -- w Truncate file to zero length or create text file for+ -- writing. The stream is positioned at the beginning of the+ -- file.+ --+ -- w+ Open for reading and writing. The file is created if it+ -- does not exist, otherwise it is truncated. The stream is+ -- positioned at the beginning of the file.+ --+ -- a Open for appending (writing at end of file). The file is+ -- created if it does not exist. The stream is positioned at+ -- the end of the file.+ --+ -- a+ Open for reading and appending (writing at end of file).+ -- The file is created if it does not exist. Output is+ -- always appended to the end of the file. POSIX is silent+ -- on what the initial read position is when using this mode.+ -- For glibc, the initial file position for reading is at the+ -- beginning of the file, but for Android/BSD/MacOS, the+ -- initial file position for reading is at the end of the+ -- file.+ -> IO FileLogStream+openFileLogStream filename mode =+ CBytes.withCBytesUnsafe filename $ \filename' ->+ CBytes.withCBytesUnsafe mode $ \mode' -> do+ cfilep <- I.c_fopen filename' mode'+ if (cfilep == nullPtr)+ then throwIO $ userError ("Open file " <> CBytes.unpack filename <> " failed!")+ else pure $ FileLogStream cfilep++closeFileLogStream :: FileLogStream -> IO ()+closeFileLogStream (FileLogStream p) = I.c_fflush p >> void (I.c_fclose p)
src/ZooKeeper/Internal/FFI.hsc view
@@ -7,8 +7,7 @@ import Control.Concurrent import Control.Exception import Control.Monad (void)-import Data.Version (Version, makeVersion,- parseVersion)+import Data.Version (Version, makeVersion) import Data.Word import Foreign.C import Foreign.ForeignPtr@@ -16,7 +15,6 @@ import Foreign.StablePtr import GHC.Conc import GHC.Stack (HasCallStack)-import Text.ParserCombinators.ReadP (readP_to_S) import qualified Z.Data.CBytes as CBytes import Z.Foreign @@ -25,18 +23,25 @@ #include "hs_zk.h" +#ifndef ZOO_MAJOR_VERSION+import Data.Version (parseVersion)+import Text.ParserCombinators.ReadP (readP_to_S)+#endif+ ------------------------------------------------------------------------------- zooVersion :: Version #ifdef ZOO_MAJOR_VERSION+-- For zookeeper-3.4 zooVersion = makeVersion [ (#const ZOO_MAJOR_VERSION) , (#const ZOO_MINOR_VERSION) , (#const ZOO_PATCH_VERSION) ] #else+-- For zookeeper-3.6+ zooVersion = case readP_to_S parseVersion (#const_str ZOO_VERSION) of [_, _, (r, _)] -> r- otherwise -> makeVersion [0, 0, 0] -- unsupported+ _otherwise -> makeVersion [0, 0, 0] -- unsupported #endif foreign import ccall unsafe "hs_zk.h &logLevel"@@ -46,6 +51,12 @@ foreign import ccall unsafe "hs_zk.h zoo_set_debug_level" zooSetDebugLevel :: ZooLogLevel -> IO () +foreign import capi unsafe "zookeeper/zookeeper.h zoo_set_log_stream"+ c_zoo_set_log_stream :: Ptr CFile -> IO ()++foreign import ccall unsafe "hs_zoo_set_std_log_stream"+ hs_zoo_set_std_log_stream :: CInt -> IO ()+ foreign import ccall "wrapper" mkCWatcherFnPtr :: CWatcherFn -> IO (FunPtr CWatcherFn) @@ -234,6 +245,17 @@ foreign import ccall unsafe "zookeeper.h is_unrecoverable" c_is_unrecoverable :: ZHandle -> IO CInt++-------------------------------------------------------------------------------++foreign import capi unsafe "stdio.h fopen"+ c_fopen :: BA## Word8 -> BA## Word8 -> IO (Ptr CFile)++foreign import capi unsafe "stdio.h fclose"+ c_fclose :: Ptr CFile -> IO CInt++foreign import capi unsafe "stdio.h fflush"+ c_fflush :: Ptr CFile -> IO CInt ------------------------------------------------------------------------------- -- Helpers
src/ZooKeeper/Internal/Types.hsc view
@@ -3,7 +3,7 @@ module ZooKeeper.Internal.Types where -import Control.Exception (bracket_)+import Control.Exception (finally) import Control.Monad (forM) import Data.ByteString.Short (ShortByteString) import qualified Data.ByteString.Short as BShort (packCStringLen)@@ -64,6 +64,10 @@ pattern ZooLogInfo = ZooLogLevel (#const ZOO_LOG_LEVEL_INFO) pattern ZooLogDebug = ZooLogLevel (#const ZOO_LOG_LEVEL_DEBUG) +-- | Disable logging+pattern ZooLogSilence :: ZooLogLevel+pattern ZooLogSilence = ZooLogLevel 0+ ------------------------------------------------------------------------------- -- | ACL permissions.@@ -111,29 +115,38 @@ { aclPerms :: [ZooPerm] , aclIdScheme :: CBytes , aclId :: CBytes- } deriving Show+ } deriving (Show, Eq) -{-# INLINE sizeOfZooAcl #-} sizeOfZooAcl :: Int sizeOfZooAcl = (#size acl_t)+{-# INLINE sizeOfZooAcl #-} -peekZooAcl :: Ptr ZooAcl -> IO ZooAcl-peekZooAcl ptr = do- perms <- toZooPerms <$> (#peek acl_t, perms) ptr- scheme_ptr <- (#peek acl_t, id.scheme) ptr- id_ptr <- (#peek acl_t, id.id) ptr- scheme <- CBytes.fromCString scheme_ptr <* free scheme_ptr- acl_id <- CBytes.fromCString id_ptr <* free id_ptr+newtype AclVector = AclVector (Ptr ())+ deriving (Show, Eq)++peekAclVector :: AclVector -> IO [ZooAcl]+peekAclVector p@(AclVector ptr) = flip finally (free_acl_vector p) $ do+ count <- fromIntegral @Int32 <$> (#peek acl_vector_t, count) ptr+ data_ptr <- (#peek acl_vector_t, data) ptr+ forM [0..count-1] $ peekAclVectorIdx data_ptr++peekAclVectorIdx :: Ptr ZooAcl -> Int -> IO ZooAcl+peekAclVectorIdx ptr offset = do+ let ptr' = ptr `plusPtr` (offset * sizeOfZooAcl)+ perms <- toZooPerms <$> (#peek acl_t, perms) ptr'+ scheme_ptr <- (#peek acl_t, id.scheme) ptr'+ id_ptr <- (#peek acl_t, id.id) ptr'+ scheme <- CBytes.fromCString scheme_ptr+ acl_id <- CBytes.fromCString id_ptr return $ ZooAcl perms scheme acl_id -- TODO unsafeAllocaZooAcl :: ZooAcl -> IO Z.ByteArray unsafeAllocaZooAcl = undefined --- FIXME: consider this--- data AclVector = AclVector (Ptr ()) | AclList [ZooAcl]-newtype AclVector = AclVector (Ptr ())- deriving (Show, Eq)+-- TODO+fromAclList :: [ZooAcl] -> IO AclVector+fromAclList = undefined -- | This is a completely open ACL foreign import ccall unsafe "hs_zk.h &ZOO_OPEN_ACL_UNSAFE"@@ -147,17 +160,8 @@ foreign import ccall unsafe "hs_zk.h &ZOO_CREATOR_ALL_ACL" zooCreatorAllAcl :: AclVector -toAclList :: AclVector -> IO [ZooAcl]-toAclList (AclVector ptr) = do- count <- fromIntegral @Int32 <$> (#peek acl_vector_t, count) ptr- data_ptr <- (#peek acl_vector_t, data) ptr- forM [0..count-1] $ \idx -> do- let data_ptr' = data_ptr `plusPtr` (idx * sizeOfZooAcl)- peekZooAcl data_ptr'---- TODO-fromAclList :: [ZooAcl] -> IO AclVector-fromAclList = undefined+foreign import ccall unsafe "free_acl_vector"+ free_acl_vector :: AclVector -> IO () ------------------------------------------------------------------------------- @@ -193,12 +197,14 @@ deriving newtype (Text.Print) instance Show ZooState where- show ZooExpiredSession = "ExpiredSession"- show ZooAuthFailed = "AuthFailed"- show ZooConnectingState = "ConnectingState"- show ZooAssociatingState = "AssociatingState"- show ZooConnectedState = "ConnectedState"- show (ZooState x) = "ZooState " <> show x+ show ZooExpiredSession = "ExpiredSession"+ show ZooAuthFailed = "AuthFailed"+ show ZooConnectingState = "ConnectingState"+ show ZooAssociatingState = "AssociatingState"+ show ZooConnectedState = "ConnectedState"+ show ZooReadonlyState = "ReadonlyState"+ show ZooNotconnectedState = "NotconnectedState"+ show (ZooState x) = "ZooState " <> show x pattern ZooExpiredSession, ZooAuthFailed@@ -209,12 +215,29 @@ pattern ZooAssociatingState = ZooState (#const ZOO_ASSOCIATING_STATE) pattern ZooConnectedState = ZooState (#const ZOO_CONNECTED_STATE) --- TODO--- pattern ZOO_READONLY_STATE :: ZooState--- pattern ZOO_READONLY_STATE = ZooState (#const ZOO_READONLY_STATE)--- pattern ZOO_NOTCONNECTED_STATE :: ZooState--- pattern ZOO_NOTCONNECTED_STATE = ZooState (#const ZOO_NOTCONNECTED_STATE)+-- This a trick to determine whether the C library expose the following apis.+--+-- ZOO_VERSION was introduced by ZOOKEEPER-3635 (3.6.0-pre). Also version after+-- 3.6 exports the following states.+#ifdef ZOO_VERSION +pattern ZooReadonlyState :: ZooState+pattern ZooReadonlyState = ZooState (#const ZOO_READONLY_STATE)++pattern ZooNotconnectedState :: ZooState+pattern ZooNotconnectedState = ZooState (#const ZOO_NOTCONNECTED_STATE)++#else+-- Hardcode for zookeeper-3.4++pattern ZooReadonlyState :: ZooState+pattern ZooReadonlyState = ZooState 5++pattern ZooNotconnectedState :: ZooState+pattern ZooNotconnectedState = ZooState 999++#endif+ ------------------------------------------------------------------------------- -- | Watch Types@@ -280,32 +303,35 @@ newtype CreateMode = CreateMode { unCreateMode :: CInt } deriving (Show, Eq, Storable) --- TODO: The following C constants (such as ZOO_PERSISTENT, ZOO_PERSISTENT_SEQUENTIAL--- and ZOO_EPTHMERAL_SEQUENTIAL) are not defined on clients <= 3.4.x. However,--- they can be used by passing an integer directly.------ The hard-coded ones will be replaced with the following patterns which use--- C constants when the library only support clients >= 3.5.x.----pattern ZooPersistent :: CreateMode---pattern ZooPersistent = CreateMode (#const ZOO_PERSISTENT)------pattern ZooPersistentSequential :: CreateMode---pattern ZooPersistentSequential = CreateMode (#const ZOO_PERSISTENT_SEQUENTIAL)------pattern ZooEphemeralSequential :: CreateMode---pattern ZooEphemeralSequential = CreateMode (#const ZOO_EPHEMERAL_SEQUENTIAL)------pattern ZooContainer :: CreateMode---pattern ZooContainer = CreateMode (#const ZOO_CONTAINER)+-- This a trick to determine whether the C library expose the following apis. -----pattern ZooPersistentWithTTL :: CreateMode---pattern ZooPersistentWithTTL = CreateMode (#const ZOO_PERSISTENT_WITH_TTL)+-- ZOO_VERSION was introduced by ZOOKEEPER-3635 (3.6.0-pre). -----pattern ZooPersistentSequentialWithTTL :: CreateMode---pattern ZooPersistentSequentialWithTTL = CreateMode (#const ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL)+-- The following C constants (such as ZOO_PERSISTENT, ZOO_PERSISTENT_SEQUENTIAL+-- and ZOO_EPTHMERAL_SEQUENTIAL) are not defined on clients <= 3.4.x.+#ifdef ZOO_VERSION pattern ZooPersistent :: CreateMode+pattern ZooPersistent = CreateMode (#const ZOO_PERSISTENT)++pattern ZooPersistentSequential :: CreateMode+pattern ZooPersistentSequential = CreateMode (#const ZOO_PERSISTENT_SEQUENTIAL)++pattern ZooEphemeralSequential :: CreateMode+pattern ZooEphemeralSequential = CreateMode (#const ZOO_EPHEMERAL_SEQUENTIAL)++pattern ZooContainer :: CreateMode+pattern ZooContainer = CreateMode (#const ZOO_CONTAINER)++pattern ZooPersistentWithTTL :: CreateMode+pattern ZooPersistentWithTTL = CreateMode (#const ZOO_PERSISTENT_WITH_TTL)++pattern ZooPersistentSequentialWithTTL :: CreateMode+pattern ZooPersistentSequentialWithTTL = CreateMode (#const ZOO_PERSISTENT_SEQUENTIAL_WITH_TTL)++#else++pattern ZooPersistent :: CreateMode pattern ZooPersistent = CreateMode 0 pattern ZooPersistentSequential :: CreateMode@@ -323,6 +349,8 @@ pattern ZooPersistentSequentialWithTTL :: CreateMode pattern ZooPersistentSequentialWithTTL = CreateMode 6 +#endif+ -- | The znode will be deleted upon the client's disconnect. pattern ZooEphemeral :: CreateMode pattern ZooEphemeral = CreateMode (#const ZOO_EPHEMERAL)@@ -367,8 +395,9 @@ newtype StringVector = StringVector { unStrVec :: [CBytes] } deriving Show +-- Peek a StringVector from point and then free the pointer peekStringVector :: Ptr StringVector -> IO StringVector-peekStringVector ptr = bracket_ (return ()) (free ptr) $ do+peekStringVector ptr = flip finally (free_string_vector ptr) $ do -- NOTE: Int32 is necessary, since count is int32_t in c count <- fromIntegral @Int32 <$> (#peek string_vector_t, count) ptr StringVector <$> forM [0..count-1] (peekStringVectorIdx ptr)@@ -377,8 +406,11 @@ peekStringVectorIdx ptr offset = do ptr' <- (#peek string_vector_t, data) ptr data_ptr <- peek $ ptr' `plusPtr` (offset * (sizeOf ptr'))- CBytes.fromCString data_ptr <* free data_ptr+ CBytes.fromCString data_ptr -- this will do a copy +foreign import ccall unsafe "free_string_vector"+ free_string_vector :: Ptr StringVector -> IO ()+ ------------------------------------------------------------------------------- -- Callback datas @@ -492,7 +524,7 @@ csize = (#size hs_acl_completion_t) peekRet ptr = (#peek hs_acl_completion_t, rc) ptr peekData ptr = do- acls <- toAclList . AclVector =<< (#peek hs_acl_completion_t, acl) ptr+ acls <- peekAclVector . AclVector =<< (#peek hs_acl_completion_t, acl) ptr stat_ptr <- (#peek hs_acl_completion_t, stat) ptr stat <- peekStat stat_ptr return $ AclCompletion acls stat
src/ZooKeeper/Internal/Utils.hs view
@@ -1,6 +1,6 @@ module ZooKeeper.Internal.Utils ( -- * Resource management- Resource(..)+ Resource (..) , initResource , initResource_ , withResource
src/ZooKeeper/Types.hs view
@@ -39,6 +39,8 @@ , pattern I.ZooConnectingState , pattern I.ZooAssociatingState , pattern I.ZooConnectedState+ , pattern I.ZooReadonlyState+ , pattern I.ZooNotconnectedState , I.CreateMode , pattern I.ZooPersistent@@ -55,6 +57,7 @@ , pattern I.ZooLogWarn , pattern I.ZooLogInfo , pattern I.ZooLogDebug+ , pattern I.ZooLogSilence , I.ZooPerm , pattern I.ZooPermRead
test/Spec.hs view
@@ -38,6 +38,7 @@ opSpec zh = do describe "ZooKeeper.zooVersion" $ do it "version should be 3.4.* - 3.8.*" $ do+ putStrLn $ "Tested with zooVersion: " <> show zooVersion zooVersion `shouldSatisfy` (>= makeVersion [3, 4, 0]) zooVersion `shouldSatisfy` (<= makeVersion [3, 8, 0])
zoovisitor.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: zoovisitor-version: 0.2.5.1+version: 0.2.6.1 synopsis: A haskell binding to Apache Zookeeper C library(mt) using Haskell Z project. @@ -12,7 +12,7 @@ copyright: Copyright (c) author: mu maintainer: mu@laxcat.xyz-tested-with: GHC ==8.10.7 || ==9.0.2 || ==9.2.8+tested-with: GHC ==8.10.7 || ==9.0.2 || ==9.2.8 || ==9.4.5 category: Database homepage: https://github.com/ZHaskell/zoovisitor bug-reports: https://github.com/ZHaskell/zoovisitor/issues@@ -27,6 +27,26 @@ type: git location: https://github.com/ZHaskell/zoovisitor +-- XXX: Hackage requires 'cabal-version' must be at most 3.0.+-- But the flag 'zoovisitor_enable_asan' use 'hsc2hs-options' requres >= 3.6.+-- flag zoovisitor_enable_asan+-- default: False+-- description:+-- Enable AddressSanitizer. This is only for local debug usage.+-- Also, do not forget to set cabal-version to 3.6 manually.++-- XXX: require cabal-version >= 3.6+-- Tricky options to link static archive, see: https://github.com/haskell/cabal/issues/4677+-- common link-asan+-- if os(osx)+-- ghc-options: "-optl-Wl,-lasan"+--+-- if !os(osx)+-- ghc-options:+-- -pgml g++ "-optl-Wl,--allow-multiple-definition"+-- "-optl-Wl,--whole-archive" "-optl-Wl,-Bstatic" "-optl-Wl,-lasan"+-- "-optl-Wl,-Bdynamic" "-optl-Wl,--no-whole-archive"+ library hs-source-dirs: src exposed-modules:@@ -45,15 +65,25 @@ build-depends: , base >=4.12 && <5- , bytestring >=0.10.10.0+ , bytestring >=0.10.10.0 && <0.13 , exceptions ^>=0.10- , Z-Data >=0.7.2 && <1.5 || ^>=2.0+ , Z-Data >=0.7.2 && <1.5 || ^>=2.0 includes: hs_zk.h c-sources: cbits/hs_zk.c include-dirs: include /usr/local/include build-tool-depends: hsc2hs:hsc2hs extra-libraries: zookeeper_mt++ -- XXX: require cabal-version >= 3.6+ -- if flag(zoovisitor_enable_asan)+ -- cc-options:+ -- -fsanitize=address -fno-omit-frame-pointer -static-libasan++ -- hsc2hs-options:+ -- "--cflag=-fsanitize=address" "--lflag=-fsanitize=address"+ -- "--cflag=-static-libasan" "--lflag=-static-libasan"+ default-language: Haskell2010 default-extensions: BangPatterns@@ -80,14 +110,18 @@ -Wincomplete-uni-patterns -Wpartial-fields -Wredundant-constraints test-suite zoovisitor-test+ -- XXX: require cabal-version >= 3.6+ -- if flag(zoovisitor_enable_asan)+ -- import: link-asan+ type: exitcode-stdio-1.0 main-is: Spec.hs hs-source-dirs: test build-depends:- , async- , base >=4.12 && <5- , hspec- , uuid+ , async ^>=2.2+ , base >=4.12 && <5+ , hspec ^>=2.11+ , uuid ^>=1.3 , Z-Data , zoovisitor