Skip to content

Commit

Permalink
Add build environment using Nix
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisandreae committed Jul 2, 2024
1 parent ddad581 commit 476550b
Show file tree
Hide file tree
Showing 14 changed files with 787 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
# Docker on Windows.
.bashrc text eol=lf
*.sh text eol=lf
*.nix text eol=lf
39 changes: 39 additions & 0 deletions README-NIX.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Building Zephyr™ Mechanical Keyboard (ZMK) Firmware with Nix

This extension is added by MoErgo for the Glove80 keyboard.

Nix makes setup significantly easier. With this approach `west` is not needed.
You can however still choose to build using the standard Zephyr `west` toolchain
if you wish.

# To build a target

In ZMK root directory,

nix-build -A *target* [-o *output_directory*]

For example,

nix-build -A glove80_left -o left

The `output_directory` nix creates is a symlink. If you prefer not to rely on
symlink (perhaps because you are using WSL on Windows), you can make a copy of
the resulting `uf2` file using:

cp -f $(nix-build -A *target* --no-out-link)/zmk.uf2 .

# To build Glove80

In ZMK root directory,

cp -f $(nix-build -A glove80_combined --no-out-link)/glove80.uf2 .

# Adding new targets

Edit default.nix and add an target based on zmk

An example is:

glove80_left = zmk.override {
board = "glove80_lh";
};
51 changes: 51 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{ pkgs ? (import ./nix/pinned-nixpkgs.nix {}) }:
let
inherit (pkgs) newScope;
inherit (pkgs.lib) makeScope;
in

makeScope newScope (self: with self; {
west = pkgs.python3Packages.west.overrideAttrs(attrs: {
patches = (attrs.patches or []) ++ [./nix/west-manifest.patch];
});

# To update the pinned Zephyr dependecies using west and update-manifest:
# nix shell -f . west -c west init -l app
# nix shell -f . west -c west update
# nix shell -f . update-manifest -c update-manifest > nix/manifest.json
# Note that any `group-filter` groups in west.yml need to be temporarily
# removed, as `west update-manifest` requires all dependencies to be fetched.
update-manifest = callPackage ./nix/update-manifest { inherit west; };

combine_uf2 = a: b: pkgs.runCommandNoCC "combined_${a.name}_${b.name}" {}
''
mkdir -p $out
cat ${a}/zmk.uf2 ${b}/zmk.uf2 > $out/glove80.uf2
'';

zephyr = callPackage ./nix/zephyr.nix { };

zmk = callPackage ./nix/zmk.nix { };

zmk_settings_reset = zmk.override {
shield = "settings_reset";
};

glove80_left = zmk.override {
board = "glove80_lh";
};

glove80_right = zmk.override {
board = "glove80_rh";
};

glove80_combined = combine_uf2 glove80_left glove80_right;

glove80_v0_left = zmk.override {
board = "glove80_v0_lh";
};

glove80_v0_right = zmk.override {
board = "glove80_v0_rh";
};
})
17 changes: 17 additions & 0 deletions nix/cmake-shell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{ pkgs ? (import ./pinned-nixpkgs.nix {}) }:

let
zmkPkgs = (import ../default.nix { inherit pkgs; });
inherit (zmkPkgs) zmk zephyr;

zmkCmake = pkgs.writeShellScriptBin "zmk-cmake" ''
export PATH=${pkgs.lib.makeBinPath zmk.nativeBuildInputs}:$PATH
export CMAKE_PREFIX_PATH=${zephyr}
cmake -G Ninja ${pkgs.lib.escapeShellArgs zmk.cmakeFlags} "-DUSER_CACHE_DIR=/tmp/.cache" "$@"
'';
in
pkgs.stdenv.mkDerivation {
name = "zmk-cmake-shell";
nativeBuildInputs = zmk.nativeBuildInputs ++ [zmkCmake];
}
34 changes: 34 additions & 0 deletions nix/generate-pin.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require 'json'
require 'net/http'
require 'shellwords'

def get_channel_url(channel)
uri = URI("https://channels.nixos.org/#{channel}")
res = Net::HTTP.get_response(uri)
raise 'Not a redirect' unless res.is_a?(Net::HTTPRedirection)
res['location']
end

def fetch_tarball(url)
hash = `nix-prefetch-url --unpack #{Shellwords.escape(url)}`
raise 'Prefetch failed' unless $?.success?
hash.chomp
end

def generate_pin(channel)
channel_url = get_channel_url(channel)
nixexprs = "#{channel_url}/nixexprs.tar.xz"
hash = fetch_tarball(nixexprs)
{ url: nixexprs, sha256: hash }
end

def main
channel = ENV.fetch('CHANNEL', 'nixpkgs-unstable')
pin = generate_pin(channel)
puts JSON.pretty_generate(pin)
end

main
Loading

0 comments on commit 476550b

Please sign in to comment.