• This repository has been archived on 27/Jul/2024
  • Stars
    star
    180
  • Rank 213,097 (Top 5 %)
  • Language
    Rust
  • License
    BSD 3-Clause "New...
  • Created almost 4 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

write scripts in compiled languages that run in the nix ecosystem, with no separate build step

nix-script

nix-script lets you write quick scripts in compiled languages, transparently compile and cache them, and pull in whatever dependencies you need from the Nix ecosystem.

This README is intended more as a reference, but I also wrote a blog post to explain what this is and why it exists.

Installing

You might have guessed this already, but you can install this package with nix!

Installing to Your Profile

nix-env -if https://github.com/BrianHicks/nix-script/archive/main.tar.gz

This project's CI also pushes Linux and macOS builds to nix-script.cachix.org automatically, meaning cachix add nix-script should set you up to compile fewer things.

Installing with Flakes

Once added as a flake, we provide these attributes in package:

  • nix-script-all (the default package): contains everything below
  • nix-script: only nix-script
  • nix-script-bash: only nix-script-bash, but referencing the correct nix-script
  • nix-script-haskell: only nix-script-haskell, but referencing the correct nix-script

We also provide an overlay, which has all of these.

Installing with Niv

Once added to Niv (niv add BrianHicks/nix-script), you should be able to import sources.nix-script { }; and have the same things described in the flakes section above, except you'll have to explicitly reference things like overlay."${builtins.currentSystem}".

Commands

nix-script

The normal nix-script invocation is controlled using shebang lines (lines starting with #! by default, although you can change it to whatever you like with the --indicator flag.) Starting your file with #!/usr/bin/env nix-script makes these options available:

What? Shebang line Notes
How to compile the script to a binary #!build The command specified here must read from $SRC and write to $OUT
Use all files in the given directory #!buildRoot Must be a parent directory of the script
Specify build-time dependencies #!buildInputs A space-separated list of Nix expressions
Use an alternative interpreter #!interpreter Run this script with the given binary (must be in runtimeInputs)
Specify runtime dependencies #!runtimeInputs This should be a space-separated list of Nix expressions.
Access auxillary files at runtime #!runtimeFiles Make these files available at runtime (at the path given in RUNTIME_FILES_ROOT)

you can also control these options with equivalent command-line flags to nix-script (see the --help output for exact names.)

nix-script also lets your compiled script know where it came from by setting the SCRIPT_FILE environment variable to what you would have gotten in $0 if it was a shell script.

Shell Mode

Building a new version for every change can get a little tiresome while developing. If you want a quicker feedback loop, you can include --shell in your nix-script invocation (e.g. nix-script --shell path/to/script) to drop into a development shell with your build-time and runtime dependencies. This won't run your build command, but it will let you run it yourself, play around in REPLs, etc.

If you are making a wrapper script, you may find the --run flag useful: it allows you to specify what command to run in the shell. If your language ecosystem has some common watcher script, it might be nice to add a special mode to your wrapper for it! (For example, nix-script-haskell has a --ghcid flag for this purpose. See the source for how it's set up!)

Exporting, or How To Grow a Script

In nix-script version 1, it was common to run up against the limits of a single file, whether that meant having namespace issues or simply a single file becoming unwieldy. Getting aroung this commonly meant giving up on all the nice things that nix-script provided (like faster feedback loops and transparent compilation caching) so it was a tough tradeoff.

Nix-script version 2 has two new flags to help with this: --build-root and --export. Once you get to the point in your program's life cycle where you need multiple files, tell nix-script where the project root is with #!buildRoot (or --build-root) and we'll include all the files in that directory during builds. This lets you do things like splitting out your source into multiple files, all of which will be checked when we try to determine whether or not we have a cache hit.

Once even that is not enough, you can include --export in your nix-script invocation to print out the default.nix that we would have used to build your script. If you put that (or any default.nix) inside the directory specified in #!buildRoot, we'll use that instead of generating our own.

Once you get to the point of having a fully-realized directory with a default.nix inside, you've arrived at a "real" derivation, and you can then use any Nix tooling you like to further modify your project.

Parsing Directives

If you are making a wrapper script for a new language, you can also use --build-root to hold package manager files and extremely custom build.nix files. We also provide a --parse flag which will ask nix-script to parse any directives in the script and give them to you as JSON on stdout.

Caution: be aware that the format here is not stable yet and may change in backwards-incompatible ways without a corresponding major version bump in nix-script. If you have any feedback on the data returned by --parse, please open an issue!

nix-script-bash

nix-script-bash exists to let you specify exact versions of your dependencies via Nix. For example:

#!/usr/bin/env nix-script-bash
#!runtimeInputs jq

jq --help

nix-script-haskell

nix-script-haskell is a convenience wrapper for Haskell scripts. In addition to the regular nix-script options, nix-script-haskell lets you specify some Haskell-specific options:

Shebang line Notes Example
#!haskellPackages Haskell packages to build with (you can get a list of available names by running nix-env -qaPA nixpkgs.haskellPackages.) #!haskellPackages text aeson
#!ghcFlags Additional flags to pass to the compiler. #!ghcFlags -threaded

You can get quick compilation feedback with ghcid by running nix-script-haskell --ghcid path/to/your/script.hs.

Controlling nixpkgs version

nix-script will generate derivations that import <nixpkgs> {} by default. That means all you need to do to control which nixpkgs your scripts are built with is to set NIX_PATH, for example to NIX_PATH=nixpkgs=/nix/store/HASHHASHHASH-source. For projects, this is reasonably easy to do in a mkShell (for example by setting NIX_PATH = "nixpkgs=${pkgs.path}",) or by using makeWrapper on nix-script in a custom derivation.

NIX_PATH is included in cache key calculations, so if you change your package set your scripts will automatically be rebuilt the next time you run them.

Climate Action

I want my open-source work to support projects addressing the climate crisis (for example, projects in clean energy, public transit, reforestation, or sustainable agriculture.) If you are working on such a project, and find a bug or missing feature in any of my libraries, please let me know and I will treat your issue as high priority. I'd also be happy to support such projects in other ways, just ask!

License

nix-script is licensed under the BSD 3-Clause license, located at LICENSE.

More Repositories

1

tree-grepper

Like grep, but uses tree-sitter grammars to search
Rust
298
star
2

elm-benchmark

Benchmarking for Elm
Elm
47
star
3

emit

Build graphs to process streams. Now with Celery!
Python
39
star
4

elm-particle

Simple particle system for web apps. Designed for visual flourishes like confetti.
Elm
37
star
5

elm-csv

Decode CSV in the most boring way possible.
Elm
31
star
6

elm-string-graphemes

Do string operations based on graphemes instead of codepoints or bytes.
Elm
24
star
7

Markov-Generator

a simple gibberish / random text generator using a markov chain.
JavaScript
20
star
8

spacemacs-rocks

A tip blog!
CSS
20
star
9

elm-duet

Rust
19
star
10

candy-and-allowances

Candy and Allowances Code
Elm
17
star
11

dotfiles.nix

Nix
16
star
12

django-plop

Django plop middleware
Python
13
star
13

finch

A task manager which implements the Final Version algorithm by Mark Forster
Go
7
star
14

frankenblog

Hugo for SEO + bake-in, Elm for rendering everything else
Elm
6
star
15

elm-trend

generate trend lines for two-dimensional data
Elm
6
star
16

elm-scientists

Code for Duplicating Scientists in Elm: Stop Sharing State blog post
Elm
6
star
17

elm-cli

Creating CLI tools with Elm !!EXPERIMENTAL!!
Elm
6
star
18

elm-json-dynamic-keys

Pies and Cake!
Elm
4
star
19

koalas

Python
4
star
20

elm-commonmark

An Elm implementation of the CommonMark spec
Elm
3
star
21

BrianHicksBlog

Django Blog
Python
3
star
22

spacemin

a ground-up .emacs.d with stolen Spacemacs stuff I like, developed at my own pace, and customized for me.
Emacs Lisp
3
star
23

lwt-docker

Docker image for lwt.sf.net
Shell
2
star
24

elm-guardian

pre-build server for Elm packages
Elixir
2
star
25

tree-db

Rust
2
star
26

bytes.zone

Elm
2
star
27

elm-subreddit-theme

Source for the Elm Subreddit theme
Makefile
2
star
28

probe

Probe lets you ship personal metrics (feelings, energy level, productivity) to external services for analysis.
Python
2
star
29

brianhicks.github.com

JavaScript
2
star
30

similar-sort

Rust
2
star
31

learnhaskell

I'm working through some books learning haskell. This here is a repo for me to document that process.
Haskell
2
star
32

xbar-review-request-status

Format GitHub review requests for use in an xbar script
Rust
2
star
33

erudite

Tail files, and do things with them.
Python
2
star
34

promtop

a quick and dirty `top` for prometheus services
Shell
1
star
35

omnifocus-scripts

JavaScript
1
star
36

minielixir

Miniature Elixir Docker Container
1
star
37

nowjs-multichat-example-coffeescript-haml

NowJS multichat example with coffeescript and haml
CoffeeScript
1
star
38

Portfolio

Brian Hicks' portfolio
Ruby
1
star
39

pt-to-things

export PivotalTracker items to Things
Python
1
star
40

lingo

Prototype language-learning tool
CSS
1
star
41

drinks

1
star
42

elm-edit-playground

Elm
1
star
43

path

Such Elm. So filesystem. Wow.
Elm
1
star
44

autoauth

Automatic Authentication for Django
Python
1
star
45

buildTemplate

a simple javascript string template
JavaScript
1
star
46

property-testing-presentation

Elm
1
star
47

aaron

Syntactic sugar for function composition
1
star
48

uatu

The watcher
Python
1
star
49

elm-infra

Upcoming Elm infrastructure
HCL
1
star
50

ListenUP

Ruby
1
star
51

elm-forbid-import

Rust
1
star
52

tinyobj

a tiny dict -> object mapper
Python
1
star
53

promtree

a quick and dirty `tree` for prometheus services
Shell
1
star
54

should

Should is a todo management program on the command line. It stores todos in plain text. Put it in your dropbox!
Python
1
star
55

funding

Python
1
star
56

elm-json-parser-toy

Elm
1
star
57

this-is-not-my-resume

This is not my Resumé.
1
star
58

nur-packages

Nix packages I'm using which aren't upstream for whatever reason
Nix
1
star
59

elm-list-randori

Randori Output of the St. Louis Elm Group, 2016-11-07
Elm
1
star
60

elm-avl-exploration

AVL trees for Set and Dict in Elm - optimized for reads
Elm
1
star
61

montage

Rust
1
star
62

habitifocus

Sync OmniFocus tasks to Habitica
Go
1
star
63

graft

graft files together. Probably do stuff with 'em too. Who knows.
Haskell
1
star