mirror of
https://github.com/nmattia/snack.git
synced 2024-12-11 11:04:03 +03:00
Update README
This commit is contained in:
parent
8bef714a9a
commit
4a47498e28
224
README.md
224
README.md
@ -3,73 +3,175 @@
|
||||
|
||||
# Snack
|
||||
|
||||
_snack_ is a Haskell build tool.
|
||||
_snack_ is a build tool which
|
||||
|
||||
## Usage
|
||||
|
||||
You need a `snack.nix`:
|
||||
|
||||
``` nix
|
||||
{ pkgs ? import <nixpkgs> {} }: # see #install for instructions
|
||||
pkgs.snack-lib.executable
|
||||
{ src = ./src; # Where you source code is located
|
||||
main = "Main"; # The name of your main module
|
||||
|
||||
# You Haskell dependencies
|
||||
dependencies =
|
||||
[
|
||||
"heterocephalus"
|
||||
"servant"
|
||||
"servant-server"
|
||||
"warp"
|
||||
"unliftio"
|
||||
"uuid"
|
||||
];
|
||||
|
||||
# GHC options
|
||||
ghc-options = [ "-Wall" ];
|
||||
|
||||
# Extra directories to add to your build, by module
|
||||
extra-directories = modName:
|
||||
if modName == "Main" then
|
||||
[ ./pages ]
|
||||
else [];
|
||||
}
|
||||
```
|
||||
|
||||
You can then build with:
|
||||
|
||||
``` shell
|
||||
$ snack build
|
||||
```
|
||||
|
||||
or run with:
|
||||
|
||||
``` shell
|
||||
$ snack run
|
||||
> ...
|
||||
```
|
||||
|
||||
or start an interactive session:
|
||||
``` shell
|
||||
$ snack ghci
|
||||
> ...
|
||||
```
|
||||
|
||||
Currently _snack_ only supports building executables. See the [test
|
||||
suite](./script/test) for examples.
|
||||
* uses Nix to build Haskell projects (HPack and special Nix configuration)
|
||||
* is incremental: running `snack build` will only rebuild the modules that
|
||||
have been modified since the previous build
|
||||
* works in the Nix sandbox
|
||||
* comes with lots of cool Nix features for free: strong reproducibility
|
||||
guarantees, remote caching, remote builds, and more
|
||||
* may improve build performance in some cases, for instance:
|
||||
- all Haskell modules modules are built in parallel
|
||||
- there is a single linking step performed (typically) on a fast tmpfs
|
||||
|
||||
## Install
|
||||
|
||||
The easiest way to install it is to add
|
||||
it to your nix shell:
|
||||
You need [nix][nix]. Then, clone this repo and run:
|
||||
|
||||
``` shell
|
||||
$ nix-env -f ./default.nix -iA snack-exe
|
||||
installing 'linker'
|
||||
```
|
||||
|
||||
The _snack_ executable should now be available:
|
||||
|
||||
``` shell
|
||||
$ snack --help
|
||||
Usage: snack ([-s|--snack-nix PATH] | [-p|--package-yaml PATH]) COMMAND
|
||||
|
||||
Available options:
|
||||
-h,--help Show this help text
|
||||
|
||||
Available commands:
|
||||
build
|
||||
run
|
||||
ghci
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
_snack_ uses HPack for building. If you need more power in your builds, you can
|
||||
also use raw nix. The next sections will give example HPack and Nix
|
||||
configurations for building the following project:
|
||||
|
||||
```shell
|
||||
.
|
||||
├── app
|
||||
│ └── Main.hs
|
||||
└── src
|
||||
└── Lib.hs
|
||||
```
|
||||
|
||||
***src/Lib.hs*** :
|
||||
``` haskell
|
||||
module Lib where
|
||||
|
||||
import Control.Lens
|
||||
import Network.Wreq
|
||||
import Data.Aeson.Lens
|
||||
import Data.Text (Text)
|
||||
|
||||
topReddit :: IO Text
|
||||
topReddit =
|
||||
getWith opts url
|
||||
<&> (^. responseBody
|
||||
. key "data"
|
||||
. key "children"
|
||||
. nth 0
|
||||
. key "data"
|
||||
. key "title"
|
||||
. _String)
|
||||
where
|
||||
url = "https://www.reddit.com/r/haskell/top.json"
|
||||
opts = defaults
|
||||
& param "limit" .~ ["1"]
|
||||
& param "t" .~ ["all"]
|
||||
```
|
||||
|
||||
***app/Main.hs*** :
|
||||
``` haskell
|
||||
module Main where
|
||||
|
||||
import Lib
|
||||
|
||||
main :: IO ()
|
||||
main = topReddit >>= print
|
||||
```
|
||||
|
||||
### HPack
|
||||
|
||||
_snack_ does not purport to support HPack entirely (yet) but merely uses some
|
||||
heuristics that map relatively well to HPack's specification. The
|
||||
aforementioned project could have the following `package.yaml`:
|
||||
|
||||
|
||||
``` yaml
|
||||
name: snack-readme
|
||||
|
||||
dependencies:
|
||||
- lens
|
||||
- wreq
|
||||
|
||||
library:
|
||||
source-dirs: ./src
|
||||
|
||||
executable:
|
||||
main: Main.hs
|
||||
source-dirs: ./app
|
||||
dependencies:
|
||||
- snack-readme
|
||||
|
||||
default-extensions:
|
||||
- OverloadedStrings
|
||||
```
|
||||
|
||||
The project can be run by using the following command:
|
||||
|
||||
``` shell
|
||||
$ snack run --package-yaml ./package.yaml
|
||||
"\"Category Theory for Programmers\" has been finished!"
|
||||
```
|
||||
|
||||
|
||||
You may decide to simply build the project, or even start an interactive
|
||||
session:
|
||||
|
||||
``` shell
|
||||
$ snack build --package-yaml ./package.yaml
|
||||
|
||||
/nix/store/x3ahgw45qja93jrbm2qd3pywfy2zcq9c-hpack-build-json
|
||||
|
||||
$ snack ghci --package-yaml ./package.yaml
|
||||
GHCi, version 8.2.2: http://www.haskell.org/ghc/ :? for help
|
||||
[1 of 2] Compiling Lib ( /home/nicolas/projects/nmattia/snack/tests/readme/src/Lib.hs, interpreted )
|
||||
[2 of 2] Compiling Main ( /home/nicolas/projects/nmattia/snack/tests/readme/app/Main.hs, interpreted )
|
||||
Ok, two modules loaded.
|
||||
*Main>
|
||||
```
|
||||
|
||||
### Nix
|
||||
|
||||
|
||||
Here is the equivalent Nix config :
|
||||
|
||||
``` nix
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
snack = (pkgs.callPackage path/to/snack {}).snack-exe;
|
||||
in pkgs.mkShell
|
||||
{ name = "snack-shell";
|
||||
buildInputs = [ snack ];
|
||||
lib =
|
||||
{ src = ./src;
|
||||
dependencies = [ "wreq" "lens" ];
|
||||
extensions = [ "OverloadedStrings"];
|
||||
};
|
||||
in
|
||||
{ main = "Main";
|
||||
src = ./app;
|
||||
packages = [ lib ];
|
||||
dependencies = [ "wreq" "lens" ];
|
||||
}
|
||||
```
|
||||
|
||||
The same commands can then be used:
|
||||
|
||||
``` shell
|
||||
$ snack --snack-nix ./snack.nix run
|
||||
"\"Category Theory for Programmers\" has been finished!"
|
||||
|
||||
```
|
||||
|
||||
Note that the `--snack-nix` argument can be omitted if a `./snack.nix` file is
|
||||
present. Using a Nix (as opposed to HPack) for building your projects gives you
|
||||
a lot of power and flexibility. For instance see [_snack_'s
|
||||
`snack.nix`](./bin/snack.nix) (yes, snack builds itself!).
|
||||
|
||||
|
||||
[nix]: https://nixos.org/nix/
|
||||
|
@ -94,6 +94,12 @@ pushd tests/hpack
|
||||
./test
|
||||
popd
|
||||
|
||||
banner "Test readme folder"
|
||||
pushd tests/readme
|
||||
echo | snack ghci --package-yaml ./package.yaml
|
||||
snack run --package-yaml ./package.yaml
|
||||
popd
|
||||
|
||||
banner "Test this file's formatting"
|
||||
list=$(shfmt -i 2 -l script/test)
|
||||
if [[ -n "$list" ]]; then
|
||||
|
6
tests/readme/app/Main.hs
Normal file
6
tests/readme/app/Main.hs
Normal file
@ -0,0 +1,6 @@
|
||||
module Main where
|
||||
|
||||
import Lib
|
||||
|
||||
main :: IO ()
|
||||
main = topReddit >>= print
|
17
tests/readme/package.yaml
Normal file
17
tests/readme/package.yaml
Normal file
@ -0,0 +1,17 @@
|
||||
name: snack-readme
|
||||
|
||||
dependencies:
|
||||
- lens
|
||||
- wreq
|
||||
|
||||
library:
|
||||
source-dirs: ./src
|
||||
|
||||
executable:
|
||||
main: Main.hs
|
||||
source-dirs: ./app
|
||||
dependencies:
|
||||
- snack-readme
|
||||
|
||||
default-extensions:
|
||||
- OverloadedStrings
|
12
tests/readme/snack.nix
Normal file
12
tests/readme/snack.nix
Normal file
@ -0,0 +1,12 @@
|
||||
let
|
||||
lib =
|
||||
{ src = ./src;
|
||||
dependencies = [ "wreq" "lens" ];
|
||||
extensions = [ "OverloadedStrings"];
|
||||
};
|
||||
in
|
||||
{ main = "Main";
|
||||
src = ./app;
|
||||
packages = [ lib ];
|
||||
dependencies = [ "wreq" "lens" ];
|
||||
}
|
22
tests/readme/src/Lib.hs
Normal file
22
tests/readme/src/Lib.hs
Normal file
@ -0,0 +1,22 @@
|
||||
module Lib where
|
||||
|
||||
import Control.Lens
|
||||
import Network.Wreq
|
||||
import Data.Aeson.Lens
|
||||
import Data.Text (Text)
|
||||
|
||||
topReddit :: IO Text
|
||||
topReddit =
|
||||
getWith opts url
|
||||
<&> (^. responseBody
|
||||
. key "data"
|
||||
. key "children"
|
||||
. nth 0
|
||||
. key "data"
|
||||
. key "title"
|
||||
. _String)
|
||||
where
|
||||
url = "https://www.reddit.com/r/haskell/top.json"
|
||||
opts = defaults
|
||||
& param "limit" .~ ["1"]
|
||||
& param "t" .~ ["all"]
|
Loading…
Reference in New Issue
Block a user