# self-extract A Haskell library that can make an executable self-extracting. ## Usage ### Basic ``` import Codec.SelfExtract (extractTo) import System.Environment (getArgs) main :: IO () main = do dir <- head <$> getArgs extractTo dir ``` ``` $ stack ghc Example.hs $ mkdir artifacts && touch artifacts/hello.txt artifacts/world.txt $ stack build self-extract && stack exec -- self-bundle ./Example artifacts/ $ ./Example dist $ ls dist hello.txt world.txt ``` ### With Cabal hooks * Add `self-extract` to the Cabal file ``` custom-setup setup-depends: base, Cabal, self-extract executable name-of-executable build-depends: self-extract ``` * Call `bundle` in `Setup.hs` ``` import Codec.SelfExtract (bundle) import Codec.SelfExtract.Distribution (getExe) import Distribution.Simple main = defaultMainWithHooks simpleUserHooks { postCopy = \args cf pd lbi -> do postCopy simpleUserHooks args cf pd lbi exe <- getExe lbi "name-of-executable" bundle exe "dir-to-bundle" } ``` * Call `extractTo` in the executable ``` import Codec.SelfExtract main = do -- will extract to $CWD/dir extractTo "dir" -- will extract to /usr/local/lib extractTo "/usr/local/lib" -- will extract to a temporary directory withExtractToTemp $ \dir -> ... ``` ### Details The above instructions should be a black box, but here is an explanation of the implementation if you need to know the details of how it works. When the executable containing `extractTo` is built, some space will be allocated to contain the size of the binary. `bundle` will take the directory specified and run `tar` on it. It will also get the size of the given executable and write the size into the space allocated by `extractTo`. Then `bundle` will replace the executable with the executable itself concatenated with the tar archive. When `extractTo` is called, it will read the size of the executable that was written with `bundle`. After seeking to the size of the binary, the tar archive can be extracted to the desired directory.