diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..8392d15 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1619a82..c09cfdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,3 +41,20 @@ jobs: - name: Test without online feature run: cargo test --all-targets --no-default-features + + nix: + name: Nix flake + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install Nix + uses: DeterminateSystems/nix-installer-action@main + + - name: Configure Nix cache + uses: DeterminateSystems/magic-nix-cache-action@main + + - name: Check flake + run: nix flake check diff --git a/.gitignore b/.gitignore index 4207179..4a5a59b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target +/.direnv -.fake \ No newline at end of file +.fake diff --git a/README.md b/README.md index 0878403..863a4c1 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,133 @@ architecture experiment, not as a production research code. ## Quick Start +### Choosing A Development Environment + +RustiQ can be developed either with the repository's Nix flake or with a +regular Rust installation. `direnv` is optional: it only automates entering and +leaving the Nix development shell. + +If Nix is new to you, start with the official [introduction to +Nix](https://nixos.org/why-nix/) and [learning resources](https://nixos.org/learn/). +Nix is a package manager and development-environment tool; NixOS is a complete +Linux distribution built around it. You do not need to replace your operating +system with NixOS to use this repository's flake. + +The flake supports the following platforms: + +- Linux on x86_64 and AArch64; +- macOS on Apple Silicon. + +The pinned nixpkgs revision no longer supports Intel macOS (`x86_64-darwin`). +Use the native Cargo workflow on that platform. + +On Windows, use the native Cargo workflow below or run the Linux flake through +WSL2. WSL2 can run either [NixOS-WSL](https://nix-community.github.io/NixOS-WSL/) +or another Linux distribution with the Nix package manager installed. Native +Windows itself is not one of the systems currently declared by `flake.nix`. + +#### Getting Nix + +Choose the case that matches your machine: + +- **On NixOS, including NixOS-WSL:** Nix is already installed as part of the + operating system. [NixOS-WSL installation + instructions](https://nix-community.github.io/NixOS-WSL/install.html) are + available for users who want to run NixOS directly under WSL2. Make sure the + modern Nix command and flakes are enabled in your NixOS configuration: + + ```nix + nix.settings.experimental-features = [ "nix-command" "flakes" ]; + ``` + + Apply the configuration with `sudo nixos-rebuild switch`, then continue with + `nix develop` or the direnv workflow below. + +- **On another Linux distribution, macOS, or a non-NixOS WSL2 distribution:** + install Nix separately as an additional package manager. It works alongside + tools such as `apt`, `dnf`, `pacman`, or Homebrew and does not replace them. + Follow the official [Nix download and installation + instructions](https://nixos.org/download/) for your platform, restart the + shell if requested, and verify the installation with `nix --version`. The + official page recommends a multi-user installation when the platform supports + it. + +In either case, Nix reads `flake.nix` and `flake.lock` from this repository to +create the same project-specific toolchain without installing those development +tools globally. The first invocation may take some time because Nix must +download the pinned dependencies; later invocations reuse its local store. + +#### Nix Without direnv + +Install Nix with flakes enabled, clone the repository, and enter the development +shell manually: + +```sh +git clone https://github.com/mveril/RustiQ.git +cd RustiQ +nix develop +``` + +This provides the Rust toolchain selected by `rust-toolchain.toml` and the +development utilities. On `x86_64-linux` and `aarch64-darwin`, where nixpkgs +currently supports its PySCF package, it also provides a Python environment +containing PySCF and its scientific Python dependencies. The shell remains +usable without PySCF on the other declared platforms and reports its absence +when it starts. Platform-specific profiling and debugging tools are included +where available. Run the usual Cargo commands inside it: + +```sh +cargo build +cargo test +cargo run -- run samples/h2/sto-3g/calculation.toml +``` + +Leave the environment with `exit` or Ctrl-D. You can also build the default Nix +package without entering the development shell: + +```sh +nix build +``` + +#### Nix With direnv + +Install both Nix and `direnv`, enable the direnv hook for your shell, then run: + +```sh +git clone https://github.com/mveril/RustiQ.git +cd RustiQ +direnv allow +``` + +The tracked `.envrc` contains `use flake`, so direnv loads the same Nix +development environment automatically whenever you enter the repository and +unloads it when you leave. `direnv allow` is deliberately required the first +time, and again after `.envrc` changes, so that repository-provided shell code +is not executed without review. Use `direnv deny` to revoke permission. + +If `use flake` is unknown, install or configure +[`nix-direnv`](https://github.com/nix-community/nix-direnv), or use `nix develop` +directly. Some direnv/Nix installations already provide this integration. + +#### Without Nix Or direnv + +Install Git and Rust through [`rustup`](https://rustup.rs/), then use Cargo +directly on Linux, macOS, or Windows: + +```sh +git clone https://github.com/mveril/RustiQ.git +cd RustiQ +rustup show +cargo build +cargo test +cargo run -- run samples/h2/sto-3g/calculation.toml +``` + +`rustup show` causes rustup to notice `rust-toolchain.toml` and install the +requested stable toolchain and components if necessary. This route is enough to +build and run RustiQ, but the extra tools and the PySCF reference environment +from the Nix development shell must be installed separately if you need them. + ### Installation From The Repository To install RustiQ directly from the source repository with Cargo, clone the diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..7db23f9 --- /dev/null +++ b/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1782949081, + "narHash": "sha256-vp6Y/Grm98ESt6ceOkWiHWyZRDV3J1RID4w+6NWK9yA=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "17c9d6cdfc60c64f4ee8d306f9bc0b4ccb51481e", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1785454630, + "narHash": "sha256-LQy14TZp77TwbQf40gg1V3jo8FwJG0jGDkAH+zRHqg8=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1559d3daa3ecc813a650b79375ea61b6741b8746", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1782614948, + "narHash": "sha256-ePjCwr1sNm9NYUqywL7QfK3JnlS015msC+eBu2zKlp8=", + "owner": "nix-community", + "repo": "nixpkgs.lib", + "rev": "db3f255737b94216eb71cce308e2912cf6bc2d7c", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixpkgs.lib", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" + } + }, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1785562362, + "narHash": "sha256-J15aBa3d6B1SUUAQydQ06wFjPzrrcVceb6jkdfwfGls=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "5f29c219a7655519f8a9f8c6968064b82c17cc93", + "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 0000000..fdbfc38 --- /dev/null +++ b/flake.nix @@ -0,0 +1,154 @@ +{ + description = "RustiQ development environment"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + + rust-overlay = { + url = "github:oxalica/rust-overlay"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + flake-parts.url = "github:hercules-ci/flake-parts"; + }; + + outputs = + inputs@{ + flake-parts, + nixpkgs, + rust-overlay, + ... + }: + flake-parts.lib.mkFlake { inherit inputs; } { + systems = [ + "x86_64-linux" + "aarch64-linux" + "aarch64-darwin" + ]; + + perSystem = + { system, ... }: + let + pkgs = import nixpkgs { + inherit system; + + overlays = [ + rust-overlay.overlays.default + ]; + }; + + rustToolchain = pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + + rustPlatform = pkgs.makeRustPlatform { + cargo = rustToolchain; + rustc = rustToolchain; + }; + + rustiq = rustPlatform.buildRustPackage { + pname = "RustiQ"; + version = "0.1.0-alpha.1"; + src = ./.; + cargoLock.lockFile = ./Cargo.lock; + doCheck = true; + }; + + pythonPyscf = pkgs.python314.withPackages ( + pythonPackages: with pythonPackages; [ + pyscf + numpy + scipy + matplotlib + jupyterlab + ipykernel + ] + ); + + pyscfSupported = builtins.elem system pkgs.python314Packages.pyscf.meta.platforms; + in + { + packages.default = rustiq; + + devShells.default = pkgs.mkShell { + strictDeps = true; + + packages = + with pkgs; + [ + rustToolchain + + cargo-nextest + cargo-deny + cargo-llvm-cov + cargo-criterion + cargo-expand + cargo-edit + + bacon + cargo-watch + git + hyperfine + just + jq + ripgrep + rust-analyzer + time + cmake + pkg-config + ] + ++ pkgs.lib.optionals pyscfSupported [ + # PySCF is currently available from nixpkgs on x86_64-linux + # and aarch64-darwin. + pythonPyscf + ] + ++ pkgs.lib.optionals pkgs.stdenv.isLinux [ + clang + cargo-flamegraph + gdb + inferno + llvmPackages.bintools + perf + ] + ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ + libiconv + samply + ]; + + env = { + RUST_BACKTRACE = "1"; + # Keep symbols in release-like profiling builds. This matches + # the [profile.profiling] section in Cargo.toml. + CARGO_PROFILE_PROFILING_DEBUG = "true"; + }; + + shellHook = '' + echo "RustiQ development environment" + echo "System: ${system}" + echo "Rust: $(rustc --version)" + echo "Cargo: $(cargo --version)" + ${pkgs.lib.optionalString pyscfSupported '' + echo "PySCF: $(python -c 'import pyscf; print(pyscf.__version__)')" + ''} + ${pkgs.lib.optionalString (!pyscfSupported) '' + echo "PySCF: unavailable from nixpkgs on ${system}" + ''} + ''; + }; + + formatter = pkgs.nixfmt; + + checks.formatting = + pkgs.runCommand "rustiq-formatting" + { + nativeBuildInputs = [ rustToolchain ]; + src = ./.; + } + '' + cargo fmt --manifest-path "$src/Cargo.toml" --all --check + + touch "$out" + ''; + + checks.tests = rustiq; + }; + }; +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..cd08da3 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "stable" +profile = "minimal" +components = ["clippy", "rustfmt", "rust-src"]