Here is a more involved example of downloading a release and then extracting the binary from a .pkg file: https://gist.github.com/J-Swift/364a8b158bf0b603f6e784e454ca...
Here is a more simplified example: https://gist.github.com/mitchellh/c47e3333bb78f57836ba2aa806...
EDIT: to get the sha, unfortunately you have to perform some esoteric command line incantations: https://github.com/NixOS/nix/issues/1880#issuecomment-366615... and https://gist.github.com/boxofrox/d8a3080fbb03f84b7d7a31e102b...
If you don't care about Nixpkgs conventions ("build phases", etc.) then you can use `runCommand` to run arbitrary bash code. It's a function which takes three arguments: a name for the output, a key/value mapping for the environment variables (plus a few some special names), and a string of bash code (usually written between ''two single quotes'').
with import <nixpkgs> {};
runCommand
"my-favourite-program" # A name for the output
{
# A key/value mapping of env vars
myVar = "myValue";
# The 'buildInputs' name is special: for each element 'x', the directory '${x}/bin'
# will be appended to the PATH env var
buildInputs = [ jq gcc ];
}
''
# This is a multi-line string containing arbitrary bash code.
# The output path will be provided via the env var $out so we
# just need to create a file or folder with that path
mkdir -p "$out/bin"
echo "$myVar" > "$out/bin/my-executable"
chmod +x "$out/bin/my-executable"
''
One complication is that (by default) the script will be run in a sandbox, with no network access. We should fetch anything it depends on up-front, using e.g. fetchurl, fetchGit, etc. Here's a more realistic example: with import <nixpkgs> {};
runCommand "foo"
{
release = fetchurl {
url = "http://example.com/foo/foo-1.0.zip";
hash = "sha256-iqZDwWkQA9XMTICEMCt5xDlmfmiIwzpeE3HJLbgbDXs=";
};
buildInputs = [ unzip ];
}
''
unzip "$release"
mkdir -p "$out/bin"
mv foo-1.0/binary "$out/bin/foo"
''The good news is once you learn how, it's basically trivial with crate2nix[0], which can autogenerate nix derivations from rust crates
The thing that Nix, for me, currently fails at is introspection. Every function is a black box and i have no clue what's in it. I have to go dig up files on github to see what it even accepts. It's as if everything is obtuse.
A "simple" LSP/Type system would do wonders for understanding what the function is, what it does, and the inputs/outputs.
.. also i have some difficulty understanding functional "mutation" patterns like how overloads are implemented. But i hope that'll make sense eventually.
NOTE: i also think Flakes are absolutely necessary for Nix. Nix is way less valuable to me without Flakes.
But yeah, it's super frustrating that it's all still hidden behind experimental flags and the official documentation continues to suggest non-flake workflows, though. It's ready for primetime— commit to it please!
Anyone have tutorials they want to share?
1. Nix the language is basically a JSON object. Almost everything is about generating and composing subtrees to build a _really_ big JSON object.
2. `<foo>` means from channel `foo`. This is less relevant now with flakes but that was always extremely confusing syntax to me and when I "got it" it made things way easier.
[1] - https://nixos.org/guides/nix-pills/
[2] - https://www.youtube.com/watch?v=NYyImy-lqaA&list=PLRGI9KQ3_H...
Bottom up, you want to learn the fundamentals of how the Nix language works, and how the basic primitives it offers can be used to build up package definitions, a package manager, and ultimately an entire OS. For this, the Nix Pills are invaluable: https://nixos.org/guides/nix-pills/
Top down, you need goals for some specific things you want to accomplish in the system. For me, this was automated packaging for hundreds of source repos internal to my company, but that's a bit of a crazy case— for a normal person, I'd expect this could be something like "I want to run a webserver with some static assets" or "I want to define and launch a container declaratively", or maybe "I want a reproducible environment to do Python development in, where the reproducibility isn't just tagged versions in a requirements/pyproject file, but also includes the full underlay of everything I'm depending on from the base system.
Whatever the goal is here, you're inevitably going to find your way to override-related tasks, like "okay, I want to upgrade this package" or "I want to add patches to this package" or "I want to change the settings on one of my dependencies", and that's where the extraordinary power of Nix really starts to sink in, when you realise how much can be accomplished with so little, and you try to imagine what accomplishing that under a conventional apt- or dnf-type system would look like.