ebeddfb308
In order to make testing and deployment simpler and more reproducible, we want to provide a Nix derivation for our macOS .app build. We already build the Rust and dashboard with Nix, but so far the Python has been blocked because we haven't had an MLX build. This change adds a Metal compiler derivation that uses `requireFile` to be provided a NAR of the unfree macOS Metal compiler. It is documented how to get this file, but effectively you have to trigger the download, mount the DMG, and NAR the result. Once this is added to the store by hash we can build MLX using it. The MLX build itself is quite self explanatory. Test plan: - CI. We follow the instructions to grab the Metal compiler. Once this is in Cachix we should really never do this again, and I can pin the path too to ensure it doesn't leave. - MLX tests run as part of the MLX derivation's build. They pass. - `NIXPKGS_ALLOW_UNFREE=1 nix build .#mlx.passthru.tests.mlxTest --impure --option sandbox false` --------- Co-authored-by: Ryuichi Leo Takashige <leo@exolabs.net>
158 lines
4.5 KiB
Nix
158 lines
4.5 KiB
Nix
{
|
|
description = "The development environment for Exo";
|
|
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
|
|
flake-parts = {
|
|
url = "github:hercules-ci/flake-parts";
|
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
|
};
|
|
|
|
crane.url = "github:ipetkov/crane";
|
|
|
|
fenix = {
|
|
url = "github:nix-community/fenix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
|
|
treefmt-nix = {
|
|
url = "github:numtide/treefmt-nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
|
|
dream2nix = {
|
|
url = "github:nix-community/dream2nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
|
|
# Pinned nixpkgs for swift-format (swift is broken on x86_64-linux in newer nixpkgs)
|
|
nixpkgs-swift.url = "github:NixOS/nixpkgs/08dacfca559e1d7da38f3cf05f1f45ee9bfd213c";
|
|
};
|
|
|
|
nixConfig = {
|
|
extra-trusted-public-keys = "exo.cachix.org-1:okq7hl624TBeAR3kV+g39dUFSiaZgLRkLsFBCuJ2NZI=";
|
|
extra-substituters = "https://exo.cachix.org";
|
|
};
|
|
|
|
outputs =
|
|
inputs:
|
|
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
|
systems = [
|
|
"x86_64-linux"
|
|
"aarch64-darwin"
|
|
"aarch64-linux"
|
|
];
|
|
|
|
imports = [
|
|
inputs.treefmt-nix.flakeModule
|
|
./dashboard/parts.nix
|
|
./rust/parts.nix
|
|
];
|
|
|
|
perSystem =
|
|
{ config, self', inputs', pkgs, lib, system, ... }:
|
|
let
|
|
fenixToolchain = inputs'.fenix.packages.complete;
|
|
# Use pinned nixpkgs for swift-format (swift is broken on x86_64-linux in newer nixpkgs)
|
|
pkgsSwift = import inputs.nixpkgs-swift { inherit system; };
|
|
in
|
|
{
|
|
# Allow unfree for metal-toolchain (needed for Darwin Metal packages)
|
|
_module.args.pkgs = import inputs.nixpkgs {
|
|
inherit system;
|
|
config.allowUnfreePredicate = pkg: (pkg.pname or "") == "metal-toolchain";
|
|
};
|
|
treefmt = {
|
|
projectRootFile = "flake.nix";
|
|
programs = {
|
|
nixpkgs-fmt.enable = true;
|
|
ruff-format = {
|
|
enable = true;
|
|
excludes = [ "rust/exo_pyo3_bindings/exo_pyo3_bindings.pyi" ];
|
|
};
|
|
rustfmt = {
|
|
enable = true;
|
|
package = config.rust.toolchain;
|
|
};
|
|
prettier = {
|
|
enable = true;
|
|
package = self'.packages.prettier-svelte;
|
|
includes = [ "*.ts" "*.svelte" ];
|
|
};
|
|
swift-format = {
|
|
enable = true;
|
|
package = pkgsSwift.swiftPackages.swift-format;
|
|
};
|
|
};
|
|
};
|
|
|
|
checks.lint = pkgs.runCommand "lint-check" { } ''
|
|
export RUFF_CACHE_DIR="$TMPDIR/ruff-cache"
|
|
${pkgs.ruff}/bin/ruff check ${inputs.self}/
|
|
touch $out
|
|
'';
|
|
|
|
packages = lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin (
|
|
let
|
|
uvLock = builtins.fromTOML (builtins.readFile ./uv.lock);
|
|
mlxPackage = builtins.head (builtins.filter (p: p.name == "mlx") uvLock.package);
|
|
uvLockMlxVersion = mlxPackage.version;
|
|
in
|
|
{
|
|
metal-toolchain = pkgs.callPackage ./nix/metal-toolchain.nix { };
|
|
mlx = pkgs.callPackage ./nix/mlx.nix {
|
|
metal-toolchain = self'.packages.metal-toolchain;
|
|
inherit uvLockMlxVersion;
|
|
};
|
|
}
|
|
);
|
|
|
|
devShells.default = with pkgs; pkgs.mkShell {
|
|
inputsFrom = [ self'.checks.cargo-build ];
|
|
|
|
packages =
|
|
[
|
|
# FORMATTING
|
|
config.treefmt.build.wrapper
|
|
|
|
# PYTHON
|
|
python313
|
|
uv
|
|
ruff
|
|
basedpyright
|
|
|
|
# RUST
|
|
config.rust.toolchain
|
|
maturin
|
|
|
|
# NIX
|
|
nixpkgs-fmt
|
|
|
|
# SVELTE
|
|
nodejs
|
|
|
|
# MISC
|
|
just
|
|
jq
|
|
]
|
|
++ lib.optionals stdenv.isLinux [
|
|
unixtools.ifconfig
|
|
]
|
|
++ lib.optionals stdenv.isDarwin [
|
|
macmon
|
|
];
|
|
|
|
OPENSSL_NO_VENDOR = "1";
|
|
|
|
shellHook = ''
|
|
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${python313}/lib"
|
|
${lib.optionalString stdenv.isLinux ''
|
|
export LD_LIBRARY_PATH="${openssl.out}/lib:$LD_LIBRARY_PATH"
|
|
''}
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
}
|