Just cool ...
Feel the Power of Nix
To build a reproducible env is the Nix's Ultimate Power. You can live without NixOS or not using Home-Manager. But this one is the essential of Nix. This post is to illustrate what you can perform with Nix.
Direnv
Nix †Direnv. These two are so powerful that it could be illegal to use both ð. Direnv grants you seamless environment while Nix guarantees they are reliable and reproducible instantly. My rest blogs are merely snippets and tips to showcase/advertise this combination (all in my dotfiles repo). BTW, direnv can work with conda too!
NodeJS
# Nixpkgs 20.09
# no -g/global install needed! node_modules/.bin is in PATH when in this folder
# { pkgs ? import <nixpkgs> {} }:
{ pkgs ?
import (builtins.fetchTarball {
name = "nixos-20.09";
url = "https://codeload.github.com/NixOS/nixpkgs/tar.gz/20.09";
sha256 = "1wg61h4gndm3vcprdcg7rc4s1v3jkm5xd7lw8r2f67w502y94gcy";
}) {}
}:
pkgs.mkShell {
buildInputs = with pkgs; [
nodejs
yarn
];
shellHook = ''
export PATH="$PWD/node_modules/.bin/:$PATH"
echo "ð nodejs ready!"
'';
MY_ENVIRONMENT_VARIABLE = "dummy";
}
Here usually you pin down to a particular nixpkgs to make sure the reproducibility. Remember npm install -g
? Now it's not allowed and neither good practice. You just install to local node_modules
folder and export the node_modules/.bin
path.
Emscripten
Webassembly? Easy piece:
let
emscriptenPackages.zlib
in
pkgs.mkShell {
buildInputs = with pkgs; [
emscripten
emscriptenPackages.zlib
webfs # webfs -F -p 3000 to serve current folder
];
}
Nixpkgs already has common emscriptenPackages ready but if you can compile your own as shown here.
Rust
let
moz_overlay = import (builtins.fetchTarball https://github.com/mozilla/nixpkgs-mozilla/archive/master.tar.gz);
nixpkgs = import <nixpkgs> { overlays = [ moz_overlay ]; };
ruststable = (nixpkgs.latest.rustChannels.stable.rust.override { extensions = [ "rust-src" "clippy-preview" "rls-preview" "rust-analysis" "rustfmt-preview" ];});
in
with nixpkgs;
mkShell {
buildInputs = [
openssl
pkg-config
nasm
ruststable
rustup
cmake
zlib
];
shellHook = ''
export PATH=$HOME/.cargo/bin:$PATH
'';
}
New and fast evolving lang, you have to overlay nightly pkgs from Mozilla. Relax, nixpkgs master is stable than you thought!
Python
Install pkgs in read-only nix python is impossible. You either use local pip (virtual python env) or manage packages in nix. With nix, you don't need to worry about the native package like cython etc..
...
:
let
pythonEnv = pkgs.python38.withPackages (ps: [
ps.numpy
ps.pytorch
ps.dateutil
]);
in pkgs.mkShell {
buildInputs = with pkgs; [
pythonEnv
libffi
openssl
];
}
If you are dealing with mostly pure py pkgs or has no admin permission, you might consider conda. It's also powerful: before my Nix age, conda is my environment pkgs manager. Another way is to use mach-nix, which can help pack pypi into nix pkgs.
C++
Nix is the out of box C++ dev pkg manager in *nix OS I'd say, since C++ pkgs are mostly low level and OS related. However, nix expression is not as good for incremental build, yet you can integrate with powerful like bazel etc. If you just need some scratch start, here you go:
let
version = "0.1";
in pkgs.mkShell {
name = "my-cpp-app";
src = "./.";
nativeBuildInputs = with pkgs; [ cmake meson ninja ];
# phases: unpackPhase -> configurePhase -> buildPhase -> installPhase
buildInputs = with pkgs; [
boost
poco
];
configurePhase = ''
cmake -G Ninja .
#meson setup builddir
'';
buildPhase = ''
c++ -o main main.cpp -lPocoFoundation -lboost_system
#meson compile
'';
installPhase = ''
mkdir -p $out/bin
cp main $out/bin
#cd builddir && meson compile
'';
enableParallelBuilding = true;
}
These buildPhase will be called in order if you build *.nix file. You can manually revoke them in nix-shell or just make it as Nix derivative and build.
ð§Jdk
TODO:
buildInputs = with pkgs; [ jdk11 ];
shellHook = ''
export JAVA_HOME=${pkgs.jdk11}
PATH="${pkgs.jdk11}/bin:$PATH"
'';
Android
https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/mobile/androidenv/examples/shell.nix Finally, we got some updates from nix community for license issue.
You'll need to accept a bunch of licenses, config.androidenv.accept_licneses = true
only help some core licenses, you need to specify extra licenses
Non-Root
If this bothers you ...
- Namespace
nix-user-chroot
. However, it cannot support tmux reattachment (hope this is tmux fault). - Proot allow tmux to reattach, however, it has limit os support for certain system call which is very hard to find out when it happens.
- Build your own stuff and troubleshooting all on your own.
Namespace is recommended however in Mac it seems to be impossible.