Skip to content

Commit

Permalink
Clean up Nix Flake & make it easier to customize (#12831)
Browse files Browse the repository at this point in the history
  • Loading branch information
RossSmyth authored Mar 4, 2025
1 parent 671a603 commit 1d45378
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 197 deletions.
84 changes: 77 additions & 7 deletions default.nix
Original file line number Diff line number Diff line change
@@ -1,8 +1,78 @@
# Flake's default package for non-flake-enabled nix instances
let
compat = builtins.fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/b4a34015c698c7793d592d66adbab377907a2be8.tar.gz";
sha256 = "sha256:1qc703yg0babixi6wshn5wm2kgl5y1drcswgszh4xxzbrwkk9sv7";
};
{
lib,
rustPlatform,
callPackage,
runCommand,
installShellFiles,
git,
...
}: let
fs = lib.fileset;

src = fs.difference (fs.gitTracked ./.) (fs.unions [
./.envrc
./rustfmt.toml
./screenshot.png
./book
./docs
./flake.lock
(fs.fileFilter (file: lib.strings.hasInfix ".git" file.name) ./.)
(fs.fileFilter (file: file.hasExt "svg") ./.)
(fs.fileFilter (file: file.hasExt "md") ./.)
(fs.fileFilter (file: file.hasExt "nix") ./.)
]);

# Next we actually need to build the grammars and the runtime directory
# that they reside in. It is built by calling the derivation in the
# grammars.nix file, then taking the runtime directory in the git repo
# and hooking symlinks up to it.
grammars = callPackage ./grammars.nix {};
runtimeDir = runCommand "helix-runtime" {} ''
mkdir -p $out
ln -s ${./runtime}/* $out
rm -r $out/grammars
ln -s ${grammars} $out/grammars
'';
in
(import compat {src = ./.;}).defaultNix
# Currently rustPlatform.buildRustPackage doesn't have the finalAttrs pattern

This comment has been minimized.

Copy link
@RossSmyth

RossSmyth Mar 4, 2025

Author Contributor

Oh this comment can be removed.

# hooked up. To get around this while having good customization, mkDerivation is
# used instead.
rustPlatform.buildRustPackage (self: {
cargoLock.lockFile = ./Cargo.lock;

nativeBuildInputs = [
installShellFiles
git
];

buildType = "release";

name = with builtins; (fromTOML (readFile ./helix-term/Cargo.toml)).package.name;
src = fs.toSource {
root = ./.;
fileset = src;
};

# Helix attempts to reach out to the network and get the grammars. Nix doesn't allow this.
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";

# So Helix knows what rev it is.
HELIX_NIX_BUILD_REV = self.rev or self.dirtyRev or null;

doCheck = false;
strictDeps = true;

# Sets the Helix runtimedir to the grammars
env.HELIX_DEFAULT_RUNTIME = "${runtimeDir}";

# Get all the application stuff in the output directory.
postInstall = ''
mkdir -p $out/lib
installShellCompletion ${./contrib/completion}/hx.{bash,fish,zsh}
mkdir -p $out/share/{applications,icons/hicolor/256x256/apps}
cp ${./contrib/Helix.desktop} $out/share/applications
cp ${./contrib/helix.png} $out/share/icons/hicolor/256x256/apps
'';

meta.mainProgram = "hx";
})
28 changes: 6 additions & 22 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

195 changes: 41 additions & 154 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@
url = "github:oxalica/rust-overlay";
inputs.nixpkgs.follows = "nixpkgs";
};
crane.url = "github:ipetkov/crane";
};

outputs = {
self,
nixpkgs,
crane,
flake-utils,
rust-overlay,
...
Expand All @@ -24,167 +22,56 @@
inherit system;
overlays = [(import rust-overlay)];
};
mkRootPath = rel:
builtins.path {
path = "${toString ./.}/${rel}";
name = rel;
};
filteredSource = let
pathsToIgnore = [
".envrc"
".ignore"
".github"
".gitignore"
"logo_dark.svg"
"logo_light.svg"
"rust-toolchain.toml"
"rustfmt.toml"
"runtime"
"screenshot.png"
"book"
"docs"
"README.md"
"CHANGELOG.md"
"shell.nix"
"default.nix"
"grammars.nix"
"flake.nix"
"flake.lock"
];
ignorePaths = path: type: let
inherit (nixpkgs) lib;
# split the nix store path into its components
components = lib.splitString "/" path;
# drop off the `/nix/hash-source` section from the path
relPathComponents = lib.drop 4 components;
# reassemble the path components
relPath = lib.concatStringsSep "/" relPathComponents;
in
lib.all (p: ! (lib.hasPrefix p relPath)) pathsToIgnore;
in
builtins.path {
name = "helix-source";
path = toString ./.;
# filter out unnecessary paths
filter = ignorePaths;
};
makeOverridableHelix = old: config: let
grammars = pkgs.callPackage ./grammars.nix config;
runtimeDir = pkgs.runCommand "helix-runtime" {} ''
mkdir -p $out
ln -s ${mkRootPath "runtime"}/* $out
rm -r $out/grammars
ln -s ${grammars} $out/grammars
'';
helix-wrapped =
pkgs.runCommand
old.name
{
inherit (old) pname version;
meta = old.meta or {};
passthru =
(old.passthru or {})
// {
unwrapped = old;
};
nativeBuildInputs = [pkgs.makeWrapper];
makeWrapperArgs = config.makeWrapperArgs or [];
}
''
cp -rs --no-preserve=mode,ownership ${old} $out
wrapProgram "$out/bin/hx" ''${makeWrapperArgs[@]} --set HELIX_RUNTIME "${runtimeDir}"
'';
in
helix-wrapped
// {
override = makeOverridableHelix old;
passthru =
helix-wrapped.passthru
// {
wrapper = old: makeOverridableHelix old config;
};
};
stdenv =
if pkgs.stdenv.isLinux
then pkgs.stdenv
else pkgs.clangStdenv;
rustFlagsEnv = pkgs.lib.optionalString stdenv.isLinux "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment --cfg tokio_unstable";
rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
craneLibMSRV = (crane.mkLib pkgs).overrideToolchain rustToolchain;
craneLibStable = (crane.mkLib pkgs).overrideToolchain pkgs.pkgsBuildHost.rust-bin.stable.latest.default;
commonArgs = {
inherit stdenv;
inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./helix-term/Cargo.toml;}) pname;
inherit (craneLibMSRV.crateNameFromCargoToml {cargoToml = ./Cargo.toml;}) version;
src = filteredSource;
# disable fetching and building of tree-sitter grammars in the helix-term build.rs
HELIX_DISABLE_AUTO_GRAMMAR_BUILD = "1";
buildInputs = [stdenv.cc.cc.lib];
nativeBuildInputs = [pkgs.installShellFiles];
# disable tests
doCheck = false;
meta.mainProgram = "hx";

# Get Helix's MSRV toolchain to build with by default.
msrvToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml;
msrvPlatform = pkgs.makeRustPlatform {
cargo = msrvToolchain;
rustc = msrvToolchain;
};
cargoArtifacts = craneLibMSRV.buildDepsOnly commonArgs;
in {
packages = {
helix-unwrapped = craneLibStable.buildPackage (commonArgs
// {
cargoArtifacts = craneLibStable.buildDepsOnly commonArgs;
postInstall = ''
mkdir -p $out/share/applications $out/share/icons/hicolor/scalable/apps $out/share/icons/hicolor/256x256/apps
cp contrib/Helix.desktop $out/share/applications
cp logo.svg $out/share/icons/hicolor/scalable/apps/helix.svg
cp contrib/helix.png $out/share/icons/hicolor/256x256/apps
installShellCompletion contrib/completion/hx.{bash,fish,zsh}
'';
# set git revision for nix flake builds, see 'git_hash' in helix-loader/build.rs
HELIX_NIX_BUILD_REV = self.rev or self.dirtyRev or null;
});
helix = makeOverridableHelix self.packages.${system}.helix-unwrapped {};
default = self.packages.${system}.helix;
};
packages = rec {
helix = pkgs.callPackage ./default.nix {};

checks = {
# Build the crate itself
inherit (self.packages.${system}) helix;

clippy = craneLibMSRV.cargoClippy (commonArgs
// {
inherit cargoArtifacts;
cargoClippyExtraArgs = "--all-targets -- --deny warnings";
});

fmt = craneLibMSRV.cargoFmt commonArgs;

doc = craneLibMSRV.cargoDoc (commonArgs
// {
inherit cargoArtifacts;
});

test = craneLibMSRV.cargoTest (commonArgs
// {
inherit cargoArtifacts;
});
# The default Helix build. Uses the latest stable Rust toolchain, and unstable
# nixpkgs.
#
# This can be overridden though to add Cargo Features, flags, and different toolchains with
# packages.${system}.default.override { ... };
default = helix;
};

devShells.default = pkgs.mkShell {
inputsFrom = builtins.attrValues self.checks.${system};
nativeBuildInputs = with pkgs;
[lld_13 cargo-flamegraph rust-analyzer]
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) pkgs.cargo-tarpaulin)
++ (lib.optional stdenv.isLinux pkgs.lldb)
++ (lib.optional stdenv.isDarwin pkgs.darwin.apple_sdk.frameworks.CoreFoundation);
shellHook = ''
export HELIX_RUNTIME="$PWD/runtime"
export RUST_BACKTRACE="1"
export RUSTFLAGS="''${RUSTFLAGS:-""} ${rustFlagsEnv}"
'';
checks.helix = self.outputs.packages.${system}.helix.override {
buildType = "debug";
rustPlatform = msrvPlatform;
};

# Devshell behavior is preserved.
devShells.default = let
rustFlagsEnv = pkgs.lib.optionalString pkgs.stdenv.isLinux "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment --cfg tokio_unstable";
in
pkgs.mkShell
{
inputsFrom = [self.checks.${system}.helix];
nativeBuildInputs = with pkgs;
[
lld_13
cargo-flamegraph
rust-bin.nightly.latest.rust-analyzer
]
++ (lib.optional (stdenv.isx86_64 && stdenv.isLinux) cargo-tarpaulin)
++ (lib.optional stdenv.isLinux lldb)
++ (lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.CoreFoundation);
shellHook = ''
export HELIX_RUNTIME="$PWD/runtime"
export RUST_BACKTRACE="1"
export RUSTFLAGS="''${RUSTFLAGS:-""} ${rustFlagsEnv}"
'';
};
})
// {
overlays.default = final: prev: {
inherit (self.packages.${final.system}) helix;
helix = final.callPackage ./default.nix {};
};
};

Expand Down
Loading

0 comments on commit 1d45378

Please sign in to comment.