# self-extract
A Haskell library that can make an executable self-extracting.
## Usage
### .cabal file
```
...
build-type: Custom
...
custom-setup
setup-depends: base, Cabal, self-extract
...
executable name-of-executable
build-depends: self-extract, ...
...
```
### Setup.hs
Basic:
```
import Codec.SelfExtract.Distribution (bundle)
import Distribution.Simple
main = defaultMainWithHooks simpleUserHooks
{ postBuild = \args bf pd lbi -> do
postBuild simpleUserHooks args bf pd lbi
bundle "name-of-executable" "dir-to-bundle" lbi
}
```
Using the [Path](https://hackage.haskell.org/package/path-0.6.1) library:
```
import Codec.SelfExtract.Distribution (bundle')
import Distribution.Simple
import Path (reldir)
main = defaultMainWithHooks simpleUserHooks
{ postBuild = \args bf pd lbi -> do
postBuild simpleUserHooks args bf pd lbi
bundle' "name-of-executable" [reldir|dir-to-bundle|] lbi
}
```
### Executable file
Basic:
```
import Codec.SelfExtract (extractTo)
main = do
extractTo "dir" -- will extract to $CWD/dir
extractTo "/usr/local/lib"
...
```
Extract to a temporary directory:
```
import Codec.SelfExtract (withExtractToTemp)
import System.Directory (removeDirectory)
main = do
withExtractToTemp $ \tmp -> do
...
```
Using the [Path](https://hackage.haskell.org/package/path-0.6.1) library:
```
import Codec.SelfExtract (extractTo', withExtractToTemp')
import Path (absdir, reldir)
import Path.IO (removeDir)
main = do
extractTo' $ [reldir|dir|] -- will extract to $CWD/dir
extractTo' $ [absdir|/usr/local/lib|]
withExtractToTemp' $ \tmp -> do
...
```
### 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 find the executable from `LocalBuildInfo`'s `buildDir`. It will take the directory
specified and run `tar` on it. It will also get the size of the 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 in `bundle`.
After seeking to the size of the binary, the tar archive can be extracted to the desired directory.