From b6f7f5ba90afedef562b04e685ebb1269433f6e0 Mon Sep 17 00:00:00 2001 From: Brandon Lucas Date: Tue, 14 Jul 2026 19:27:29 -0400 Subject: [PATCH] Add Nix Flake + direnv Restores and updates the old flake.nix to add a post-Zig migration devshell. Also adds direnv for automatic env loading upon entering the directory. Since Zig compiler has no stable release yet, this uses roc-overlay to always use latest nightly roc compiler, so the user doesn't have to continuously download nightly. Adds checks to scripts/build.py to not download the rust toolchain on every build if it already exists, and to allow interop with Nix users and backward compatibility for non Nix users. Also updates CONTRIBUTING.md with new Nix usage section. docs: note required Nix features --- .envrc | 1 + .gitignore | 1 - CONTRIBUTING.md | 29 +++++++++++++++ flake.lock | 89 +++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 78 +++++++++++++++++++++++++++++++++++++++ rust-toolchain.toml | 2 +- scripts/build.py | 24 ++++++++++++ 7 files changed, 222 insertions(+), 2 deletions(-) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 51f08051..06a6806c 100644 --- a/.gitignore +++ b/.gitignore @@ -14,7 +14,6 @@ target generated-docs generated-docs-* .direnv -.envrc *.rs.bk *.o *.so diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d5df55d..9a568cd4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -7,6 +7,35 @@ For local work, use any recent `roc` on `PATH`, or download the latest archive for your operating system from the [`roc-lang/nightlies` releases](https://github.com/roc-lang/nightlies/releases/latest). +## Nix Development Environment + +With Nix's `nix-command` and `flakes` features enabled, the flake provides Roc +nightly, the Rust toolchain and cross-compilation standard libraries, Zig, +Python, and the documentation preview server on supported Linux and macOS +systems. Enter it with: + +```sh +nix develop +``` + +To load the shell automatically, install [`direnv`](https://direnv.net/) and +hook it into your shell. The checked-in `.envrc` uses direnv's `use flake`; +install [`nix-direnv`](https://github.com/nix-community/nix-direnv) as well if +your direnv version does not provide it. Then simply approve `.envrc` once: + +```sh +direnv allow +``` + +The lock file pins every flake input, including the Roc nightly supplied by +[`roc-overlay`](https://github.com/thebrandonlucas/roc-overlay). CI deliberately +tracks the current nightly, while local updates are explicit. Update the pinned +compiler with: + +```sh +nix flake update roc-overlay +``` + ## Code of Conduct We are committed to providing a friendly, safe, and welcoming environment for all. See the [Code of Conduct](https://github.com/roc-lang/roc/blob/main/CODE_OF_CONDUCT.md) for details. diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..1cb17e8b --- /dev/null +++ b/flake.lock @@ -0,0 +1,89 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1784007870, + "narHash": "sha256-djcLt/JJphyNt4eDY9XTly+/WbCK5lqWq9lSgCmJkkQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "18b9261cb3294b6d2a06d03f96872827b8fe2698", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-x86-darwin": { + "locked": { + "lastModified": 1783945712, + "narHash": "sha256-ePHSbY7/7fNdOA2CE8J4T9Jt7xRrX87N2mlKd8EsYdM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "293d01ba488ddb4c3560ba7c8de1fbec7047f78c", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-26.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "roc-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ], + "nixpkgs-darwin": [ + "nixpkgs-x86-darwin" + ] + }, + "locked": { + "lastModified": 1784073071, + "narHash": "sha256-tmJuQY9Kr4yFTnA56pdTbyExRfd94NTj7jRBtpSozCc=", + "owner": "thebrandonlucas", + "repo": "roc-overlay", + "rev": "a9afdcfed9bf90c53e6b4b1443e00676a939e971", + "type": "github" + }, + "original": { + "owner": "thebrandonlucas", + "repo": "roc-overlay", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs", + "nixpkgs-x86-darwin": "nixpkgs-x86-darwin", + "roc-overlay": "roc-overlay", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1784178955, + "narHash": "sha256-YtXHVFBzzqSidcEhPhfTcF2yzzu0p0yA7x07LOR+LaY=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "1785b85aeccca381caf8777133410f577b8f2f59", + "type": "github" + }, + "original": { + "owner": "oxalica", + "repo": "rust-overlay", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..88f4b577 --- /dev/null +++ b/flake.nix @@ -0,0 +1,78 @@ +{ + description = "basic-cli development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + # nixos-unstable no longer supports Intel macOS. + nixpkgs-x86-darwin.url = "github:NixOS/nixpkgs/nixpkgs-26.05-darwin"; + roc-overlay = { + url = "github:thebrandonlucas/roc-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.nixpkgs-darwin.follows = "nixpkgs-x86-darwin"; + }; + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { + nixpkgs, + nixpkgs-x86-darwin, + roc-overlay, + rust-overlay, + ... + }: + let + inherit (nixpkgs) lib; + + supportedSystems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + forAllSystems = lib.genAttrs supportedSystems; + rustToolchainConfig = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml)).toolchain; + rustTargets = [ + "x86_64-apple-darwin" + "aarch64-apple-darwin" + "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-musl" + ]; + pkgsFor = + system: + import (if system == "x86_64-darwin" then nixpkgs-x86-darwin else nixpkgs) { + inherit system; + overlays = [ + roc-overlay.overlays.default + rust-overlay.overlays.default + ]; + }; + in + { + formatter = forAllSystems (system: (pkgsFor system).nixfmt); + + devShells = forAllSystems ( + system: + let + pkgs = pkgsFor system; + rustToolchain = pkgs.rust-bin.fromRustupToolchain ( + rustToolchainConfig // { targets = rustTargets; } + ); + in + { + default = pkgs.mkShell { + packages = [ + pkgs.rocpkgs.nightly + pkgs.python3 + rustToolchain + pkgs.simple-http-server + pkgs.zig_0_16 + ]; + }; + } + ); + }; +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 9e701eb6..c0e44280 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -6,6 +6,6 @@ # b) update `channel = "nightly-OLD_DATE"` below channel = "1.83.0" # check ^^^ when changing this -components = ["rust-analyzer"] +components = ["rust-analyzer", "llvm-tools-preview"] # # channel = "nightly-2024-04-28" # 1.79.0 nightly to be able to use unstable features diff --git a/scripts/build.py b/scripts/build.py index 890c0f42..542d5dca 100755 --- a/scripts/build.py +++ b/scripts/build.py @@ -117,7 +117,31 @@ def musl_build_env(rust_target: str) -> dict[str, str]: return env +def rust_target_is_installed(rust_target: str) -> bool: + result = subprocess.run( + ["rustc", "--print", "target-libdir", "--target", rust_target], + check=False, + stdout=subprocess.PIPE, + stderr=subprocess.DEVNULL, + text=True, + ) + return result.returncode == 0 and Path(result.stdout.strip()).is_dir() + + def install_rust_target(rust_target: str, *, required: bool = False) -> None: + if rust_target_is_installed(rust_target): + return + + if shutil.which("rustup") is None: + message = ( + f"Rust target {rust_target} is not installed and rustup is unavailable; " + "enter `nix develop` or install the target manually" + ) + if required: + raise SystemExit(message) + print(f"warning: {message}") + return + run("rustup", "target", "add", rust_target, check=required)