make nix flake apps usable

This commit is contained in:
Clément DOUIN 2024-04-20 07:51:15 +02:00
commit 3c417d14eb
No known key found for this signature in database
GPG key ID: 353E4A18EE0FAB72
4 changed files with 180 additions and 125 deletions

View file

@ -31,12 +31,15 @@ jobs:
include:
- target: x86_64-linux
os: ubuntu-latest
- target: arm64-linux
- target: aarch64-linux
os: ubuntu-latest
- target: x86_64-windows
os: ubuntu-latest
- target: x86_64-macos
- target: x86_64-darwin
os: macos-latest
# FIXME: build broken
# - target: aarch64-darwin
# os: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
@ -53,7 +56,7 @@ jobs:
- name: Build release archive
run: |
nix build -L .#${{ matrix.target }}
cp result/bin/himalaya* .
cp result/himalaya* .
- name: Upload tgz release archive
uses: actions/upload-release-asset@v1
env:

41
.github/workflows/test.yml vendored Normal file
View file

@ -0,0 +1,41 @@
name: test
on:
push:
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-linux
os: ubuntu-latest
- target: aarch64-linux
os: ubuntu-latest
- target: x86_64-windows
os: ubuntu-latest
- target: x86_64-darwin
os: macos-latest
# FIXME: build broken
# - target: aarch64-darwin
# os: macos-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Install Nix
uses: cachix/install-nix-action@v24
with:
nix_path: nixpkgs=channel:nixos-23.11
extra_nix_config: |
experimental-features = nix-command flakes
- uses: cachix/cachix-action@v12
with:
name: soywod
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Run app
run: |
nix build -L .#${{ matrix.target }}
nix run -L .#${{ matrix.target }} -- --version
ls -R result

247
flake.nix
View file

@ -23,127 +23,188 @@
outputs = { self, nixpkgs, gitignore, fenix, naersk, ... }:
let
inherit (nixpkgs) lib;
inherit (gitignore.lib) gitignoreSource;
staticRustFlags = [ "-Ctarget-feature=+crt-static" ];
# Map of map matching supported Nix build systems with Rust
# cross target systems.
crossBuildTargets = {
crossSystems = {
x86_64-linux = {
x86_64-linux = {
rustTarget = "x86_64-unknown-linux-musl";
override = { ... }: { };
};
arm64-linux = rec {
aarch64-linux = rec {
rustTarget = "aarch64-unknown-linux-musl";
override = { system, pkgs }:
runner = { pkgs, himalaya }: "${pkgs.qemu}/bin/qemu-aarch64 ${himalaya}";
mkPackage = { system, pkgs }: package:
let
inherit (mkPkgsCross system rustTarget) stdenv;
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc"; in
rec {
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
in
package // {
TARGET_CC = cc;
CARGO_BUILD_RUSTFLAGS = staticRustFlags ++ [ "-Clinker=${cc}" ];
postInstall = mkPostInstall {
inherit pkgs;
bin = "${pkgs.qemu}/bin/qemu-aarch64 ./himalaya";
};
CARGO_BUILD_RUSTFLAGS = package.CARGO_BUILD_RUSTFLAGS ++ [ "-Clinker=${cc}" ];
};
};
x86_64-windows = {
rustTarget = "x86_64-pc-windows-gnu";
override = { system, pkgs }:
runner = { pkgs, himalaya }:
let wine = pkgs.wine.override { wineBuild = "wine64"; };
in "${wine}/bin/wine64 ${himalaya}.exe";
mkPackage = { system, pkgs }: package:
let
inherit (pkgs) pkgsCross zip;
inherit (pkgsCross.mingwW64) stdenv windows;
inherit (pkgs.pkgsCross.mingwW64) stdenv windows;
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
wine = pkgs.wine.override { wineBuild = "wine64"; };
postInstall = mkPostInstall {
inherit pkgs;
bin = "${wine}/bin/wine64 ./himalaya.exe";
};
in
{
package // {
depsBuildBuild = [ stdenv.cc windows.pthreads ];
TARGET_CC = cc;
CARGO_BUILD_RUSTFLAGS = staticRustFlags ++ [ "-Clinker=${cc}" ];
postInstall = ''
export WINEPREFIX="$(mktemp -d)"
${postInstall}
'';
CARGO_BUILD_RUSTFLAGS = package.CARGO_BUILD_RUSTFLAGS ++ [ "-Clinker=${cc}" ];
};
};
};
aarch64-linux = {
aarch64-linux = {
rustTarget = "aarch64-unknown-linux-musl";
};
};
x86_64-darwin = {
x86_64-macos = {
x86_64-darwin = {
rustTarget = "x86_64-apple-darwin";
override = { pkgs, ... }:
let inherit (pkgs.darwin.apple_sdk.frameworks) AppKit Cocoa; in
{
mkPackage = { pkgs, ... }: package:
let inherit (pkgs.darwin.apple_sdk.frameworks) AppKit Cocoa;
in package // {
buildInputs = [ Cocoa ];
NIX_LDFLAGS = "-F${AppKit}/Library/Frameworks -framework AppKit";
};
};
# FIXME: infinite recursion in stdenv?!
arm64-macos = {
# FIXME: https://github.com/NixOS/nixpkgs/issues/273442
aarch64-darwin = {
rustTarget = "aarch64-apple-darwin";
override = { system, pkgs }:
runner = { pkgs, himalaya }: "${pkgs.qemu}/bin/qemu-aarch64 ${himalaya}";
mkPackage = { system, pkgs }: package:
let
# inherit (mkPkgsCross system "aarch64-darwin") stdenv;
inherit ((mkPkgsCross system "aarch64-darwin").pkgsStatic) stdenv darwin;
inherit (darwin.apple_sdk.frameworks) AppKit Cocoa;
cc = "${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc";
in
rec {
package // {
buildInputs = [ Cocoa ];
NIX_LDFLAGS = "-F${AppKit}/Library/Frameworks -framework AppKit -F${Cocoa}/Library/Frameworks -framework Cocoa";
NIX_CFLAGS_COMPILE = "-F${AppKit}/Library/Frameworks -framework AppKit -F${Cocoa}/Library/Frameworks -framework Cocoa";
NIX_LDFLAGS = "-F${AppKit}/Library/Frameworks -framework AppKit";
TARGET_CC = cc;
CARGO_BUILD_RUSTFLAGS = staticRustFlags ++ [ "-Clinker=${cc}" "-lframework=${Cocoa}/Library/Frameworks" ];
postInstall = mkPostInstall {
inherit pkgs;
bin = "${pkgs.qemu}/bin/qemu-aarch64 ./himalaya";
};
CARGO_BUILD_RUSTFLAGS = package.CARGO_BUILD_RUSTFLAGS ++ [ "-Clinker=${cc}" ];
};
};
};
aarch64-darwin = {
aarch64-darwin = {
rustTarget = "aarch64-apple-darwin";
mkPackage = { pkgs, ... }: package:
let inherit (pkgs.darwin.apple_sdk.frameworks) AppKit Cocoa;
in package // {
buildInputs = [ Cocoa ];
NIX_LDFLAGS = "-F${AppKit}/Library/Frameworks -framework AppKit";
};
};
};
};
mkToolchain = import ./rust-toolchain.nix fenix;
eachBuildSystem = lib.genAttrs (builtins.attrNames crossSystems);
mkPkgsCross = buildSystem: crossSystem: import nixpkgs {
system = buildSystem;
crossSystem.config = crossSystem;
};
mkPostInstall = { pkgs, bin ? "./himalaya" }: with pkgs; ''
cd $out/bin
mkdir -p {man,completions}
${bin} man ./man
${bin} completion bash > ./completions/himalaya.bash
${bin} completion elvish > ./completions/himalaya.elvish
${bin} completion fish > ./completions/himalaya.fish
${bin} completion powershell > ./completions/himalaya.powershell
${bin} completion zsh > ./completions/himalaya.zsh
tar -czf himalaya.tgz himalaya* man completions
${zip}/bin/zip -r himalaya.zip himalaya* man completions
'';
mkToolchain = import ./rust-toolchain.nix fenix;
mkDevShells = buildPlatform:
mkApp = { pkgs, buildSystem, targetSystem ? buildSystem }:
let
pkgs = import nixpkgs { system = buildPlatform; };
rust-toolchain = mkToolchain.fromFile { system = buildPlatform; };
himalaya = lib.getExe self.packages.${buildSystem}.${targetSystem};
wrapper = crossSystems.${buildSystem}.${targetSystem}.runner or (_: himalaya) { inherit pkgs himalaya; };
program = lib.getExe (pkgs.writeShellScriptBin "himalaya" "${wrapper} $@");
app = { inherit program; type = "app"; };
in
{
default = pkgs.mkShell {
app;
mkApps = buildSystem:
let
pkgs = import nixpkgs { system = buildSystem; };
mkApp' = targetSystem: _: mkApp { inherit pkgs buildSystem targetSystem; };
defaultApp = mkApp { inherit pkgs buildSystem; };
apps = builtins.mapAttrs mkApp' crossSystems.${buildSystem};
in
apps // { default = defaultApp; };
mkPackage = { pkgs, buildSystem, targetSystem ? buildSystem }:
let
targetConfig = crossSystems.${buildSystem}.${targetSystem};
toolchain = mkToolchain.fromTarget {
inherit pkgs buildSystem;
targetSystem = targetConfig.rustTarget;
};
rust = naersk.lib.${buildSystem}.override {
cargo = toolchain;
rustc = toolchain;
};
mkPackage' = targetConfig.mkPackage or (_: p: p);
himalaya = "./himalaya";
runner = targetConfig.runner or (_: himalaya) { inherit pkgs himalaya; };
package = mkPackage' { inherit pkgs; system = buildSystem; } {
name = "himalaya";
src = gitignoreSource ./.;
strictDeps = true;
doCheck = false;
auditable = false;
nativeBuildInputs = with pkgs; [ pkg-config ];
CARGO_BUILD_TARGET = targetConfig.rustTarget;
CARGO_BUILD_RUSTFLAGS = [ "-Ctarget-feature=+crt-static" ];
postInstall = ''
export WINEPREFIX="$(mktemp -d)"
mkdir -p $out/bin/share/{applications,completions,man,services}
cp assets/himalaya.desktop $out/bin/share/applications/
cp assets/himalaya-watch@.service $out/bin/share/services/
cd $out/bin
${runner} man ./share/man
${runner} completion bash > ./share/completions/himalaya.bash
${runner} completion elvish > ./share/completions/himalaya.elvish
${runner} completion fish > ./share/completions/himalaya.fish
${runner} completion powershell > ./share/completions/himalaya.powershell
${runner} completion zsh > ./share/completions/himalaya.zsh
tar -czf himalaya.tgz himalaya* share
${pkgs.zip}/bin/zip -r himalaya.zip himalaya* share
mv share ../
mv himalaya.tgz himalaya.zip ../
'';
};
in
rust.buildPackage package;
mkPackages = buildSystem:
let
pkgs = import nixpkgs { system = buildSystem; };
mkPackage' = targetSystem: _: mkPackage { inherit pkgs buildSystem targetSystem; };
defaultPackage = mkPackage { inherit pkgs buildSystem; };
packages = builtins.mapAttrs mkPackage' crossSystems.${buildSystem};
in
packages // { default = defaultPackage; };
mkDevShells = buildSystem:
let
pkgs = import nixpkgs { system = buildSystem; };
rust-toolchain = mkToolchain.fromFile { inherit buildSystem; };
defaultShell = pkgs.mkShell {
nativeBuildInputs = with pkgs; [ pkg-config ];
buildInputs = with pkgs; [
# Nix
# rnix-lsp
nixd
nixpkgs-fmt
# Rust
@ -157,63 +218,13 @@
notmuch
];
};
};
mkPackage = pkgs: buildPlatform: targetPlatform: package:
let
toolchain = mkToolchain.fromTarget {
inherit pkgs buildPlatform targetPlatform;
};
naersk' = naersk.lib.${buildPlatform}.override {
cargo = toolchain;
rustc = toolchain;
};
package' = {
name = "himalaya";
src = gitignoreSource ./.;
# overrideMain = _: {
# postInstall = ''
# mkdir -p $out/share/applications/
# cp assets/himalaya.desktop $out/share/applications/
# '';
# };
doCheck = false;
auditable = false;
strictDeps = true;
CARGO_BUILD_TARGET = targetPlatform;
CARGO_BUILD_RUSTFLAGS = staticRustFlags;
postInstall = mkPostInstall { inherit pkgs; };
} // package;
in
naersk'.buildPackage package';
{ default = defaultShell; };
mkPackages = system:
let
pkgs = import nixpkgs { inherit system; };
mkPackage' = target: package: mkPackage pkgs system package.rustTarget (package.override { inherit system pkgs; });
in
builtins.mapAttrs mkPackage' crossBuildTargets.${system};
mkApp = drv:
let exePath = drv.passthru.exePath or "/bin/himalaya"; in
{
type = "app";
program = "${drv}${exePath}";
};
mkApps = buildPlatform:
let
pkgs = import nixpkgs { system = buildPlatform; };
mkApp' = target: package: mkApp self.packages.${buildPlatform}.${target};
in
builtins.mapAttrs mkApp' crossBuildTargets.${buildPlatform};
supportedSystems = builtins.attrNames crossBuildTargets;
mapSupportedSystem = nixpkgs.lib.genAttrs supportedSystems;
in
{
apps = mapSupportedSystem mkApps;
packages = mapSupportedSystem mkPackages;
devShells = mapSupportedSystem mkDevShells;
apps = eachBuildSystem mkApps;
packages = eachBuildSystem mkPackages;
devShells = eachBuildSystem mkDevShells;
};
}

View file

@ -5,16 +5,16 @@ let
sha256 = "+syqAd2kX8KVa8/U2gz3blIQTTsYYt3U63xBWaGOSc8=";
in
{
fromFile = { system }: fenix.packages.${system}.fromToolchainFile {
fromFile = { buildSystem }: fenix.packages.${buildSystem}.fromToolchainFile {
inherit file sha256;
};
fromTarget = { pkgs, buildPlatform, targetPlatform }:
fromTarget = { pkgs, buildSystem, targetSystem }:
let
name = (pkgs.lib.importTOML file).toolchain.channel;
fenixPackage = fenix.packages.${buildPlatform};
fenixPackage = fenix.packages.${buildSystem};
toolchain = fenixPackage.fromToolchainName { inherit name sha256; };
targetToolchain = fenixPackage.targets.${targetPlatform}.fromToolchainName { inherit name sha256; };
targetToolchain = fenixPackage.targets.${targetSystem}.fromToolchainName { inherit name sha256; };
in
fenixPackage.combine [
toolchain.rustc