diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
 # lz4
 
+## 0.1.2.0
+
+  * Add `cross` flag
+  * Fix some stuff for cross-compiling
+
 ## 0.1.1.0
 
   * Export `lZ4VersionString` and `lZ4VersionNumber`
diff --git a/bench/Bench.hs b/bench/Bench.hs
new file mode 100644
--- /dev/null
+++ b/bench/Bench.hs
@@ -0,0 +1,38 @@
+module Main (main) where
+
+import           Codec.Lz4
+import           Criterion.Main
+import qualified Data.ByteString.Lazy as BSL
+import           System.FilePath      ((</>))
+import           System.IO.Temp       (withSystemTempDirectory)
+
+decompressDump :: FilePath -> FilePath -> IO ()
+decompressDump dir fp' =
+    BSL.writeFile (dir </> "dump.tar") =<<
+        (decompress <$> BSL.readFile fp')
+
+compressDump :: FilePath -> FilePath -> IO ()
+compressDump dir fp' =
+    BSL.writeFile (dir </> "dump.tar.lz4") =<<
+        (compress <$> BSL.readFile fp')
+
+main :: IO ()
+main =
+    withSystemTempDirectory "lz4" $ \dir ->
+        defaultMain [ bgroup "decompress/dump"
+                        [ bench "lz4" $ nfIO (decompressDump dir "valgrind-3.15.0.tar.lz4")
+                        , bench "lz4" $ nfIO (decompressDump dir "llvm-9.0.0.src.tar.lz4")
+                        ]
+                    , env lz4Files $ \ ~(v, l) ->
+                      bgroup "decompress"
+                        [ bench "lz4" $ nf decompress v
+                        , bench "lz4" $ nf decompress l
+                        ]
+                    , bgroup "compress/dump"
+                        [ bench "lz4" $ nfIO (compressDump dir "valgrind-3.15.0.tar")
+                        , bench "lz4" $ nfIO (compressDump dir "llvm-9.0.0.src.tar")
+                        ]
+                    ]
+    where lz4Files = (,) <$> valgrindFile <*> llvmFile
+          valgrindFile = BSL.readFile "valgrind-3.15.0.tar.lz4"
+          llvmFile = BSL.readFile "llvm-9.0.0.src.tar.lz4"
diff --git a/lz4-hs.cabal b/lz4-hs.cabal
--- a/lz4-hs.cabal
+++ b/lz4-hs.cabal
@@ -1,6 +1,6 @@
 cabal-version:   1.18
 name:            lz4-hs
-version:         0.1.1.0
+version:         0.1.2.0
 license:         BSD3
 license-file:    LICENSE
 copyright:       Copyright: (c) 2020 Vanessa McHale
@@ -18,27 +18,34 @@
     type:     darcs
     location: https://hub.darcs.net/vmchale/lz4
 
+flag cross
+    description: Set this flag if cross-compiling
+    default:     False
+    manual:      True
+
 library
-    exposed-modules:    Codec.Lz4
-    build-tool-depends: c2hs:c2hs >=0.28.6
+    exposed-modules:  Codec.Lz4
     c-sources:
         cbits/lz4.c
         cbits/lz4frame.c
         cbits/lz4hc.c
         cbits/xxhash.c
 
-    hs-source-dirs:     src
-    other-modules:      Codec.Lz4.Foreign
-    default-language:   Haskell2010
-    include-dirs:       cbits
+    hs-source-dirs:   src
+    other-modules:    Codec.Lz4.Foreign
+    default-language: Haskell2010
+    include-dirs:     cbits
     install-includes:
         cbits/lz4.h cbits/lz4frame.h cbits/lz4hc.h cbits/xxhash.h
 
-    ghc-options:        -Wall
+    ghc-options:      -Wall
     build-depends:
         base >=4.8 && <5,
         bytestring -any
 
+    if !flag(cross)
+        build-tool-depends: c2hs:c2hs >=0.28.6
+
     if impl(ghc >=8.0)
         ghc-options:
             -Wincomplete-uni-patterns -Wincomplete-record-updates
@@ -86,3 +93,28 @@
 
     if impl(ghc >=8.0)
         ghc-options: -Wincomplete-uni-patterns -Wincomplete-record-updates
+
+benchmark lz4-bench
+    type:             exitcode-stdio-1.0
+    main-is:          Bench.hs
+    hs-source-dirs:   bench
+    default-language: Haskell2010
+    ghc-options:      -Wall
+    build-depends:
+        base -any,
+        lz4-hs -any,
+        criterion -any,
+        bytestring -any,
+        temporary -any,
+        filepath -any
+
+    if impl(ghc >=8.0)
+        ghc-options:
+            -Wincomplete-uni-patterns -Wincomplete-record-updates
+            -Wredundant-constraints -Widentities
+
+    if impl(ghc >=8.4)
+        ghc-options: -Wmissing-export-lists
+
+    if impl(ghc >=8.2)
+        ghc-options: -Wcpp-undef
diff --git a/src/Codec/Lz4.hs b/src/Codec/Lz4.hs
--- a/src/Codec/Lz4.hs
+++ b/src/Codec/Lz4.hs
@@ -74,7 +74,7 @@
                             bRead <- peek szPtr
                             bWritten <- peek dSzPtr
                             outBs <- BS.packCStringLen (castPtr d, fromIntegral bWritten)
-                            let remBs = if fromIntegral bRead == sz || res == 0
+                            let remBs = if fromIntegral bRead == sz
                                 then Nothing
                                 else Just (BS.drop (fromIntegral bRead) b)
                             pure (remBs, outBs)
@@ -96,10 +96,10 @@
                 check err
                 ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)
                 dst <- mallocForeignPtrBytes lZ4FHeaderSizeMax
-                res <- withForeignPtr dst $ \d ->
-                    lZ4FCompressBegin ctx d lZ4FHeaderSizeMax nullPtr
-                check res
-                let header = BS.fromForeignPtr dst 0 (fromIntegral res)
+                header <- withForeignPtr dst $ \d -> do
+                    res <- lZ4FCompressBegin ctx d lZ4FHeaderSizeMax nullPtr
+                    check res
+                    BS.packCStringLen (castPtr d, fromIntegral res)
                 pure (ctx, header)
 
           loop :: LzCtxPtr -> [BS.ByteString] -> LazyST.ST s [BS.ByteString]
@@ -113,7 +113,7 @@
             withForeignPtr dst $ \d -> do
                 res <- lZ4FCompressEnd ctx d expectedSz nullPtr
                 check res
-                BS.packCStringLen (d, fromIntegral res)
+                BS.packCStringLen (castPtr d, fromIntegral res)
 
           update :: LzCtxPtr -> BS.ByteString -> LazyST.ST s BS.ByteString
           update ctx b = LazyST.unsafeIOToST $
@@ -123,7 +123,7 @@
                 withForeignPtr dst $ \d -> do
                     res <- lZ4FCompressUpdate ctx d expectedSz buf (fromIntegral sz) nullPtr
                     check res
-                    BS.packCStringLen (d, fromIntegral res)
+                    BS.packCStringLen (castPtr d, fromIntegral res)
 
 {-# NOINLINE compressBlock #-}
 compressBlock :: BS.ByteString -> BS.ByteString
@@ -144,7 +144,7 @@
         withForeignPtr dst $ \d -> do
             bWritten <- cfun buf d (fromIntegral sz) resSz
             when (bWritten == 0) $ error "Compression error"
-            BS.packCStringLen (d, fromIntegral bWritten)
+            pure $ BS.fromForeignPtr (castForeignPtr dst) 0 (fromIntegral bWritten)
 
 {-# NOINLINE decompressBlockSz #-}
 -- | Decompress a block. The size of the uncompressed data must be known.
diff --git a/src/Codec/Lz4/Foreign.chs b/src/Codec/Lz4/Foreign.chs
--- a/src/Codec/Lz4/Foreign.chs
+++ b/src/Codec/Lz4/Foreign.chs
@@ -29,8 +29,9 @@
                          , LzDecompressionCtxPtr
                          ) where
 
+import Data.Coerce (coerce)
 import Foreign.C.String (CString)
-import Foreign.C.Types (CInt, CUInt, CULong)
+import Foreign.C.Types (CInt, CUInt, CSize (..))
 import Foreign.Marshal.Alloc (alloca)
 import Foreign.Ptr (castPtr, Ptr)
 import Foreign.Storable (peek)
@@ -40,6 +41,7 @@
 #include <lz4hc.h>
 
 {# fun pure LZ4_versionNumber as ^ {} -> `CInt' #}
+-- | @since 0.1.1.0
 {# fun pure LZ4_versionString as ^ {} -> `String' #}
 
 {# fun LZ4_compress_default as ^ { `CString', `CString', `CInt' , `CInt' } -> `CInt' #}
@@ -47,7 +49,7 @@
 
 {# fun pure LZ4_compressBound as ^ { `CInt' } -> `CInt' #}
 
-type LZ4FErrorCode = {# type LZ4F_errorCode_t #}
+type LZ4FErrorCode = CSize -- {# type LZ4F_errorCode_t #}
 {# typedef LZ4F_errorCode_t LZ4FErrorCode #}
 
 {# fun pure LZ4F_isError as ^ { `LZ4FErrorCode' } -> `Bool' #}
@@ -68,26 +70,26 @@
 lZ4FHeaderSizeMax :: Integral a => a
 lZ4FHeaderSizeMax = {# const LZ4F_HEADER_SIZE_MAX #}
 
-{# fun LZ4F_compressBegin as ^ { `LzCtxPtr', castPtr `Ptr a', `CULong', `LzPreferencesPtr' } -> `CULong' #}
+{# fun LZ4F_compressBegin as ^ { `LzCtxPtr', castPtr `Ptr a', coerce `CSize', `LzPreferencesPtr' } -> `CSize' coerce #}
 
-{# fun pure LZ4F_compressBound as ^ { `CULong', `LzPreferencesPtr' } -> `CULong' #}
+{# fun pure LZ4F_compressBound as ^ { coerce `CSize', `LzPreferencesPtr' } -> `CSize' coerce #}
 
 data LzCompressOptions
 
 {# pointer *LZ4F_compressOptions_t as LzCompressOptionsPtr -> LzCompressOptions #}
 
-{# fun LZ4F_compressUpdate as ^ 
+{# fun LZ4F_compressUpdate as ^
     { `LzCtxPtr'
     , castPtr `Ptr a'
-    , `CULong'
+    , coerce `CSize'
     , castPtr `Ptr b'
-    , `CULong'
-    , `LzCompressOptionsPtr' 
-    } -> `CULong' 
+    , coerce `CSize'
+    , `LzCompressOptionsPtr'
+    } -> `CSize' coerce
   #}
 
-{# fun LZ4F_compressEnd as ^ 
-    { `LzCtxPtr', castPtr `Ptr a', `CULong', `LzCompressOptionsPtr' } -> `CULong' #}
+{# fun LZ4F_compressEnd as ^
+    { `LzCtxPtr', castPtr `Ptr a', coerce `CSize', `LzCompressOptionsPtr' } -> `CSize' coerce #}
 
 data LzDecompressionCtx
 
@@ -102,18 +104,20 @@
 {# fun LZ4F_decompress as ^
     { `LzDecompressionCtxPtr'
     , castPtr `Ptr a'
-    , id `Ptr CULong'
+    , castPtr `Ptr CSize'
     , castPtr `Ptr b'
-    , id `Ptr CULong'
+    , castPtr `Ptr CSize'
     , `LzDecompressOptionsPtr'
-    } -> `CULong' 
+    } -> `CSize' coerce
   #}
 
+-- | @since 0.1.1.0
 lZ4MaxInputSize :: Integral a => a
 lZ4MaxInputSize = {# const LZ4_MAX_INPUT_SIZE #}
 
-{# fun LZ4_compress_HC as ^ 
+{# fun LZ4_compress_HC as ^
     { `CString', `CString', `CInt', `CInt', `CInt' } -> `CInt' #}
 
+-- | @since 0.1.1.0
 lZ4HCClevelMax :: Integral a => a
 lZ4HCClevelMax = {# const LZ4HC_CLEVEL_MAX #}
