# 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.