mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-11-13 12:23:38 +01:00
build(nix): one root flake for Windows, KDE Plasma and macOS
One flake.nix and one flake.lock replace the root flake that re-exported two nested flakes.
The inputs are one nixpkgs (the revision the KDE flake was locked to, f05535a0: the VM suites
run against its Plasma and KWin 6.8.2), one crane, rust-overlay (19ecdd08, rustc 1.99.1),
flake-parts, treefmt-nix and git-hooks-nix, all the KDE flake revisions, plus asc. A second
nixpkgs, nixpkgs-x86_64-darwin (16c7794d, the macOS flake pin), serves the x86_64-darwin
outputs only: evaluating that system with the unified pin throws (nixpkgs 26.11 dropped it).
Layout: nix/common.nix (systems, pkgs, treefmt, pre-commit, dev shells default and native,
default overlay), nix/lib.nix, nix/workspace-src.nix (one source per platform from the one Cargo
workspace: the platform members, its files of the shared crates told apart by name, the data
files, and stubs for the other members, which cargo needs), nix/{windows,linux,macos}/
{build,flake-module}.nix. The dependency derivations use a manifests-only dummy source, a plain
path, so crane reads nothing built at evaluation and the Darwin outputs evaluate on Linux.
Names: unprefixed outputs are the native build (Linux: KDE; Darwin: macOS); Windows cross
outputs are windows-*; checks are windows-*, linux-*, macos-* and vm-NAME; table in docs/dev/flake.md
(next revision). One deny.toml, one format-all and one version (workspace) are used by all.
PLACEHOLDER for the agent that owns the check sets: the checks that evaluate a NixOS system
or a VM (vm-*, linux-nixos-module-eval, linux-plasma-guests-eval, linux-run-kde*) are
legacyPackages.<system>.heavyChecks.<name>, not checks, because evaluating them needs more
memory than nix flake check --all-systems can use. The Plasma guests got a stub root file system
and boot loader (mkDefault, replaced by their vmVariant) so that nix flake check can evaluate
their toplevel.
Verified: nix flake check --no-build --all-systems passes (42 s, rc 0); nix flake check
--no-build passes. Not verified: any build (next revisions record them).
This commit is contained in:
1 parent
05698a34ba
commit
ae9ee327f9
11 files changed
+1821
-1084
No files matched your search
Generated
+14
-364
@@ -17,98 +17,6 @@
|
||||
}
|
||||
},
|
||||
"crane": {
|
||||
"locked": {
|
||||
"lastModified": 1766774972,
|
||||
"narHash": "sha256-8qxEFpj4dVmIuPn9j9z6NTbU+hrcGjBOvaxTzre5HmM=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "01bc1d404a51a0a07e9d8759cd50a7903e218c82",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1761588595,
|
||||
"narHash": "sha256-XKUZz9zewJNUj46b4AJdiRZJAvSZ0Dqj2BNfXvFlJC4=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "f387cd2afec9419c8ee37694406ca490c3f34ee5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1765835352,
|
||||
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks-nix": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1765911976,
|
||||
"narHash": "sha256-t3T/xm8zstHRLx+pIHxVpQTiySbKqcQbK+r+01XVKc0=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "b68b780b69702a090c8bb1b973bab13756cc7a27",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"git-hooks-nix",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-crane": {
|
||||
"locked": {
|
||||
"lastModified": 1792350552,
|
||||
"narHash": "sha256-292lvpvxTGKryKxh3/3tcIVi85CwYGdl4oOi113Sob8=",
|
||||
@@ -120,11 +28,10 @@
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "e675a36b7377bebe41d548388a2501cbb16d380d",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-flake-compat": {
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
@@ -137,15 +44,12 @@
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-flake-parts": {
|
||||
"flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"kfde-nixpkgs-lib"
|
||||
]
|
||||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1790898470,
|
||||
@@ -158,17 +62,14 @@
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "024633cd702b10285db5cb19b40ad48d2399ba60",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-git-hooks-nix": {
|
||||
"git-hooks-nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"kfde-flake-compat"
|
||||
],
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": [
|
||||
"kfde-nixpkgs"
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
@@ -182,11 +83,10 @@
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "1ba1dbfe28738c9a71c266be6efa5b89e75491a9",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-nixpkgs": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1793136825,
|
||||
"narHash": "sha256-2pkE69JpFRInaARSczZytcfPw83IL82E2KdhbWGwdMs=",
|
||||
@@ -197,12 +97,12 @@
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "f05535a0efcb2134c478d1e88434fadf486d42b5",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-nixpkgs-lib": {
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1790477367,
|
||||
"narHash": "sha256-oujbxmVKDhci2E4EM3KyAbRUgp5/IsCoiA/LfEF7OOk=",
|
||||
@@ -214,155 +114,10 @@
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "f7cd230690d9fc982d06129f9189b101fddcfa3b",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"kfde-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1793174968,
|
||||
"narHash": "sha256-u5nUf4cewaT36iIzG1s/VECktqUMiZaGF5BsgervsvQ=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "19ecdd08213836b36c4296a3a4f4af5a3d5308db",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "19ecdd08213836b36c4296a3a4f4af5a3d5308db",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfde-treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"kfde-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1791885023,
|
||||
"narHash": "sha256-C3alQ2MEt0zVrUSho5NUDo3jmhbff72++bfwoqT9Omo=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "0d6d739a833ba9a9c93034862e4a7b061a062a1c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "0d6d739a833ba9a9c93034862e4a7b061a062a1c",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-crane": {
|
||||
"locked": {
|
||||
"lastModified": 1767461147,
|
||||
"narHash": "sha256-TH/xTeq/RI+DOzo+c+4F431eVuBpYVwQwBxzURe7kcI=",
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "7d59256814085fd9666a2ae3e774dc5ee216b630",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "ipetkov",
|
||||
"repo": "crane",
|
||||
"rev": "7d59256814085fd9666a2ae3e774dc5ee216b630",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1767039857,
|
||||
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"repo": "flake-compat",
|
||||
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-flake-parts": {
|
||||
"inputs": {
|
||||
"nixpkgs-lib": [
|
||||
"kfm-nixpkgs-lib"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1765835352,
|
||||
"narHash": "sha256-XswHlK/Qtjasvhd1nOa1e8MgZ8GS//jBoTqWtrS1Giw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "a34fae9c08a15ad73f295041fec82323541400a9",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-git-hooks-nix": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"kfm-flake-compat"
|
||||
],
|
||||
"gitignore": [
|
||||
"kfm-gitignore"
|
||||
],
|
||||
"nixpkgs": [
|
||||
"kfm-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767281941,
|
||||
"narHash": "sha256-6MkqajPICgugsuZ92OMoQcgSHnD6sJHwk8AxvMcIgTE=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "f0927703b7b1c8d97511c4116eb9b4ec6645a0fa",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "f0927703b7b1c8d97511c4116eb9b4ec6645a0fa",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"kfm-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-nixpkgs": {
|
||||
"nixpkgs-x86_64-darwin": {
|
||||
"locked": {
|
||||
"lastModified": 1767364772,
|
||||
"narHash": "sha256-fFUnEYMla8b7UKjijLnMe+oVFOz6HjijGGNS1l7dYaQ=",
|
||||
@@ -378,119 +133,14 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1765674936,
|
||||
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-rust-overlay": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"kfm-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1793174968,
|
||||
"narHash": "sha256-u5nUf4cewaT36iIzG1s/VECktqUMiZaGF5BsgervsvQ=",
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "19ecdd08213836b36c4296a3a4f4af5a3d5308db",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "oxalica",
|
||||
"repo": "rust-overlay",
|
||||
"rev": "19ecdd08213836b36c4296a3a4f4af5a3d5308db",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"kfm-treefmt-nix": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"kfm-nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767468822,
|
||||
"narHash": "sha256-MpffQxHxmjVKMiQd0Tg2IM/bSjjdQAM+NDcX6yxj7rE=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "d56486eb9493ad9c4777c65932618e9c2d0468fc",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "d56486eb9493ad9c4777c65932618e9c2d0468fc",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1766870016,
|
||||
"narHash": "sha256-fHmxAesa6XNqnIkcS6+nIHuEmgd/iZSP/VXxweiEuQw=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "5c2bc52fb9f8c264ed6c93bd20afa2ff5e763dce",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1765674936,
|
||||
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"asc": "asc",
|
||||
"crane": "crane",
|
||||
"flake-parts": "flake-parts",
|
||||
"git-hooks-nix": "git-hooks-nix",
|
||||
"kfde-crane": "kfde-crane",
|
||||
"kfde-flake-compat": "kfde-flake-compat",
|
||||
"kfde-flake-parts": "kfde-flake-parts",
|
||||
"kfde-git-hooks-nix": "kfde-git-hooks-nix",
|
||||
"kfde-nixpkgs": "kfde-nixpkgs",
|
||||
"kfde-nixpkgs-lib": "kfde-nixpkgs-lib",
|
||||
"kfde-rust-overlay": "kfde-rust-overlay",
|
||||
"kfde-treefmt-nix": "kfde-treefmt-nix",
|
||||
"kfm-crane": "kfm-crane",
|
||||
"kfm-flake-compat": "kfm-flake-compat",
|
||||
"kfm-flake-parts": "kfm-flake-parts",
|
||||
"kfm-git-hooks-nix": "kfm-git-hooks-nix",
|
||||
"kfm-gitignore": "kfm-gitignore",
|
||||
"kfm-nixpkgs": "kfm-nixpkgs",
|
||||
"kfm-nixpkgs-lib": "kfm-nixpkgs-lib",
|
||||
"kfm-rust-overlay": "kfm-rust-overlay",
|
||||
"kfm-treefmt-nix": "kfm-treefmt-nix",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-x86_64-darwin": "nixpkgs-x86_64-darwin",
|
||||
"rust-overlay": "rust-overlay",
|
||||
"treefmt-nix": "treefmt-nix"
|
||||
}
|
||||
@@ -522,11 +172,11 @@
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1766000401,
|
||||
"narHash": "sha256-+cqN4PJz9y0JQXfAK5J1drd0U05D5fcAGhzhfVrDlsI=",
|
||||
"lastModified": 1791885023,
|
||||
"narHash": "sha256-C3alQ2MEt0zVrUSho5NUDo3jmhbff72++bfwoqT9Omo=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "42d96e75aa56a3f70cab7e7dc4a32868db28e8fd",
|
||||
"rev": "0d6d739a833ba9a9c93034862e4a7b061a062a1c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
{
|
||||
description = "komorebi for Windows";
|
||||
description = "komorebi, a tiling window manager for Windows, KDE Plasma and macOS";
|
||||
|
||||
inputs = {
|
||||
# One nixpkgs for the three platforms. The KDE VM tests run against the Plasma and KWin of this
|
||||
# revision (nix/linux/supported-kwin.nix says which KWin that is), so it is the one an update has
|
||||
# to keep green for the VM suites; see docs/dev/flake.md.
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
# Intel Macs only: nixpkgs 26.11 dropped x86_64-darwin (evaluating it throws), so the x86_64-darwin
|
||||
# outputs use the last revision that still supported it, the one the macOS flake was pinned to.
|
||||
# Nothing else uses it; drop it with x86_64-darwin when Intel Macs are no longer supported.
|
||||
nixpkgs-x86_64-darwin.url = "github:NixOS/nixpkgs/16c7794d0a28b5a37904d55bcca36003b9109aaa";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
crane.url = "github:ipetkov/crane";
|
||||
rust-overlay.url = "github:oxalica/rust-overlay";
|
||||
@@ -11,718 +18,21 @@
|
||||
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
git-hooks-nix.url = "github:cachix/git-hooks.nix";
|
||||
git-hooks-nix.inputs.nixpkgs.follows = "nixpkgs";
|
||||
# the application-specific configuration that komorebic embeds on Windows
|
||||
asc = {
|
||||
url = "github:LGUG2Z/komorebi-application-specific-configuration";
|
||||
flake = false;
|
||||
};
|
||||
|
||||
# the other platforms' flakes (komorebi-for-kde/flake.nix, komorebi-for-mac/flake.nix) are not inputs: their
|
||||
# flake.nix files are imported below and called with these inputs, which are pinned to exactly the
|
||||
# revisions of their flake.lock (so nothing here pins the content of those directories)
|
||||
# inputs of komorebi-for-kde, pinned to the revisions in komorebi-for-kde/flake.lock (keep them equal to it)
|
||||
kfde-nixpkgs.url = "github:NixOS/nixpkgs/f05535a0efcb2134c478d1e88434fadf486d42b5";
|
||||
kfde-nixpkgs-lib.url = "github:nix-community/nixpkgs.lib/f7cd230690d9fc982d06129f9189b101fddcfa3b";
|
||||
kfde-flake-compat = { url = "github:NixOS/flake-compat/5edf11c44bc78a0d334f6334cdaf7d60d732daab"; flake = false; };
|
||||
kfde-flake-parts.url = "github:hercules-ci/flake-parts/024633cd702b10285db5cb19b40ad48d2399ba60";
|
||||
kfde-flake-parts.inputs.nixpkgs-lib.follows = "kfde-nixpkgs-lib";
|
||||
kfde-crane.url = "github:ipetkov/crane/e675a36b7377bebe41d548388a2501cbb16d380d";
|
||||
kfde-rust-overlay.url = "github:oxalica/rust-overlay/19ecdd08213836b36c4296a3a4f4af5a3d5308db";
|
||||
kfde-rust-overlay.inputs.nixpkgs.follows = "kfde-nixpkgs";
|
||||
kfde-treefmt-nix.url = "github:numtide/treefmt-nix/0d6d739a833ba9a9c93034862e4a7b061a062a1c";
|
||||
kfde-treefmt-nix.inputs.nixpkgs.follows = "kfde-nixpkgs";
|
||||
kfde-git-hooks-nix.url = "github:cachix/git-hooks.nix/1ba1dbfe28738c9a71c266be6efa5b89e75491a9";
|
||||
kfde-git-hooks-nix.inputs.nixpkgs.follows = "kfde-nixpkgs";
|
||||
kfde-git-hooks-nix.inputs.flake-compat.follows = "kfde-flake-compat";
|
||||
|
||||
# inputs of komorebi-for-mac, pinned to the revisions in komorebi-for-mac/flake.lock (keep them equal to it)
|
||||
kfm-nixpkgs.url = "github:NixOS/nixpkgs/16c7794d0a28b5a37904d55bcca36003b9109aaa";
|
||||
kfm-nixpkgs-lib.url = "github:nix-community/nixpkgs.lib/2075416fcb47225d9b68ac469a5c4801a9c4dd85";
|
||||
kfm-flake-compat = { url = "github:NixOS/flake-compat/5edf11c44bc78a0d334f6334cdaf7d60d732daab"; flake = false; };
|
||||
kfm-flake-parts.url = "github:hercules-ci/flake-parts/a34fae9c08a15ad73f295041fec82323541400a9";
|
||||
kfm-flake-parts.inputs.nixpkgs-lib.follows = "kfm-nixpkgs-lib";
|
||||
kfm-crane.url = "github:ipetkov/crane/7d59256814085fd9666a2ae3e774dc5ee216b630";
|
||||
kfm-rust-overlay.url = "github:oxalica/rust-overlay/19ecdd08213836b36c4296a3a4f4af5a3d5308db";
|
||||
kfm-rust-overlay.inputs.nixpkgs.follows = "kfm-nixpkgs";
|
||||
kfm-treefmt-nix.url = "github:numtide/treefmt-nix/d56486eb9493ad9c4777c65932618e9c2d0468fc";
|
||||
kfm-treefmt-nix.inputs.nixpkgs.follows = "kfm-nixpkgs";
|
||||
kfm-git-hooks-nix.url = "github:cachix/git-hooks.nix/f0927703b7b1c8d97511c4116eb9b4ec6645a0fa";
|
||||
kfm-git-hooks-nix.inputs.nixpkgs.follows = "kfm-nixpkgs";
|
||||
kfm-git-hooks-nix.inputs.flake-compat.follows = "kfm-flake-compat";
|
||||
kfm-gitignore = { url = "github:hercules-ci/gitignore.nix/637db329424fd7e46cf4185293b9cc8c88c95394"; inputs.nixpkgs.follows = "kfm-nixpkgs"; };
|
||||
kfm-git-hooks-nix.inputs.gitignore.follows = "kfm-gitignore";
|
||||
};
|
||||
|
||||
outputs =
|
||||
inputs@{
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-parts,
|
||||
crane,
|
||||
rust-overlay,
|
||||
...
|
||||
}:
|
||||
let
|
||||
windowsSdkVersion = "10.0.26100";
|
||||
windowsCrtVersion = "14.44.17.14";
|
||||
|
||||
mkWindowsSdk =
|
||||
pkgs:
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "windows-sdk-${windowsSdkVersion}-crt-${windowsCrtVersion}";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.xwin
|
||||
pkgs.cacert
|
||||
];
|
||||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
# hash of `xwin splat --disable-symlinks`: without the flag xwin makes
|
||||
# case-alias symlinks on a case-sensitive filesystem and none on a
|
||||
# case-insensitive one, so the hash depends on the host
|
||||
outputHash = "sha256-YjmEfoxtcmQXvUc+WtaElnyP/4osNvtSI7X6MDaNTjg=";
|
||||
|
||||
buildCommand = ''
|
||||
export HOME=$(mktemp -d)
|
||||
# keep the cache on the same filesystem as $out, as xwin moves
|
||||
# files from the cache into the output and rename(2) fails with
|
||||
# EXDEV when the build dir and the store are separate mounts
|
||||
mkdir -p $out
|
||||
xwin --accept-license \
|
||||
--cache-dir $out/.xwin-cache \
|
||||
--sdk-version ${windowsSdkVersion} \
|
||||
--crt-version ${windowsCrtVersion} \
|
||||
splat --disable-symlinks --output $out
|
||||
rm -rf $out/.xwin-cache
|
||||
'';
|
||||
};
|
||||
|
||||
# the linker asks for `kernel32.lib` of a file that is `Kernel32.lib`, so
|
||||
# on a case-sensitive host add a lowercase alias for every name with a
|
||||
# capital in it, and the spellings the headers include each other by (the
|
||||
# SDK itself is made without symlinks)
|
||||
caseFolded =
|
||||
{ pkgs, windowsSdk }:
|
||||
if pkgs.stdenv.hostPlatform.isDarwin then
|
||||
windowsSdk
|
||||
else
|
||||
pkgs.runCommandLocal "${windowsSdk.name}-case-folded" { } ''
|
||||
cp -rs ${windowsSdk} $out
|
||||
chmod -R u+w $out
|
||||
cd $out
|
||||
find . -name '*[A-Z]*' | while read -r path; do
|
||||
directory=$(dirname "$path")
|
||||
name=$(basename "$path")
|
||||
lower=$(echo "$name" | tr 'A-Z' 'a-z')
|
||||
if [ ! -e "$directory/$lower" ] && [ ! -L "$directory/$lower" ]; then
|
||||
ln -s "$name" "$directory/$lower"
|
||||
fi
|
||||
done
|
||||
|
||||
# headers include each other with spellings that differ from the
|
||||
# file name (`DriverSpecs.h` for `driverspecs.h`), which xwin
|
||||
# covers with symlinks unless told not to
|
||||
grep -Rhoi -E '^[[:space:]]*#[[:space:]]*include[[:space:]]*[<"][^>"]+[>"]' \
|
||||
crt/include sdk/include 2>/dev/null \
|
||||
| sed -E 's/.*[<"]([^>"]+)[>"]/\1/; s#\\#/#g; s#.*/##' \
|
||||
| sort -u > $TMPDIR/spellings
|
||||
find crt/include sdk/include \( -type f -o -type l \) \
|
||||
| awk -v spellings=$TMPDIR/spellings '
|
||||
BEGIN {
|
||||
while ((getline line < spellings) > 0)
|
||||
known[tolower(line)] = known[tolower(line)] "\n" line
|
||||
}
|
||||
{
|
||||
n = split($0, parts, "/"); base = parts[n]
|
||||
dir = substr($0, 1, length($0) - length(base))
|
||||
m = split(known[tolower(base)], names, "\n")
|
||||
for (i = 1; i <= m; i++)
|
||||
if (names[i] != "" && names[i] != base)
|
||||
print dir "\t" base "\t" names[i]
|
||||
}' \
|
||||
| while IFS=$'\t' read -r directory name spelling; do
|
||||
if [ ! -e "$directory$spelling" ] && [ ! -L "$directory$spelling" ]; then
|
||||
ln -s "$name" "$directory$spelling"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
|
||||
mkMsvcEnv =
|
||||
{ pkgs, windowsSdk }:
|
||||
let
|
||||
sdk = caseFolded { inherit pkgs windowsSdk; };
|
||||
clangVersion = pkgs.lib.versions.major pkgs.llvmPackages.clang.version;
|
||||
in
|
||||
{
|
||||
# linker for the windows target
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER = "lld-link";
|
||||
|
||||
# c/c++ compiler
|
||||
CC_x86_64_pc_windows_msvc = "clang-cl";
|
||||
CXX_x86_64_pc_windows_msvc = "clang-cl";
|
||||
AR_x86_64_pc_windows_msvc = "llvm-lib";
|
||||
|
||||
# IMPORTANT: libclang include path MUST come first to avoid header conflicts
|
||||
CFLAGS_x86_64_pc_windows_msvc = builtins.concatStringsSep " " [
|
||||
"--target=x86_64-pc-windows-msvc"
|
||||
"-Wno-unused-command-line-argument"
|
||||
"-fuse-ld=lld-link"
|
||||
"/imsvc${pkgs.llvmPackages.libclang.lib}/lib/clang/${clangVersion}/include"
|
||||
"/imsvc${sdk}/crt/include"
|
||||
"/imsvc${sdk}/sdk/include/ucrt"
|
||||
"/imsvc${sdk}/sdk/include/um"
|
||||
"/imsvc${sdk}/sdk/include/shared"
|
||||
];
|
||||
|
||||
CXXFLAGS_x86_64_pc_windows_msvc = builtins.concatStringsSep " " [
|
||||
"--target=x86_64-pc-windows-msvc"
|
||||
"-Wno-unused-command-line-argument"
|
||||
"-fuse-ld=lld-link"
|
||||
"/imsvc${pkgs.llvmPackages.libclang.lib}/lib/clang/${clangVersion}/include"
|
||||
"/imsvc${sdk}/crt/include"
|
||||
"/imsvc${sdk}/sdk/include/ucrt"
|
||||
"/imsvc${sdk}/sdk/include/um"
|
||||
"/imsvc${sdk}/sdk/include/shared"
|
||||
];
|
||||
|
||||
# target-specific rust flags with linker flavor and library search paths
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS = builtins.concatStringsSep " " [
|
||||
"-Clinker-flavor=lld-link"
|
||||
"-Lnative=${sdk}/crt/lib/x86_64"
|
||||
"-Lnative=${sdk}/sdk/lib/um/x86_64"
|
||||
"-Lnative=${sdk}/sdk/lib/ucrt/x86_64"
|
||||
];
|
||||
|
||||
# cargo target
|
||||
CARGO_BUILD_TARGET = "x86_64-pc-windows-msvc";
|
||||
};
|
||||
|
||||
mkKomorebiPackages =
|
||||
{
|
||||
pkgs,
|
||||
windowsSdk,
|
||||
# the commit stamped into the binaries; a build for the e2e guest
|
||||
# gives a constant one, so that a new commit does not rebuild it
|
||||
commit ? self.rev or (pkgs.lib.removeSuffix "-dirty" (self.dirtyRev or "unknown")),
|
||||
}:
|
||||
let
|
||||
# toolchain with windows msvc target
|
||||
toolchain = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml).override {
|
||||
targets = [ "x86_64-pc-windows-msvc" ];
|
||||
};
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||
version = "0.1.0";
|
||||
|
||||
msvcEnv = mkMsvcEnv { inherit pkgs windowsSdk; };
|
||||
|
||||
# the files of the Windows crates; the KDE and macOS crates are in the same Cargo workspace and
|
||||
# are added as stubs (nix/workspace-src.nix), so that an edit of one changes nothing here
|
||||
real = pkgs.lib.cleanSourceWith {
|
||||
src = ./.;
|
||||
filter =
|
||||
path: type:
|
||||
# the other platforms' crates are added as stubs below
|
||||
!(pkgs.lib.hasInfix "/komorebi-for-kde" path || pkgs.lib.hasInfix "/komorebi-for-mac" path)
|
||||
# the Linux and macOS files of komorebic are not read when building for Windows
|
||||
&& !(builtins.match ".*/komorebi(c/(src/(linux|macos)|tests/(linux|macos)_)|-client/(src/(linux|macos)\\.rs|tests/(linux|macos)_)|-bar/src/macos|-daemon/tests/(linux|macos)_)[^/]*.*" path != null)
|
||||
&& (
|
||||
(craneLib.filterCargoSources path type)
|
||||
|| (pkgs.lib.hasInfix "/docs/" path)
|
||||
|| (builtins.match ".*/docs/.*" path != null)
|
||||
|| (builtins.match ".*/komorebic/fixtures/.*" path != null)
|
||||
);
|
||||
};
|
||||
|
||||
src = import ./nix/workspace-src.nix {
|
||||
inherit pkgs real;
|
||||
repoRoot = ./.;
|
||||
isReal = member: !(pkgs.lib.hasPrefix "komorebi-for-" member);
|
||||
};
|
||||
|
||||
lockFile = builtins.path {
|
||||
path = ./Cargo.lock;
|
||||
name = "Cargo.lock";
|
||||
};
|
||||
tomlFile = builtins.path {
|
||||
path = ./Cargo.toml;
|
||||
name = "Cargo.toml";
|
||||
};
|
||||
|
||||
commonArgs = {
|
||||
inherit src version;
|
||||
# the lock and the root manifest as files of their own: a path inside the filtered source would put the
|
||||
# whole filtered source into the context of every derivation, and then an edit of any file
|
||||
# would change the dependencies
|
||||
cargoLock = lockFile;
|
||||
cargoToml = tomlFile;
|
||||
cargoVendorDir = craneLib.vendorCargoDeps { cargoLock = lockFile; };
|
||||
strictDeps = true;
|
||||
# applications.json is committed now; this copies the pinned asc input over it, so that the
|
||||
# embedded file is the pinned one even when the committed copy is older
|
||||
preBuild = "mkdir -p komorebic && cp ${inputs.asc}/applications.json komorebic/applications.json";
|
||||
# a constant, so that the dependencies and every check are the same
|
||||
# derivations for every commit; only fullBuild stamps the real one
|
||||
COMMIT_HASH = "nix-check";
|
||||
|
||||
# build inputs for cross-compilation
|
||||
nativeBuildInputs = [
|
||||
pkgs.llvmPackages.clang-unwrapped
|
||||
pkgs.llvmPackages.lld
|
||||
pkgs.llvmPackages.llvm
|
||||
# komorebic build script uses reqwest, which runs on the build host
|
||||
pkgs.pkg-config
|
||||
pkgs.openssl
|
||||
pkgs.openssl.dev
|
||||
];
|
||||
|
||||
# point the host-side openssl-sys build at the nix openssl
|
||||
OPENSSL_NO_VENDOR = "1";
|
||||
OPENSSL_LIB_DIR = "${pkgs.openssl.out}/lib";
|
||||
OPENSSL_INCLUDE_DIR = "${pkgs.openssl.dev}/include";
|
||||
|
||||
# cross-compilation environment
|
||||
inherit (msvcEnv)
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER
|
||||
CC_x86_64_pc_windows_msvc
|
||||
CXX_x86_64_pc_windows_msvc
|
||||
AR_x86_64_pc_windows_msvc
|
||||
CFLAGS_x86_64_pc_windows_msvc
|
||||
CXXFLAGS_x86_64_pc_windows_msvc
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS
|
||||
CARGO_BUILD_TARGET
|
||||
;
|
||||
};
|
||||
|
||||
cargoArtifacts = craneLib.buildDepsOnly commonArgs;
|
||||
|
||||
individualCrateArgs = commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
doDoc = false;
|
||||
};
|
||||
|
||||
fullBuild = craneLib.buildPackage (
|
||||
individualCrateArgs
|
||||
// {
|
||||
pname = "komorebi-workspace";
|
||||
COMMIT_HASH = commit;
|
||||
}
|
||||
);
|
||||
|
||||
extractBinary =
|
||||
binaryName:
|
||||
pkgs.runCommand "komorebi-${binaryName}"
|
||||
{
|
||||
meta = fullBuild.meta // { };
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${fullBuild}/bin/${binaryName}.exe $out/bin/
|
||||
'';
|
||||
in
|
||||
{
|
||||
inherit
|
||||
craneLib
|
||||
src
|
||||
real
|
||||
individualCrateArgs
|
||||
fullBuild
|
||||
msvcEnv
|
||||
;
|
||||
komorebi = extractBinary "komorebi";
|
||||
komorebic = extractBinary "komorebic";
|
||||
komorebic-no-console = extractBinary "komorebic-no-console";
|
||||
komorebi-bar = extractBinary "komorebi-bar";
|
||||
komorebi-gui = extractBinary "komorebi-gui";
|
||||
komorebi-shortcuts = extractBinary "komorebi-shortcuts";
|
||||
komorebi-testwin = extractBinary "komorebi-testwin";
|
||||
komorebi-e2e-agent = extractBinary "komorebi-e2e-agent";
|
||||
};
|
||||
|
||||
mkPkgs =
|
||||
system:
|
||||
import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [ (import rust-overlay) ];
|
||||
};
|
||||
in
|
||||
inputs@{ flake-parts, ... }:
|
||||
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||
systems = [
|
||||
"aarch64-darwin"
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
|
||||
imports = [
|
||||
inputs.treefmt-nix.flakeModule
|
||||
inputs.git-hooks-nix.flakeModule
|
||||
# komorebi for KDE Plasma (kfde) and komorebi for macOS (kfm), re-exported with a prefix.
|
||||
# Their flakes keep their own inputs and lock files (inputs.<name>.inputs), but their
|
||||
# outputs are made here, from the whole repository as the source: the Rust workspaces of
|
||||
# both depend on the crates of this tree by path, which a flake of their own directory
|
||||
# cannot see (their `lib.mkOutputs`). The VM tests of kfde are not re-exported as checks,
|
||||
# so that `nix flake check` of this flake does not boot them; they are reachable as
|
||||
# legacyPackages.<system>.kfde-vm.
|
||||
(
|
||||
{ lib, ... }:
|
||||
let
|
||||
# the nested flake.nix files are plain attribute sets: import them and call their
|
||||
# `lib.mkOutputs` with the inputs declared above (same revisions as their own locks).
|
||||
# `self` of a nested flake: its own outputs, with the revision and the path of this one
|
||||
nestedOutputs =
|
||||
name: dir:
|
||||
let
|
||||
nestedInputs = lib.genAttrs [
|
||||
"nixpkgs"
|
||||
"flake-parts"
|
||||
"crane"
|
||||
"rust-overlay"
|
||||
"treefmt-nix"
|
||||
"git-hooks-nix"
|
||||
] (n: inputs."${name}-${n}");
|
||||
mkOutputs =
|
||||
((import (self.outPath + "/${dir}/flake.nix")).outputs (nestedInputs // { inherit self; })).lib.mkOutputs;
|
||||
nestedSelf =
|
||||
outputs
|
||||
// lib.filterAttrs (n: _: n == "rev" || n == "dirtyRev") self
|
||||
// {
|
||||
outPath = self.outPath + "/${dir}";
|
||||
inputs = nestedInputs;
|
||||
};
|
||||
outputs = mkOutputs {
|
||||
self = nestedSelf;
|
||||
inputs = nestedInputs // {
|
||||
self = nestedSelf;
|
||||
};
|
||||
repoRoot = self;
|
||||
platformDir = dir;
|
||||
};
|
||||
in
|
||||
outputs;
|
||||
kfde = nestedOutputs "kfde" "komorebi-for-kde";
|
||||
kfm = nestedOutputs "kfm" "komorebi-for-mac";
|
||||
in
|
||||
{
|
||||
flake = {
|
||||
nixosModules.komorebi-for-kde = kfde.nixosModules.default;
|
||||
overlays.komorebi-for-kde = kfde.overlays.default;
|
||||
darwinModules.komorebi-for-mac = kfm.darwinModules.default;
|
||||
};
|
||||
|
||||
perSystem =
|
||||
{ system, ... }:
|
||||
let
|
||||
prefixed = prefix: lib.mapAttrs' (name: lib.nameValuePair "${prefix}-${name}");
|
||||
withoutVmTests = lib.filterAttrs (name: _: !(lib.hasPrefix "vm-" name));
|
||||
in
|
||||
{
|
||||
packages =
|
||||
prefixed "kfde" (kfde.packages.${system} or { }) // prefixed "kfm" (kfm.packages.${system} or { });
|
||||
checks =
|
||||
prefixed "kfde" (withoutVmTests (kfde.checks.${system} or { }))
|
||||
// prefixed "kfm" (kfm.checks.${system} or { });
|
||||
legacyPackages.kfde-vm = (kfde.legacyPackages.${system} or { }).vm or { };
|
||||
};
|
||||
}
|
||||
)
|
||||
./nix/common.nix
|
||||
./nix/windows/flake-module.nix
|
||||
./nix/linux/flake-module.nix
|
||||
./nix/macos/flake-module.nix
|
||||
];
|
||||
|
||||
perSystem =
|
||||
{ config, system, ... }:
|
||||
let
|
||||
pkgs = mkPkgs system;
|
||||
windowsSdk = mkWindowsSdk pkgs;
|
||||
build = mkKomorebiPackages { inherit pkgs windowsSdk; };
|
||||
# the binaries the e2e guest runs: the same build, but with a
|
||||
# constant commit stamp, so a new commit (or a dirty tree) that does
|
||||
# not change a source file reuses it. The commit under test is
|
||||
# KOMOREBI_E2E_COMMIT, not what the binary says.
|
||||
e2eBuild = mkKomorebiPackages {
|
||||
inherit pkgs windowsSdk;
|
||||
commit = "e2e";
|
||||
};
|
||||
|
||||
# OVMF without SMM and with the TPM support Windows 11 Setup asks for
|
||||
ovmfWithTpm = (pkgs.OVMF.override { tpmSupport = true; }).fd;
|
||||
e2eWindows = pkgs.writeShellApplication {
|
||||
name = "e2e-windows";
|
||||
runtimeInputs = [
|
||||
pkgs.qemu
|
||||
pkgs.swtpm
|
||||
(pkgs.python3.withPackages (p: [ p.pillow ]))
|
||||
];
|
||||
text = ''
|
||||
: "''${E2E_GOLDEN:?set E2E_GOLDEN to the golden image directory}"
|
||||
out=''${1:?usage: e2e-windows OUT SCENARIO...}
|
||||
shift
|
||||
# the binaries under test: this checkout's, or those of another
|
||||
# commit, made by e2e/platforms/qemu_windows/build-ref.sh
|
||||
if [ -n "''${KOMOREBI_E2E_BINS:-}" ]; then
|
||||
bins=$KOMOREBI_E2E_BINS
|
||||
if [ -f "$bins/commit" ]; then
|
||||
KOMOREBI_E2E_COMMIT=$(cat "$bins/commit")
|
||||
fi
|
||||
else
|
||||
bins=$(mktemp -d)
|
||||
trap 'rm -rf "$bins"' EXIT
|
||||
cp ${e2eBuild.komorebi}/bin/komorebi.exe "$bins"
|
||||
cp ${e2eBuild.komorebic}/bin/komorebic.exe "$bins"
|
||||
cp ${e2eBuild.komorebi-testwin}/bin/komorebi-testwin.exe "$bins"
|
||||
cp ${e2eBuild.komorebi-bar}/bin/komorebi-bar.exe "$bins"
|
||||
fi
|
||||
export OVMF_FD=${ovmfWithTpm}
|
||||
export KOMOREBI_E2E_BAR_SCHEMA=${./schema.bar.json}
|
||||
export KOMOREBI_E2E_COMMIT=''${KOMOREBI_E2E_COMMIT:-${self.rev or "dirty"}}
|
||||
export PYTHONPATH=${./e2e/lib}:${./e2e}
|
||||
exec python -m platforms.qemu_windows.run \
|
||||
"$E2E_GOLDEN" "$bins" "$out" "$@"
|
||||
'';
|
||||
};
|
||||
|
||||
# toolchain with windows target and nightly rustfmt
|
||||
rustToolchain = (pkgs.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml).override {
|
||||
targets = [ "x86_64-pc-windows-msvc" ];
|
||||
};
|
||||
nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
rustToolchainWithNightlyRustfmt = pkgs.symlinkJoin {
|
||||
name = "rust-toolchain-with-nightly-rustfmt";
|
||||
paths = [
|
||||
nightlyRustfmt
|
||||
rustToolchain
|
||||
];
|
||||
};
|
||||
nightlyToolchain = pkgs.rust-bin.nightly.latest.default.override {
|
||||
targets = [ "x86_64-pc-windows-msvc" ];
|
||||
};
|
||||
cargo-udeps = pkgs.writeShellScriptBin "cargo-udeps" ''
|
||||
export PATH="${nightlyToolchain}/bin:$PATH"
|
||||
exec ${pkgs.cargo-udeps}/bin/cargo-udeps "$@"
|
||||
'';
|
||||
in
|
||||
{
|
||||
treefmt = {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
deadnix.enable = true;
|
||||
just.enable = true;
|
||||
nixfmt.enable = true;
|
||||
taplo.enable = true;
|
||||
rustfmt = {
|
||||
enable = true;
|
||||
package = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
checks = {
|
||||
komorebi-workspace-clippy = build.craneLib.cargoClippy (
|
||||
build.individualCrateArgs
|
||||
// {
|
||||
cargoClippyExtraArgs = "--all-targets -- -D warnings";
|
||||
}
|
||||
);
|
||||
|
||||
# the nightly rustfmt over the Windows files, as tools/format-all --tree windows does locally. Not
|
||||
# `cargo fmt`: it ran the stable rustfmt (which ignores the nightly options of rustfmt.toml) over
|
||||
# the stub sources of the other platforms and followed `mod linux;` into files the Windows source
|
||||
# does not have.
|
||||
komorebi-workspace-fmt =
|
||||
pkgs.runCommand "komorebi-workspace-fmt"
|
||||
{
|
||||
nativeBuildInputs = [ nightlyRustfmt ];
|
||||
}
|
||||
''
|
||||
RUSTFMT=rustfmt bash ${./tools/format-all} --check --tree windows --root ${build.real}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
komorebi-workspace-toml-fmt = build.craneLib.taploFmt {
|
||||
src = pkgs.lib.sources.sourceFilesBySuffices build.real [ ".toml" ];
|
||||
};
|
||||
|
||||
# cargo deny sees every member of the workspace: leave out the KDE and macOS packages, which
|
||||
# have their own policy (komorebi-for-*/deny.toml) in their own checks
|
||||
komorebi-workspace-deny = build.craneLib.cargoDeny {
|
||||
inherit (build) src;
|
||||
pname = "komorebi-workspace";
|
||||
version = "0.1.0";
|
||||
cargoToml = "${build.real}/Cargo.toml";
|
||||
cargoLock = "${build.real}/Cargo.lock";
|
||||
cargoDenyExtraArgs =
|
||||
"--workspace "
|
||||
+ pkgs.lib.concatMapStringsSep " " (p: "--exclude ${p}") [
|
||||
"komorebi-linux"
|
||||
"komorebic-linux"
|
||||
"komorebi-client-linux"
|
||||
"komorebi-hotkeys"
|
||||
"version-linux"
|
||||
"komorebi-macos"
|
||||
"komorebic-macos"
|
||||
"komorebi-client-macos"
|
||||
"komorebi-bar-macos"
|
||||
"version-macos"
|
||||
];
|
||||
};
|
||||
|
||||
komorebi-workspace-nextest = build.craneLib.cargoNextest build.individualCrateArgs;
|
||||
|
||||
# the Python of the Windows e2e guest that needs no guest: the
|
||||
# vendored core's tests and those of the runner
|
||||
e2e-tests =
|
||||
pkgs.runCommand "e2e-tests"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
pkgs.git
|
||||
(pkgs.python3.withPackages (p: [
|
||||
p.pillow
|
||||
p.pytest
|
||||
]))
|
||||
];
|
||||
}
|
||||
''
|
||||
cp -r ${./e2e} e2e
|
||||
chmod -R u+w e2e
|
||||
cd e2e
|
||||
export HOME=$TMPDIR PYTHONPATH=$PWD/lib:$PWD
|
||||
python -m pytest -q -p no:cacheprovider lib/tests platforms/qemu_windows/tests
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
|
||||
packages = {
|
||||
inherit (build)
|
||||
komorebi
|
||||
komorebic
|
||||
komorebic-no-console
|
||||
komorebi-bar
|
||||
komorebi-gui
|
||||
komorebi-shortcuts
|
||||
komorebi-testwin
|
||||
komorebi-e2e-agent
|
||||
;
|
||||
inherit windowsSdk;
|
||||
# the test window of the Windows e2e guest, built with the constant
|
||||
# stamp: a new commit does not rebuild what it depends on
|
||||
komorebi-testwin-e2e = e2eBuild.komorebi-testwin;
|
||||
komorebi-full = build.fullBuild;
|
||||
default = build.fullBuild;
|
||||
};
|
||||
|
||||
apps = {
|
||||
komorebi = {
|
||||
type = "app";
|
||||
program = "${build.komorebi}/bin/komorebi.exe";
|
||||
};
|
||||
komorebic = {
|
||||
type = "app";
|
||||
program = "${build.komorebic}/bin/komorebic.exe";
|
||||
};
|
||||
komorebic-no-console = {
|
||||
type = "app";
|
||||
program = "${build.komorebic-no-console}/bin/komorebic-no-console.exe";
|
||||
};
|
||||
komorebi-bar = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-bar}/bin/komorebi-bar.exe";
|
||||
};
|
||||
komorebi-gui = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-gui}/bin/komorebi-gui.exe";
|
||||
};
|
||||
komorebi-shortcuts = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-shortcuts}/bin/komorebi-shortcuts.exe";
|
||||
};
|
||||
default = {
|
||||
type = "app";
|
||||
program = "${build.fullBuild}/bin/komorebi.exe";
|
||||
};
|
||||
}
|
||||
// pkgs.lib.optionalAttrs (system == "x86_64-linux") {
|
||||
# the neutral scenarios against a throwaway Windows guest:
|
||||
# E2E_GOLDEN=<golden image dir> nix run .#e2e-windows -- \
|
||||
# OUT SCENARIO...
|
||||
# KOMOREBI_E2E_BINS=<dir from build-ref.sh> tests another commit
|
||||
# the golden image is built once with
|
||||
# e2e/platforms/qemu_windows/build-golden.sh
|
||||
e2e-windows = {
|
||||
type = "app";
|
||||
program = pkgs.lib.getExe e2eWindows;
|
||||
};
|
||||
};
|
||||
|
||||
devShells.default = pkgs.mkShell {
|
||||
name = "komorebi";
|
||||
|
||||
RUST_BACKTRACE = "full";
|
||||
|
||||
# komorebic's build script runs on the host and wants OpenSSL, as in
|
||||
# the nix build
|
||||
OPENSSL_NO_VENDOR = "1";
|
||||
OPENSSL_LIB_DIR = "${pkgs.openssl.out}/lib";
|
||||
OPENSSL_INCLUDE_DIR = "${pkgs.openssl.dev}/include";
|
||||
|
||||
# the Windows e2e guest (e2e/platforms/qemu_windows): the build
|
||||
# scripts and the runner find OVMF here, and the vendored core
|
||||
# and the platform on PYTHONPATH
|
||||
OVMF_FD = "${ovmfWithTpm}";
|
||||
shellHook = ''
|
||||
export PYTHONPATH="$PWD/e2e/lib:$PWD/e2e''${PYTHONPATH:+:$PYTHONPATH}"
|
||||
'';
|
||||
|
||||
# cross-compilation environment
|
||||
inherit (build.msvcEnv)
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER
|
||||
CC_x86_64_pc_windows_msvc
|
||||
CXX_x86_64_pc_windows_msvc
|
||||
AR_x86_64_pc_windows_msvc
|
||||
CFLAGS_x86_64_pc_windows_msvc
|
||||
CXXFLAGS_x86_64_pc_windows_msvc
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS
|
||||
CARGO_BUILD_TARGET
|
||||
;
|
||||
|
||||
packages = [
|
||||
rustToolchainWithNightlyRustfmt
|
||||
cargo-udeps
|
||||
|
||||
# cross-compilation tooling
|
||||
pkgs.llvmPackages.clang-unwrapped # provides clang-cl
|
||||
pkgs.llvmPackages.lld # provides lld-link
|
||||
pkgs.llvmPackages.llvm # provides llvm-lib
|
||||
|
||||
# komorebic's build script (reqwest) runs on the build host
|
||||
pkgs.pkg-config
|
||||
pkgs.openssl
|
||||
|
||||
pkgs.cargo-deny
|
||||
pkgs.cargo-nextest
|
||||
pkgs.cargo-outdated
|
||||
pkgs.jq
|
||||
pkgs.just
|
||||
pkgs.prettier
|
||||
|
||||
# the Windows e2e guest
|
||||
pkgs.qemu
|
||||
pkgs.swtpm
|
||||
pkgs.xorriso
|
||||
pkgs.socat
|
||||
pkgs.git
|
||||
(pkgs.python3.withPackages (p: [
|
||||
p.pillow
|
||||
p.pytest # the tests of e2e/lib
|
||||
]))
|
||||
];
|
||||
};
|
||||
|
||||
pre-commit = {
|
||||
check.enable = true;
|
||||
settings.hooks.treefmt = {
|
||||
enable = true;
|
||||
package = config.treefmt.build.wrapper;
|
||||
pass_filenames = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
# What the three platforms share: the systems, nixpkgs with the rust overlay, the formatter, the
|
||||
# pre-commit hook and the dev shell.
|
||||
{ inputs, self, ... }:
|
||||
let
|
||||
lib' = import ./lib.nix { inherit inputs; };
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
# pkgs of every perSystem module (a module of its own: one that takes `pkgs` cannot define it)
|
||||
{
|
||||
perSystem =
|
||||
{ system, ... }:
|
||||
{
|
||||
_module.args.pkgs = lib'.mkPkgs system;
|
||||
};
|
||||
}
|
||||
inputs.treefmt-nix.flakeModule
|
||||
inputs.git-hooks-nix.flakeModule
|
||||
];
|
||||
|
||||
# Linux and Windows (cross) builds on both Linux architectures, macOS on both Apple ones.
|
||||
# x86_64-darwin uses an older nixpkgs (flake.nix, input nixpkgs-x86_64-darwin).
|
||||
systems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
"x86_64-darwin"
|
||||
];
|
||||
|
||||
flake = {
|
||||
# the packages of the platform of the system the overlay is applied to: the Linux ones (overlays.linux,
|
||||
# nix/linux/flake-module.nix) or the macOS ones (overlays.macos)
|
||||
overlays.default =
|
||||
final: prev:
|
||||
(if final.stdenv.hostPlatform.isDarwin then self.overlays.macos else self.overlays.linux) final
|
||||
prev;
|
||||
overlays.komorebi = self.overlays.default;
|
||||
};
|
||||
|
||||
perSystem =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
system,
|
||||
msvcEnv,
|
||||
ovmfWithTpm,
|
||||
...
|
||||
}:
|
||||
let
|
||||
crossToWindows = builtins.elem system lib'.windowsSystems;
|
||||
# the toolchain of rust-toolchain.toml, with the Windows target on the systems that cross-build
|
||||
rustToolchain =
|
||||
let
|
||||
stable = pkgs.rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
|
||||
in
|
||||
if crossToWindows then stable.override { targets = [ "x86_64-pc-windows-msvc" ]; } else stable;
|
||||
nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
rustToolchainWithNightlyRustfmt = pkgs.symlinkJoin {
|
||||
name = "rust-toolchain-with-nightly-rustfmt";
|
||||
paths = [
|
||||
nightlyRustfmt
|
||||
rustToolchain
|
||||
];
|
||||
};
|
||||
nightlyToolchain = pkgs.rust-bin.nightly.latest.default.override {
|
||||
targets = pkgs.lib.optional crossToWindows "x86_64-pc-windows-msvc";
|
||||
};
|
||||
# cargo-udeps needs a nightly compiler
|
||||
cargo-udeps = pkgs.writeShellScriptBin "cargo-udeps" ''
|
||||
export PATH="${nightlyToolchain}/bin:$PATH"
|
||||
exec ${pkgs.cargo-udeps}/bin/cargo-udeps "$@"
|
||||
'';
|
||||
|
||||
# the tools of every platform's development
|
||||
tools = [
|
||||
rustToolchainWithNightlyRustfmt
|
||||
cargo-udeps
|
||||
|
||||
# cross-compilation tooling for Windows (xwin): clang-cl, lld-link, llvm-lib
|
||||
pkgs.llvmPackages.clang-unwrapped
|
||||
pkgs.llvmPackages.lld
|
||||
pkgs.llvmPackages.llvm
|
||||
|
||||
# komorebic's build script (reqwest) runs on the build host
|
||||
pkgs.pkg-config
|
||||
pkgs.openssl
|
||||
|
||||
pkgs.cargo-deny
|
||||
pkgs.cargo-nextest
|
||||
pkgs.cargo-outdated
|
||||
pkgs.check-jsonschema
|
||||
pkgs.jq
|
||||
pkgs.just
|
||||
pkgs.prettier
|
||||
pkgs.ripgrep
|
||||
|
||||
# the tests of the sleep and lock signals of the KDE daemon start private buses (`kwin::power`)
|
||||
pkgs.dbus
|
||||
|
||||
# the KDE bridge's type check and tests (`just check-js`)
|
||||
pkgs.nodejs
|
||||
pkgs.typescript
|
||||
|
||||
# the VM test library of the KDE suites
|
||||
pkgs.ruff
|
||||
pkgs.ty
|
||||
|
||||
# the Windows e2e guest (e2e/platforms/qemu_windows) and the tests of e2e/lib
|
||||
pkgs.qemu
|
||||
pkgs.swtpm
|
||||
pkgs.xorriso
|
||||
pkgs.socat
|
||||
pkgs.git
|
||||
(pkgs.python3.withPackages (p: [
|
||||
p.pillow
|
||||
p.pytest
|
||||
]))
|
||||
]
|
||||
# publishes the schema site of the macOS tree
|
||||
++ pkgs.lib.optional pkgs.stdenv.hostPlatform.isDarwin pkgs.wrangler;
|
||||
|
||||
mkDevShell =
|
||||
{
|
||||
name,
|
||||
# the cross-compilation environment of the Windows build: CARGO_BUILD_TARGET makes every
|
||||
# `cargo` command build for Windows, so a shell that builds the Linux or macOS packages
|
||||
# natively leaves it out
|
||||
cross,
|
||||
}:
|
||||
pkgs.mkShell (
|
||||
{
|
||||
inherit name;
|
||||
|
||||
RUST_BACKTRACE = "full";
|
||||
|
||||
# komorebic's build script runs on the host and wants OpenSSL, as in
|
||||
# the nix build
|
||||
OPENSSL_NO_VENDOR = "1";
|
||||
OPENSSL_LIB_DIR = "${pkgs.openssl.out}/lib";
|
||||
OPENSSL_INCLUDE_DIR = "${pkgs.openssl.dev}/include";
|
||||
|
||||
packages = tools;
|
||||
}
|
||||
// pkgs.lib.optionalAttrs (crossToWindows) {
|
||||
# the Windows e2e guest (e2e/platforms/qemu_windows): the build
|
||||
# scripts and the runner find OVMF here, and the vendored core
|
||||
# and the platform on PYTHONPATH
|
||||
OVMF_FD = "${ovmfWithTpm}";
|
||||
shellHook = ''
|
||||
export PYTHONPATH="$PWD/e2e/lib:$PWD/e2e''${PYTHONPATH:+:$PYTHONPATH}"
|
||||
'';
|
||||
}
|
||||
// pkgs.lib.optionalAttrs (cross && crossToWindows) {
|
||||
# cross-compilation environment
|
||||
inherit (msvcEnv)
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER
|
||||
CC_x86_64_pc_windows_msvc
|
||||
CXX_x86_64_pc_windows_msvc
|
||||
AR_x86_64_pc_windows_msvc
|
||||
CFLAGS_x86_64_pc_windows_msvc
|
||||
CXXFLAGS_x86_64_pc_windows_msvc
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS
|
||||
CARGO_BUILD_TARGET
|
||||
;
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
treefmt = {
|
||||
projectRootFile = "flake.nix";
|
||||
programs = {
|
||||
deadnix.enable = true;
|
||||
just.enable = true;
|
||||
nixfmt.enable = true;
|
||||
taplo.enable = true;
|
||||
rustfmt = {
|
||||
enable = true;
|
||||
package = nightlyRustfmt;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# `nix develop`: everything the three platforms need, and the Windows cross-compilation
|
||||
# environment (cargo builds for x86_64-pc-windows-msvc by default). `nix develop .#native` is the
|
||||
# same without it, for `cargo` commands on the Linux or macOS packages (-p komorebi-linux, ...).
|
||||
devShells = {
|
||||
default = mkDevShell {
|
||||
name = "komorebi";
|
||||
cross = true;
|
||||
};
|
||||
native = mkDevShell {
|
||||
name = "komorebi-native";
|
||||
cross = false;
|
||||
};
|
||||
};
|
||||
|
||||
pre-commit = {
|
||||
check.enable = true;
|
||||
settings.hooks.treefmt = {
|
||||
enable = true;
|
||||
package = config.treefmt.build.wrapper;
|
||||
pass_filenames = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Helpers shared by the platform modules of the flake.
|
||||
{ inputs }:
|
||||
rec {
|
||||
# the repository, as the source of the flake
|
||||
repoRoot = ./..;
|
||||
|
||||
# a file or directory of the repository as a store path of its own: `./tools/format-all` would name
|
||||
# a place in the store path of the whole flake source, which changes with every edit of the
|
||||
# repository and so would rebuild the derivation that reads it
|
||||
repoFile =
|
||||
rel:
|
||||
builtins.path {
|
||||
path = repoRoot + "/${rel}";
|
||||
name = builtins.baseNameOf rel;
|
||||
};
|
||||
|
||||
# the version of the workspace: every package says `version.workspace = true`
|
||||
version =
|
||||
(builtins.fromTOML (builtins.readFile (repoRoot + "/Cargo.toml"))).workspace.package.version;
|
||||
|
||||
# the systems that cross-build for Windows, build the Linux packages and build the macOS packages
|
||||
windowsSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
linuxSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
];
|
||||
# Apple silicon also gets the checks of the KDE crates (they run against a fake desktop)
|
||||
linuxCheckSystems = linuxSystems ++ [ "aarch64-darwin" ];
|
||||
macosSystems = [
|
||||
"aarch64-darwin"
|
||||
"x86_64-darwin"
|
||||
];
|
||||
|
||||
# The manifests (Cargo.toml, Cargo.lock, build scripts, .cargo/config.toml) of every member of the
|
||||
# workspace, of all three platforms, and nothing else: crane makes the dummy source of the dependency
|
||||
# derivations from it. A pure path (no derivation), so that crane reads it at evaluation without
|
||||
# building anything, which `nix flake check --all-systems` needs on a host that cannot build for the
|
||||
# other systems; and the same for every platform, so that the dependencies do not depend on the stubs.
|
||||
manifestSource =
|
||||
lib:
|
||||
lib.fileset.toSource {
|
||||
root = repoRoot;
|
||||
fileset = lib.fileset.fileFilter (
|
||||
file:
|
||||
builtins.elem file.name [
|
||||
"Cargo.toml"
|
||||
"Cargo.lock"
|
||||
"build.rs"
|
||||
"config.toml"
|
||||
]
|
||||
) repoRoot;
|
||||
};
|
||||
|
||||
# nixpkgs with the rust overlay, for a system (x86_64-darwin: see the input nixpkgs-x86_64-darwin)
|
||||
mkPkgs =
|
||||
system:
|
||||
import (if system == "x86_64-darwin" then inputs.nixpkgs-x86_64-darwin else inputs.nixpkgs) {
|
||||
inherit system;
|
||||
overlays = [ (import inputs.rust-overlay) ];
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
# The crane derivations of the Linux (KDE Plasma) packages, from the Linux members of the one Cargo
|
||||
# workspace (nix/workspace-src.nix).
|
||||
{ inputs, self }:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
inherit (lib') version;
|
||||
inherit (inputs) crane;
|
||||
in
|
||||
{
|
||||
mkKomorebiPackages =
|
||||
{ pkgs }:
|
||||
let
|
||||
toolchain = pkgs.rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml;
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||
|
||||
inherit
|
||||
(import ../workspace-src.nix {
|
||||
inherit pkgs craneLib;
|
||||
repoRoot = ../..;
|
||||
platform = "linux";
|
||||
})
|
||||
real
|
||||
src
|
||||
stubbedPackages
|
||||
;
|
||||
|
||||
lockFile = lib'.repoFile "Cargo.lock";
|
||||
tomlFile = lib'.repoFile "Cargo.toml";
|
||||
packages = "-p komorebi -p komorebi-linux -p komorebic -p komorebi-client -p komorebi-hotkeys";
|
||||
workspaceArgs = {
|
||||
pname = "komorebi-workspace-linux";
|
||||
inherit version;
|
||||
# the lock and the root manifest as files of their own: a path inside the filtered source
|
||||
# would put all of it into the context of every derivation, and an edit of any file
|
||||
# would then change the dependencies
|
||||
cargoLock = lockFile;
|
||||
cargoToml = tomlFile;
|
||||
cargoVendorDir = craneLib.vendorCargoDeps { cargoLock = lockFile; };
|
||||
};
|
||||
|
||||
commonArgs = workspaceArgs // {
|
||||
cargoExtraArgs = "--locked ${packages}";
|
||||
inherit src;
|
||||
strictDeps = true;
|
||||
# The version crate wants a commit at compile time. It is a constant here, so that the
|
||||
# dependencies and every check are the same derivations for every commit; only the final
|
||||
# build below knows the real one.
|
||||
COMMIT_HASH = "nix-check";
|
||||
};
|
||||
|
||||
# the dummy source is of the manifests alone (nix/lib.nix): the dependencies are the same
|
||||
# derivations for every source file and every stub, and nothing is built at evaluation
|
||||
cargoArtifacts = craneLib.buildDepsOnly (
|
||||
builtins.removeAttrs commonArgs [ "src" ]
|
||||
// {
|
||||
dummySrc = craneLib.mkDummySrc {
|
||||
src = lib'.manifestSource pkgs.lib;
|
||||
cargoLock = lockFile;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
individualCrateArgs = commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
doDoc = false;
|
||||
};
|
||||
|
||||
fullBuild = craneLib.buildPackage (
|
||||
individualCrateArgs
|
||||
// {
|
||||
COMMIT_HASH = self.rev or (pkgs.lib.removeSuffix "-dirty" (self.dirtyRev or "unknown"));
|
||||
}
|
||||
);
|
||||
|
||||
# the same build with the constant commit of the checks: the VM tests install this one, so
|
||||
# that a new commit does not build the daemon again
|
||||
vmBuild = craneLib.buildPackage individualCrateArgs;
|
||||
|
||||
extractBinaryOf =
|
||||
package: binaryName:
|
||||
pkgs.runCommand "komorebi-${binaryName}" { meta = package.meta // { }; } ''
|
||||
mkdir -p $out/bin
|
||||
cp ${package}/bin/${binaryName} $out/bin/
|
||||
'';
|
||||
extractBinary = extractBinaryOf fullBuild;
|
||||
in
|
||||
{
|
||||
inherit
|
||||
craneLib
|
||||
src
|
||||
real
|
||||
workspaceArgs
|
||||
stubbedPackages
|
||||
packages
|
||||
commonArgs
|
||||
individualCrateArgs
|
||||
fullBuild
|
||||
vmBuild
|
||||
;
|
||||
komorebi = extractBinary "komorebi";
|
||||
komorebic = extractBinary "komorebic";
|
||||
komorebiForVm = extractBinaryOf vmBuild "komorebi";
|
||||
komorebicForVm = extractBinaryOf vmBuild "komorebic";
|
||||
# komorebic with the constant commit of the checks, whose output the schemas are
|
||||
# checked against: it is the same for every commit
|
||||
komorebicForChecks = craneLib.buildPackage (
|
||||
individualCrateArgs
|
||||
// {
|
||||
pname = "komorebic-for-checks";
|
||||
cargoExtraArgs = "--package komorebic --bin komorebic";
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,526 @@
|
||||
# komorebi for Linux (KDE Plasma): the native packages, the `linux-*` checks, the VM tests (`vm-*`),
|
||||
# the NixOS module and the Plasma guests. The Rust packages are built on Linux; Apple silicon gets
|
||||
# the checks and the VM guests' definitions, which run the same tests against the fake desktop.
|
||||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
inherit (inputs) nixpkgs;
|
||||
linux = import ./build.nix { inherit inputs self; };
|
||||
inherit (lib') mkPkgs;
|
||||
in
|
||||
{
|
||||
perSystem =
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
system,
|
||||
...
|
||||
}:
|
||||
let
|
||||
build = linux.mkKomorebiPackages { inherit pkgs; };
|
||||
isLinux = pkgs.stdenv.hostPlatform.isLinux;
|
||||
# the guests install komorebi through the module, as a NixOS user does
|
||||
komorebiModule = self.nixosModules.forVmTests;
|
||||
# a Mac runs the guests under HVF, which is slower than KVM. A Linux host is no faster
|
||||
# than a Mac to the suites that time the daemon: on a 24-core WSL2 machine, under nested
|
||||
# KVM and with nothing else running, `latency` measured a p95 of 129 ms against its
|
||||
# 100 ms times `scale`, where x86-1 had passed it at 1
|
||||
vm = import ./tests/vm {
|
||||
hostPkgs = pkgs;
|
||||
inherit komorebiModule;
|
||||
scale = 1.5;
|
||||
};
|
||||
# the probe of a NixOS-WSL2 machine (docs/linux/dev/wsl2-probe.md); the checks use a constant
|
||||
# revision, so that they are the same derivations for every commit
|
||||
wsl2Probe = import ./dev/wsl2-probe.nix {
|
||||
inherit pkgs;
|
||||
rev = self.rev or self.dirtyRev or "unknown";
|
||||
};
|
||||
wsl2ProbeForChecks = import ./dev/wsl2-probe.nix {
|
||||
inherit pkgs;
|
||||
rev = "nix-check";
|
||||
};
|
||||
# `run-kde` starts the demo guest of the host's architecture (docs/linux/trying-it.md). The guest's
|
||||
# runner is named in the program, not depended on: the command works out what is missing
|
||||
# and builds it, with its progress shown, instead of `nix run` fetching 4 GB first.
|
||||
runKde =
|
||||
let
|
||||
arch = if system == "x86_64-linux" then "x86_64" else "aarch64";
|
||||
guest = self.nixosConfigurations."run-kde-${arch}";
|
||||
runner = builtins.unsafeDiscardStringContext "${guest.config.system.build.vm}";
|
||||
in
|
||||
pkgs.writeShellApplication {
|
||||
name = "run-kde";
|
||||
runtimeInputs = with pkgs; [
|
||||
coreutils
|
||||
e2fsprogs
|
||||
gawk
|
||||
git
|
||||
gnugrep
|
||||
gnused
|
||||
mesa-demos
|
||||
openssh
|
||||
qemu-utils
|
||||
virtiofsd
|
||||
];
|
||||
text = ''
|
||||
: "''${RUN_KDE_GUEST:=run-kde-${arch}}"
|
||||
: "''${RUN_KDE_RUNNER_BIN:=${runner}/bin/run-${guest.config.networking.hostName}-vm}"
|
||||
''
|
||||
+ builtins.readFile ../../scripts/linux/run-kde;
|
||||
};
|
||||
# rustfmt.toml uses options only a nightly rustfmt knows
|
||||
nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
checkSystem = builtins.elem system lib'.linuxCheckSystems;
|
||||
|
||||
# PLACEHOLDER until the structure of the check sets is decided (agent flake-checks): the checks that
|
||||
# evaluate a NixOS system or a VM (vm-*, the Plasma guests, the module option tests, run-kde) take
|
||||
# minutes and many GB to evaluate, so `nix flake check --no-build --all-systems` cannot hold them. They
|
||||
# are `legacyPackages.<system>.heavyChecks.<name>` (same names as before), not `checks.<system>`.
|
||||
isHeavy =
|
||||
name:
|
||||
lib.hasPrefix "vm-" name
|
||||
|| builtins.elem name [
|
||||
"linux-nixos-module-eval"
|
||||
"linux-plasma-guests-eval"
|
||||
"linux-run-kde"
|
||||
"linux-run-kde-doctor"
|
||||
"linux-run-kde-dry-run"
|
||||
];
|
||||
split =
|
||||
r:
|
||||
if r ? allChecks then
|
||||
removeAttrs r [ "allChecks" ]
|
||||
// {
|
||||
checks = lib.filterAttrs (n: _: !isHeavy n) r.allChecks;
|
||||
legacyPackages = r.legacyPackages // {
|
||||
heavyChecks = lib.filterAttrs (n: _: isHeavy n) r.allChecks;
|
||||
};
|
||||
}
|
||||
else
|
||||
r;
|
||||
in
|
||||
split (
|
||||
lib.optionalAttrs checkSystem {
|
||||
allChecks = {
|
||||
# tools/format-all: the nightly rustfmt over the files of the Linux source, file by file. `cargo fmt`
|
||||
# followed `mod windows;` of the shared entry files into files this source does not have.
|
||||
linux-fmt =
|
||||
pkgs.runCommand "komorebi-linux-fmt"
|
||||
{
|
||||
nativeBuildInputs = [ nightlyRustfmt ];
|
||||
}
|
||||
''
|
||||
RUSTFMT=rustfmt bash ${lib'.repoFile "tools/format-all"} --check --root ${build.real}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
linux-clippy = build.craneLib.cargoClippy (
|
||||
build.individualCrateArgs
|
||||
// {
|
||||
cargoClippyExtraArgs = "--all-targets -- -D warnings";
|
||||
}
|
||||
);
|
||||
|
||||
linux-doc = build.craneLib.cargoDoc (
|
||||
build.individualCrateArgs
|
||||
// {
|
||||
cargoDocExtraArgs = "--no-deps";
|
||||
env.RUSTDOCFLAGS = "-D warnings";
|
||||
}
|
||||
);
|
||||
|
||||
linux-toml-fmt = build.craneLib.taploFmt (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
src = lib.sources.sourceFilesBySuffices build.real [ ".toml" ];
|
||||
}
|
||||
);
|
||||
|
||||
# cargo deny sees every member of the workspace: leave out the other platforms' packages (stubs
|
||||
# here); the policy is the one deny.toml of the repository
|
||||
linux-deny = build.craneLib.cargoDeny (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
inherit (build) src;
|
||||
cargoDenyExtraArgs =
|
||||
"--workspace " + lib.concatMapStringsSep " " (p: "--exclude ${p}") build.stubbedPackages;
|
||||
cargoDenyChecks = "bans licenses sources";
|
||||
}
|
||||
);
|
||||
|
||||
linux-nextest = build.craneLib.cargoNextest (build.individualCrateArgs // { doCheck = true; });
|
||||
|
||||
# The bridge is not Rust: tsc checks its types from its JSDoc comments, and node runs
|
||||
# its tests against a fake KWin. No package.json and no build step.
|
||||
linux-bridge-js =
|
||||
pkgs.runCommand "komorebi-bridge-js"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
pkgs.nodejs
|
||||
pkgs.typescript
|
||||
];
|
||||
src = lib.fileset.toSource {
|
||||
root = ../../komorebi-linux/src/kwin;
|
||||
fileset = lib.fileset.fileFilter (file: !file.hasExt "rs") ../../komorebi-linux/src/kwin;
|
||||
};
|
||||
}
|
||||
''
|
||||
cd $src
|
||||
tsc -p tsconfig.json
|
||||
node --test bridge.test.js
|
||||
touch $out
|
||||
'';
|
||||
|
||||
vm-lib = vm.lib;
|
||||
|
||||
# The schemas, the options made from one of them and the example are what the Rust types
|
||||
# say: `just jsonschema` and `just nixgen-linux` write them
|
||||
linux-schema-fresh =
|
||||
pkgs.runCommand "komorebi-schema-fresh"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
build.komorebicForChecks
|
||||
pkgs.diffutils
|
||||
];
|
||||
}
|
||||
''
|
||||
komorebic static-config-schema | diff -u ${lib'.repoFile "schemas/linux/schema.json"} - \
|
||||
|| { echo "schemas/linux/schema.json is stale: run just jsonschema"; exit 1; }
|
||||
komorebic application-specific-configuration-schema | diff -u ${lib'.repoFile "schemas/linux/schema.asc.json"} - \
|
||||
|| { echo "schemas/linux/schema.asc.json is stale: run just jsonschema"; exit 1; }
|
||||
expected=$(sha256sum ${lib'.repoFile "schemas/linux/schema.json"} | cut -d' ' -f1)
|
||||
head -n 1 ${./komorebi-options.nix} | grep -qx "# schema-sha256: $expected" \
|
||||
|| { echo "nix/linux/komorebi-options.nix is stale: run just nixgen-linux"; exit 1; }
|
||||
touch $out
|
||||
'';
|
||||
|
||||
# the options the module is typed with, evaluated against the example configuration
|
||||
linux-nix-options-validation = import ./tests/default.nix { inherit pkgs; };
|
||||
|
||||
# every file of the key binding corpus through `komorebic hotkeys compile`, as the
|
||||
# module runs it
|
||||
linux-keybindings-fixtures = import ./tests/keybindings.nix {
|
||||
inherit pkgs;
|
||||
komorebic = build.fullBuild;
|
||||
};
|
||||
|
||||
# The NixOS module in real NixOS systems, evaluated and never built, so a Mac checks it
|
||||
# too. A VM suite, `vm-module`, runs it.
|
||||
linux-nixos-module-eval = import ./tests/nixos-module.nix {
|
||||
inherit pkgs;
|
||||
inherit (nixpkgs.lib) nixosSystem;
|
||||
module = self.nixosModules.default;
|
||||
komorebiFor = guestSystem: self.packages.${guestSystem}.komorebi-full;
|
||||
borderEffectFor = guestSystem: self.packages.${guestSystem}.kde-rounded-corners-komorebi;
|
||||
animationEffectFor = guestSystem: self.packages.${guestSystem}.kwin-effect-geometry-change-komorebi;
|
||||
};
|
||||
|
||||
# The Plasma guests to develop against, evaluated and never built, so that every system
|
||||
# sees an option that nixpkgs renamed or an assertion that fails. The QEMU guests are
|
||||
# systems in a VM (`vmVariant`), with a runner for the machine that runs QEMU; UTM's is
|
||||
# a system of its own. Each guest is for one kind of machine, which is also checked: the
|
||||
# architecture of the guest, the machine that runs its QEMU, and that a guest of a Linux
|
||||
# machine has KVM and one display device only.
|
||||
linux-plasma-guests-eval =
|
||||
let
|
||||
guests = self.nixosConfigurations;
|
||||
machines =
|
||||
let
|
||||
mac = {
|
||||
guest = "aarch64-linux";
|
||||
host = "aarch64-darwin";
|
||||
};
|
||||
linux = system: {
|
||||
guest = system;
|
||||
host = system;
|
||||
};
|
||||
# the runner of the demo is given its display device, its ports and whether to
|
||||
# insist on KVM when it starts, by `run-kde`
|
||||
demo = machine: machine // { demo = true; };
|
||||
in
|
||||
{
|
||||
plasma-vm = mac;
|
||||
plasma-vm-session = mac;
|
||||
plasma-vm-x86_64 = linux "x86_64-linux";
|
||||
plasma-vm-session-x86_64 = linux "x86_64-linux";
|
||||
plasma-vm-aarch64 = linux "aarch64-linux";
|
||||
plasma-vm-session-aarch64 = linux "aarch64-linux";
|
||||
run-kde-x86_64 = demo (linux "x86_64-linux");
|
||||
run-kde-aarch64 = demo (linux "aarch64-linux");
|
||||
};
|
||||
isDisplay =
|
||||
option: lib.hasPrefix "-device virtio-vga" option || lib.hasPrefix "-device virtio-gpu" option;
|
||||
qemuGuest =
|
||||
name:
|
||||
let
|
||||
machine = machines.${name};
|
||||
demo = machine.demo or false;
|
||||
vm = guests.${name}.config.virtualisation.vmVariant.virtualisation;
|
||||
in
|
||||
assert lib.assertMsg (
|
||||
guests.${name}.pkgs.stdenv.hostPlatform.system == machine.guest
|
||||
) "${name} is not a ${machine.guest} guest";
|
||||
assert lib.assertMsg (
|
||||
vm.host.pkgs.stdenv.hostPlatform.system == machine.host
|
||||
) "${name} does not run on a ${machine.host} host";
|
||||
assert lib.assertMsg (
|
||||
vm.qemu.forceAccel != demo
|
||||
) "${name} would run without KVM or HVF, which is too slow to use";
|
||||
assert lib.assertMsg (
|
||||
builtins.length (builtins.filter isDisplay vm.qemu.options) == (if demo then 0 else 1)
|
||||
) "${name} does not have the display devices it should have";
|
||||
assert lib.assertMsg
|
||||
# an x86_64 machine has a VGA of its own, which would be a second display
|
||||
((machine.guest == "x86_64-linux" && !demo) == builtins.elem "-vga none" vm.qemu.options)
|
||||
"${name} has `-vga none` if and only if it is an x86_64 guest with a display device";
|
||||
assert lib.assertMsg (
|
||||
demo -> (vm.forwardPorts == [ ] && vm.sharedDirectories.run-kde.target == "/run/run-kde")
|
||||
) "${name} does not leave its ports and its shared directory to the runner's environment";
|
||||
{
|
||||
${name} = guests.${name}.config.virtualisation.vmVariant.system.build.toplevel;
|
||||
"${name}, its runner" = guests.${name}.config.system.build.vm;
|
||||
};
|
||||
builds = lib.foldl' (builds: name: builds // qemuGuest name) { } (lib.attrNames machines) // {
|
||||
plasma-utm = guests.plasma-utm.config.system.build.toplevel;
|
||||
};
|
||||
lines = lib.mapAttrsToList (
|
||||
name: drv: "${name}: ${builtins.unsafeDiscardStringContext drv.drvPath}"
|
||||
) builds;
|
||||
in
|
||||
pkgs.runCommand "plasma-guests-eval" { } ''
|
||||
${lib.concatMapStringsSep "\n" (line: "echo ${lib.escapeShellArg line}") lines}
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
# The probe builds (shellcheck runs over the script and over the guest's init as it
|
||||
# does) and its dry run works without a machine to probe, so that it cannot rot between
|
||||
# the times somebody runs it.
|
||||
// lib.optionalAttrs isLinux {
|
||||
linux-wsl2-probe = wsl2ProbeForChecks.probe;
|
||||
linux-wsl2-probe-dry-run =
|
||||
pkgs.runCommand "wsl2-probe-dry-run" { nativeBuildInputs = [ wsl2ProbeForChecks.probe ]; }
|
||||
''
|
||||
wsl2-probe --dry-run --no-prompt --report report.txt > out.txt
|
||||
cat out.txt
|
||||
for probe in P0 P1 P2 P3 P4 P5 P6; do
|
||||
grep -q "^$probe " out.txt || { echo "no verdict line for $probe"; exit 1; }
|
||||
done
|
||||
grep -q "PASTE THIS" out.txt
|
||||
grep -q "would run" out.txt
|
||||
# the report file has what the screen has
|
||||
grep -q "PASTE THIS" report.txt
|
||||
# a mistake in the options is refused
|
||||
if wsl2-probe --nonsense 2> err.txt; then exit 1; fi
|
||||
grep -q "unknown option" err.txt
|
||||
touch $out
|
||||
'';
|
||||
}
|
||||
# `run-kde` is shellchecked when it is built, and its output is what a test says it is
|
||||
// lib.optionalAttrs isLinux (
|
||||
lib.mapAttrs' (name: lib.nameValuePair "linux-${name}") (
|
||||
{
|
||||
run-kde = config.packages.run-kde;
|
||||
}
|
||||
// import ./tests/run-kde.nix {
|
||||
inherit pkgs;
|
||||
runKde = config.packages.run-kde;
|
||||
}
|
||||
)
|
||||
)
|
||||
# The VM tests need QEMU with KVM, so only Linux checks them. A Mac runs the same tests
|
||||
# through legacyPackages.<system>.vm, see docs/linux/dev/vm-tests.md.
|
||||
// lib.optionalAttrs isLinux (
|
||||
lib.mapAttrs' (name: test: lib.nameValuePair "vm-${name}" test) vm.suites
|
||||
)
|
||||
# the KWin effects komorebi drives, installed and inspected without a session
|
||||
// lib.optionalAttrs isLinux (
|
||||
lib.mapAttrs' (name: lib.nameValuePair "linux-${name}") (
|
||||
import ./tests/effects.nix {
|
||||
inherit pkgs;
|
||||
inherit (config) packages;
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
legacyPackages = lib.optionalAttrs checkSystem (
|
||||
{
|
||||
# every suite, as a test with a `driver`, on every system
|
||||
vm = vm.suites;
|
||||
# the suites of each tier, for the CI matrix
|
||||
vmTiers = vm.tiers;
|
||||
# the guests of every suite, to build on a Linux builder when the host is a Mac
|
||||
vmGuests = vm.guests;
|
||||
}
|
||||
// lib.optionalAttrs isLinux {
|
||||
# the same suites on a machine with no KVM, which is slow but works anywhere
|
||||
vmTcg =
|
||||
(import ./tests/vm {
|
||||
hostPkgs = pkgs;
|
||||
inherit komorebiModule;
|
||||
scale = 8;
|
||||
}).suites;
|
||||
}
|
||||
);
|
||||
}
|
||||
)
|
||||
// lib.optionalAttrs (builtins.elem system lib'.linuxSystems) {
|
||||
packages = {
|
||||
inherit (build) komorebi komorebic;
|
||||
komorebi-full = build.fullBuild;
|
||||
default = build.fullBuild;
|
||||
kde-rounded-corners-komorebi = pkgs.callPackage ../linux/kde-rounded-corners.nix { };
|
||||
kwin-effect-geometry-change-komorebi =
|
||||
pkgs.callPackage ../linux/kwin-effect-geometry-change.nix
|
||||
{ };
|
||||
wsl2-probe = wsl2Probe.probe;
|
||||
wsl2-probe-guest = wsl2Probe.guest;
|
||||
run-kde = runKde;
|
||||
};
|
||||
|
||||
apps = {
|
||||
komorebi = {
|
||||
type = "app";
|
||||
program = "${build.komorebi}/bin/komorebi";
|
||||
meta.description = "The komorebi daemon";
|
||||
};
|
||||
komorebic = {
|
||||
type = "app";
|
||||
program = "${build.komorebic}/bin/komorebic";
|
||||
meta.description = "The command line interface of komorebi";
|
||||
};
|
||||
wsl2-probe = {
|
||||
type = "app";
|
||||
program = lib.getExe wsl2Probe.probe;
|
||||
meta.description = "Probes a NixOS-WSL2 machine for KVM, WSLg, a GPU and RDP";
|
||||
};
|
||||
run-kde = {
|
||||
type = "app";
|
||||
program = lib.getExe config.packages.run-kde;
|
||||
meta.description = "Start the komorebi demo in a virtual machine";
|
||||
};
|
||||
default = config.apps.komorebi;
|
||||
};
|
||||
};
|
||||
|
||||
flake = {
|
||||
overlays.linux =
|
||||
final: _:
|
||||
let
|
||||
build = linux.mkKomorebiPackages { pkgs = mkPkgs final.stdenv.hostPlatform.system; };
|
||||
in
|
||||
{
|
||||
inherit (build) komorebi komorebic;
|
||||
komorebi-full = build.fullBuild;
|
||||
# with the consumer's KWin, so that the plugin links the libkwin it is loaded into
|
||||
kde-rounded-corners-komorebi = final.callPackage ./kde-rounded-corners.nix { };
|
||||
kwin-effect-geometry-change-komorebi = final.callPackage ./kwin-effect-geometry-change.nix { };
|
||||
};
|
||||
# the same packages built with the constant commit of the checks, for the VM tests
|
||||
overlays.forVmTests =
|
||||
final: prev:
|
||||
let
|
||||
build = linux.mkKomorebiPackages { pkgs = mkPkgs final.stdenv.hostPlatform.system; };
|
||||
in
|
||||
(self.overlays.linux final prev)
|
||||
// {
|
||||
komorebi = build.komorebiForVm;
|
||||
komorebic = build.komorebicForVm;
|
||||
komorebi-full = build.vmBuild;
|
||||
};
|
||||
|
||||
# `services.komorebi`, with the overlay that provides its package, so that a NixOS
|
||||
# configuration needs this flake as an input and one module line (docs/linux/installation.md)
|
||||
nixosModules.default = {
|
||||
imports = [ ./nixos-module.nix ];
|
||||
nixpkgs.overlays = [ self.overlays.linux ];
|
||||
};
|
||||
nixosModules.komorebi = self.nixosModules.default;
|
||||
# the names of the root flake before the nested flakes were merged into it
|
||||
nixosModules.komorebi-for-kde = self.nixosModules.default;
|
||||
overlays.komorebi-for-kde = self.overlays.linux;
|
||||
# `services.komorebi` with the packages the VM tests install
|
||||
nixosModules.forVmTests = {
|
||||
imports = [ ./nixos-module.nix ];
|
||||
nixpkgs.overlays = [ self.overlays.forVmTests ];
|
||||
};
|
||||
|
||||
# Plasma guests to develop against (docs/linux/dev/utm.md). For an Apple silicon Mac, QEMU runs
|
||||
# the first two under HVF, and UTM boots the third from a disk image. For a Linux machine
|
||||
# with KVM, QEMU runs the other four: the same two guests for an x86_64 host and for an
|
||||
# aarch64 one, each of which runs the guest of its own architecture. The last two are the
|
||||
# demo that `run-kde` starts.
|
||||
nixosConfigurations =
|
||||
let
|
||||
# `guest` is the system of the guest, and `host` the pkgs of the machine that runs QEMU
|
||||
mkPlasmaGuest =
|
||||
{ guest, host }:
|
||||
modules:
|
||||
nixpkgs.lib.nixosSystem {
|
||||
specialArgs.hostPkgs = host;
|
||||
modules = [
|
||||
self.nixosModules.default
|
||||
{ nixpkgs.hostPlatform = guest; }
|
||||
# `nix flake check` evaluates the toplevel of every configuration, which needs a root file
|
||||
# system and a boot loader; the guests run as VMs (vmVariant), which replace both
|
||||
(
|
||||
{ lib, ... }:
|
||||
{
|
||||
fileSystems."/" = lib.mkDefault {
|
||||
device = "/dev/disk/by-label/nixos";
|
||||
fsType = "ext4";
|
||||
};
|
||||
boot.loader.grub.devices = lib.mkDefault [ "nodev" ];
|
||||
}
|
||||
)
|
||||
]
|
||||
++ modules;
|
||||
};
|
||||
onMac = mkPlasmaGuest {
|
||||
guest = "aarch64-linux";
|
||||
host = nixpkgs.legacyPackages.aarch64-darwin;
|
||||
};
|
||||
onLinux =
|
||||
system:
|
||||
mkPlasmaGuest {
|
||||
guest = system;
|
||||
host = nixpkgs.legacyPackages.${system};
|
||||
};
|
||||
session = [
|
||||
./dev/plasma-vm.nix
|
||||
{ komorebi.plasmaVm.session = true; }
|
||||
];
|
||||
# the session guest with the demo of `run-kde` (nix/linux/dev/run-kde.nix) and no display
|
||||
# device, which the command gives it when it starts the guest
|
||||
demo = [
|
||||
./dev/plasma-vm.nix
|
||||
{
|
||||
komorebi.plasmaVm = {
|
||||
session = true;
|
||||
display = false;
|
||||
};
|
||||
}
|
||||
./dev/run-kde.nix
|
||||
({ lib, ... }: { networking.hostName = lib.mkOverride 40 "komorebi-demo"; })
|
||||
];
|
||||
in
|
||||
{
|
||||
plasma-vm = onMac [ ./dev/plasma-vm.nix ];
|
||||
plasma-vm-session = onMac session;
|
||||
plasma-utm = onMac [ ./dev/plasma-utm.nix ];
|
||||
|
||||
plasma-vm-x86_64 = onLinux "x86_64-linux" [ ./dev/plasma-vm.nix ];
|
||||
plasma-vm-session-x86_64 = onLinux "x86_64-linux" session;
|
||||
plasma-vm-aarch64 = onLinux "aarch64-linux" [ ./dev/plasma-vm.nix ];
|
||||
plasma-vm-session-aarch64 = onLinux "aarch64-linux" session;
|
||||
|
||||
run-kde-x86_64 = onLinux "x86_64-linux" demo;
|
||||
run-kde-aarch64 = onLinux "aarch64-linux" demo;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
# The crane derivations of the macOS packages, from the macOS members of the one Cargo workspace
|
||||
# (nix/workspace-src.nix).
|
||||
{ inputs, self }:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
inherit (lib') version;
|
||||
inherit (inputs) crane;
|
||||
in
|
||||
{
|
||||
mkKomorebiPackages =
|
||||
{ pkgs }:
|
||||
let
|
||||
toolchain = pkgs.rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml;
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||
|
||||
inherit
|
||||
(import ../workspace-src.nix {
|
||||
inherit pkgs craneLib;
|
||||
repoRoot = ../..;
|
||||
platform = "macos";
|
||||
})
|
||||
real
|
||||
src
|
||||
stubbedPackages
|
||||
;
|
||||
|
||||
lockFile = lib'.repoFile "Cargo.lock";
|
||||
tomlFile = lib'.repoFile "Cargo.toml";
|
||||
packages = "-p komorebi -p komorebi-macos -p komorebic -p komorebi-client -p komorebi-bar";
|
||||
workspaceArgs = {
|
||||
pname = "komorebi-workspace-macos";
|
||||
inherit version;
|
||||
# the lock and the root manifest as files of their own: a path inside the filtered source
|
||||
# would put all of it into the context of every derivation, and an edit of any file
|
||||
# would then change the dependencies
|
||||
cargoLock = lockFile;
|
||||
cargoToml = tomlFile;
|
||||
cargoVendorDir = craneLib.vendorCargoDeps { cargoLock = lockFile; };
|
||||
};
|
||||
|
||||
commonArgs = workspaceArgs // {
|
||||
cargoExtraArgs = "--locked ${packages}";
|
||||
inherit src;
|
||||
strictDeps = true;
|
||||
# a constant, so that the dependencies and every check are the same derivations for
|
||||
# every commit; only fullBuild stamps the real one
|
||||
COMMIT_HASH = "nix-check";
|
||||
nativeBuildInputs = [
|
||||
pkgs.darwin.cctools
|
||||
];
|
||||
postFixup = ''
|
||||
for bin in $out/bin/*; do
|
||||
if [ -f "$bin" ] && [ -x "$bin" ]; then
|
||||
# Get all linked libraries and fix libiconv references
|
||||
otool -L "$bin" | grep -o '/nix/store/[^/]*/lib/libiconv[^ ]*' | while read -r lib; do
|
||||
install_name_tool -change "$lib" /usr/lib/libiconv.dylib "$bin"
|
||||
done
|
||||
fi
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
# the dummy source is of the manifests alone (nix/lib.nix): the dependencies are the same
|
||||
# derivations for every source file and every stub, and nothing is built at evaluation
|
||||
cargoArtifacts = craneLib.buildDepsOnly (
|
||||
builtins.removeAttrs commonArgs [ "src" ]
|
||||
// {
|
||||
dummySrc = craneLib.mkDummySrc {
|
||||
src = lib'.manifestSource pkgs.lib;
|
||||
cargoLock = lockFile;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
individualCrateArgs = commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
doDoc = false;
|
||||
};
|
||||
|
||||
fullBuild = craneLib.buildPackage (
|
||||
individualCrateArgs
|
||||
// {
|
||||
COMMIT_HASH = self.rev or (pkgs.lib.removeSuffix "-dirty" (self.dirtyRev or "unknown"));
|
||||
}
|
||||
);
|
||||
|
||||
extractBinary =
|
||||
binaryName:
|
||||
pkgs.runCommand "komorebi-${binaryName}"
|
||||
{
|
||||
meta = fullBuild.meta // { };
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${fullBuild}/bin/${binaryName} $out/bin/
|
||||
'';
|
||||
in
|
||||
{
|
||||
inherit
|
||||
craneLib
|
||||
src
|
||||
real
|
||||
workspaceArgs
|
||||
stubbedPackages
|
||||
packages
|
||||
individualCrateArgs
|
||||
fullBuild
|
||||
;
|
||||
komorebi = extractBinary "komorebi";
|
||||
komorebic = extractBinary "komorebic";
|
||||
komorebi-bar = extractBinary "komorebi-bar";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
# komorebi for macOS: the native packages on Apple machines, the `macos-*` checks and the
|
||||
# nix-darwin module. The Rust packages cannot be built on Linux; `nix flake check --no-build
|
||||
# --all-systems` evaluates them there.
|
||||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
macos = import ./build.nix { inherit inputs self; };
|
||||
inherit (lib') mkPkgs;
|
||||
in
|
||||
{
|
||||
perSystem =
|
||||
{ pkgs, system, ... }:
|
||||
let
|
||||
build = macos.mkKomorebiPackages { inherit pkgs; };
|
||||
# rustfmt.toml uses options only a nightly rustfmt knows
|
||||
nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
in
|
||||
lib.optionalAttrs (builtins.elem system lib'.macosSystems) {
|
||||
checks = {
|
||||
macos-clippy = build.craneLib.cargoClippy build.individualCrateArgs;
|
||||
|
||||
# the nightly rustfmt over the macOS files only (the source of this platform has no others), with
|
||||
# the 2024 edition of the manifests. `cargo fmt` would follow the `mod windows;` of the shared
|
||||
# entry files (komorebi-bar, komorebi-client), which the macOS source does not have.
|
||||
macos-fmt =
|
||||
pkgs.runCommand "komorebi-macos-fmt"
|
||||
{
|
||||
nativeBuildInputs = [ nightlyRustfmt ];
|
||||
}
|
||||
''
|
||||
RUSTFMT=rustfmt bash ${lib'.repoFile "tools/format-all"} --check --root ${build.real}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
macos-toml-fmt = build.craneLib.taploFmt (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
src = lib.sources.sourceFilesBySuffices build.real [ ".toml" ];
|
||||
}
|
||||
);
|
||||
|
||||
# cargo deny sees every member of the workspace: leave out the other platforms' packages (stubs
|
||||
# here); the policy is the one deny.toml of the repository
|
||||
macos-deny = build.craneLib.cargoDeny (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
inherit (build) src;
|
||||
cargoDenyExtraArgs =
|
||||
"--workspace " + lib.concatMapStringsSep " " (p: "--exclude ${p}") build.stubbedPackages;
|
||||
cargoDenyChecks = "bans licenses sources";
|
||||
}
|
||||
);
|
||||
|
||||
macos-nextest = build.craneLib.cargoNextest build.individualCrateArgs;
|
||||
|
||||
macos-nix-options-validation = import ./tests { inherit pkgs; };
|
||||
|
||||
macos-darwin-module-validation = import ./tests/darwin-module.nix { inherit pkgs; };
|
||||
};
|
||||
|
||||
packages = {
|
||||
inherit (build) komorebi komorebic komorebi-bar;
|
||||
komorebi-full = build.fullBuild;
|
||||
default = build.fullBuild;
|
||||
};
|
||||
|
||||
apps = {
|
||||
komorebi = {
|
||||
type = "app";
|
||||
program = "${build.komorebi}/bin/komorebi";
|
||||
};
|
||||
komorebic = {
|
||||
type = "app";
|
||||
program = "${build.komorebic}/bin/komorebic";
|
||||
};
|
||||
komorebi-bar = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-bar}/bin/komorebi-bar";
|
||||
};
|
||||
default = {
|
||||
type = "app";
|
||||
program = "${build.fullBuild}/bin/komorebi";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
flake = {
|
||||
overlays.macos =
|
||||
final: _:
|
||||
let
|
||||
build = macos.mkKomorebiPackages { pkgs = mkPkgs final.stdenv.hostPlatform.system; };
|
||||
in
|
||||
{
|
||||
inherit (build) komorebi komorebic komorebi-bar;
|
||||
komorebi-full = build.fullBuild;
|
||||
};
|
||||
|
||||
darwinModules.default = import ./darwin-module.nix;
|
||||
darwinModules.komorebi = import ./darwin-module.nix;
|
||||
# the name of the root flake before the nested flakes were merged into it
|
||||
darwinModules.komorebi-for-mac = import ./darwin-module.nix;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
# The Windows cross build: xwin's SDK and CRT, the clang-cl/lld-link environment and the crane
|
||||
# derivations of the Windows workspace (target x86_64-pc-windows-msvc), for the systems that build it.
|
||||
{ inputs, self }:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
inherit (lib') version;
|
||||
inherit (inputs) crane;
|
||||
windowsSdkVersion = "10.0.26100";
|
||||
windowsCrtVersion = "14.44.17.14";
|
||||
|
||||
mkWindowsSdk =
|
||||
pkgs:
|
||||
pkgs.stdenvNoCC.mkDerivation {
|
||||
name = "windows-sdk-${windowsSdkVersion}-crt-${windowsCrtVersion}";
|
||||
|
||||
nativeBuildInputs = [
|
||||
pkgs.xwin
|
||||
pkgs.cacert
|
||||
];
|
||||
|
||||
outputHashAlgo = "sha256";
|
||||
outputHashMode = "recursive";
|
||||
# hash of `xwin splat --disable-symlinks`: without the flag xwin makes
|
||||
# case-alias symlinks on a case-sensitive filesystem and none on a
|
||||
# case-insensitive one, so the hash depends on the host
|
||||
outputHash = "sha256-YjmEfoxtcmQXvUc+WtaElnyP/4osNvtSI7X6MDaNTjg=";
|
||||
|
||||
buildCommand = ''
|
||||
export HOME=$(mktemp -d)
|
||||
# keep the cache on the same filesystem as $out, as xwin moves
|
||||
# files from the cache into the output and rename(2) fails with
|
||||
# EXDEV when the build dir and the store are separate mounts
|
||||
mkdir -p $out
|
||||
xwin --accept-license \
|
||||
--cache-dir $out/.xwin-cache \
|
||||
--sdk-version ${windowsSdkVersion} \
|
||||
--crt-version ${windowsCrtVersion} \
|
||||
splat --disable-symlinks --output $out
|
||||
rm -rf $out/.xwin-cache
|
||||
'';
|
||||
};
|
||||
|
||||
# the linker asks for `kernel32.lib` of a file that is `Kernel32.lib`, so
|
||||
# on a case-sensitive host add a lowercase alias for every name with a
|
||||
# capital in it, and the spellings the headers include each other by (the
|
||||
# SDK itself is made without symlinks)
|
||||
caseFolded =
|
||||
{ pkgs, windowsSdk }:
|
||||
if pkgs.stdenv.hostPlatform.isDarwin then
|
||||
windowsSdk
|
||||
else
|
||||
pkgs.runCommandLocal "${windowsSdk.name}-case-folded" { } ''
|
||||
cp -rs ${windowsSdk} $out
|
||||
chmod -R u+w $out
|
||||
cd $out
|
||||
find . -name '*[A-Z]*' | while read -r path; do
|
||||
directory=$(dirname "$path")
|
||||
name=$(basename "$path")
|
||||
lower=$(echo "$name" | tr 'A-Z' 'a-z')
|
||||
if [ ! -e "$directory/$lower" ] && [ ! -L "$directory/$lower" ]; then
|
||||
ln -s "$name" "$directory/$lower"
|
||||
fi
|
||||
done
|
||||
|
||||
# headers include each other with spellings that differ from the
|
||||
# file name (`DriverSpecs.h` for `driverspecs.h`), which xwin
|
||||
# covers with symlinks unless told not to
|
||||
grep -Rhoi -E '^[[:space:]]*#[[:space:]]*include[[:space:]]*[<"][^>"]+[>"]' \
|
||||
crt/include sdk/include 2>/dev/null \
|
||||
| sed -E 's/.*[<"]([^>"]+)[>"]/\1/; s#\\#/#g; s#.*/##' \
|
||||
| sort -u > $TMPDIR/spellings
|
||||
find crt/include sdk/include \( -type f -o -type l \) \
|
||||
| awk -v spellings=$TMPDIR/spellings '
|
||||
BEGIN {
|
||||
while ((getline line < spellings) > 0)
|
||||
known[tolower(line)] = known[tolower(line)] "\n" line
|
||||
}
|
||||
{
|
||||
n = split($0, parts, "/"); base = parts[n]
|
||||
dir = substr($0, 1, length($0) - length(base))
|
||||
m = split(known[tolower(base)], names, "\n")
|
||||
for (i = 1; i <= m; i++)
|
||||
if (names[i] != "" && names[i] != base)
|
||||
print dir "\t" base "\t" names[i]
|
||||
}' \
|
||||
| while IFS=$'\t' read -r directory name spelling; do
|
||||
if [ ! -e "$directory$spelling" ] && [ ! -L "$directory$spelling" ]; then
|
||||
ln -s "$name" "$directory$spelling"
|
||||
fi
|
||||
done
|
||||
'';
|
||||
|
||||
mkMsvcEnv =
|
||||
{ pkgs, windowsSdk }:
|
||||
let
|
||||
sdk = caseFolded { inherit pkgs windowsSdk; };
|
||||
clangVersion = pkgs.lib.versions.major pkgs.llvmPackages.clang.version;
|
||||
in
|
||||
{
|
||||
# linker for the windows target
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER = "lld-link";
|
||||
|
||||
# c/c++ compiler
|
||||
CC_x86_64_pc_windows_msvc = "clang-cl";
|
||||
CXX_x86_64_pc_windows_msvc = "clang-cl";
|
||||
AR_x86_64_pc_windows_msvc = "llvm-lib";
|
||||
|
||||
# IMPORTANT: libclang include path MUST come first to avoid header conflicts
|
||||
CFLAGS_x86_64_pc_windows_msvc = builtins.concatStringsSep " " [
|
||||
"--target=x86_64-pc-windows-msvc"
|
||||
"-Wno-unused-command-line-argument"
|
||||
"-fuse-ld=lld-link"
|
||||
"/imsvc${pkgs.llvmPackages.libclang.lib}/lib/clang/${clangVersion}/include"
|
||||
"/imsvc${sdk}/crt/include"
|
||||
"/imsvc${sdk}/sdk/include/ucrt"
|
||||
"/imsvc${sdk}/sdk/include/um"
|
||||
"/imsvc${sdk}/sdk/include/shared"
|
||||
];
|
||||
|
||||
CXXFLAGS_x86_64_pc_windows_msvc = builtins.concatStringsSep " " [
|
||||
"--target=x86_64-pc-windows-msvc"
|
||||
"-Wno-unused-command-line-argument"
|
||||
"-fuse-ld=lld-link"
|
||||
"/imsvc${pkgs.llvmPackages.libclang.lib}/lib/clang/${clangVersion}/include"
|
||||
"/imsvc${sdk}/crt/include"
|
||||
"/imsvc${sdk}/sdk/include/ucrt"
|
||||
"/imsvc${sdk}/sdk/include/um"
|
||||
"/imsvc${sdk}/sdk/include/shared"
|
||||
];
|
||||
|
||||
# target-specific rust flags with linker flavor and library search paths
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS = builtins.concatStringsSep " " [
|
||||
"-Clinker-flavor=lld-link"
|
||||
"-Lnative=${sdk}/crt/lib/x86_64"
|
||||
"-Lnative=${sdk}/sdk/lib/um/x86_64"
|
||||
"-Lnative=${sdk}/sdk/lib/ucrt/x86_64"
|
||||
];
|
||||
|
||||
# cargo target
|
||||
CARGO_BUILD_TARGET = "x86_64-pc-windows-msvc";
|
||||
};
|
||||
|
||||
mkKomorebiPackages =
|
||||
{
|
||||
pkgs,
|
||||
windowsSdk,
|
||||
# the commit stamped into the binaries; a build for the e2e guest
|
||||
# gives a constant one, so that a new commit does not rebuild it
|
||||
commit ? self.rev or (pkgs.lib.removeSuffix "-dirty" (self.dirtyRev or "unknown")),
|
||||
}:
|
||||
let
|
||||
# toolchain with windows msvc target
|
||||
toolchain = (pkgs.rust-bin.fromRustupToolchainFile ../../rust-toolchain.toml).override {
|
||||
targets = [ "x86_64-pc-windows-msvc" ];
|
||||
};
|
||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||
|
||||
msvcEnv = mkMsvcEnv { inherit pkgs windowsSdk; };
|
||||
|
||||
# the Windows members of the one Cargo workspace; the Linux and macOS members are stubs
|
||||
# (nix/workspace-src.nix), so that an edit of one changes nothing here
|
||||
inherit
|
||||
(import ../workspace-src.nix {
|
||||
inherit pkgs craneLib;
|
||||
repoRoot = ../..;
|
||||
platform = "windows";
|
||||
})
|
||||
real
|
||||
src
|
||||
stubbedPackages
|
||||
;
|
||||
|
||||
lockFile = lib'.repoFile "Cargo.lock";
|
||||
tomlFile = lib'.repoFile "Cargo.toml";
|
||||
|
||||
workspaceArgs = {
|
||||
pname = "komorebi-workspace-windows";
|
||||
inherit version;
|
||||
# the lock and the root manifest as files of their own: a path inside the filtered source would put the
|
||||
# whole filtered source into the context of every derivation, and then an edit of any file
|
||||
# would change the dependencies
|
||||
cargoLock = lockFile;
|
||||
cargoToml = tomlFile;
|
||||
cargoVendorDir = craneLib.vendorCargoDeps { cargoLock = lockFile; };
|
||||
};
|
||||
|
||||
commonArgs = workspaceArgs // {
|
||||
inherit src;
|
||||
strictDeps = true;
|
||||
# applications.json is committed now; this copies the pinned asc input over it, so that the
|
||||
# embedded file is the pinned one even when the committed copy is older
|
||||
preBuild = "mkdir -p komorebic && cp ${inputs.asc}/applications.json komorebic/applications.json";
|
||||
# a constant, so that the dependencies and every check are the same
|
||||
# derivations for every commit; only fullBuild stamps the real one
|
||||
COMMIT_HASH = "nix-check";
|
||||
|
||||
# build inputs for cross-compilation
|
||||
nativeBuildInputs = [
|
||||
pkgs.llvmPackages.clang-unwrapped
|
||||
pkgs.llvmPackages.lld
|
||||
pkgs.llvmPackages.llvm
|
||||
# komorebic build script uses reqwest, which runs on the build host
|
||||
pkgs.pkg-config
|
||||
pkgs.openssl
|
||||
pkgs.openssl.dev
|
||||
];
|
||||
|
||||
# point the host-side openssl-sys build at the nix openssl
|
||||
OPENSSL_NO_VENDOR = "1";
|
||||
OPENSSL_LIB_DIR = "${pkgs.openssl.out}/lib";
|
||||
OPENSSL_INCLUDE_DIR = "${pkgs.openssl.dev}/include";
|
||||
|
||||
# cross-compilation environment
|
||||
inherit (msvcEnv)
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_LINKER
|
||||
CC_x86_64_pc_windows_msvc
|
||||
CXX_x86_64_pc_windows_msvc
|
||||
AR_x86_64_pc_windows_msvc
|
||||
CFLAGS_x86_64_pc_windows_msvc
|
||||
CXXFLAGS_x86_64_pc_windows_msvc
|
||||
CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUSTFLAGS
|
||||
CARGO_BUILD_TARGET
|
||||
;
|
||||
};
|
||||
|
||||
# the dummy source is of the manifests alone (nix/lib.nix): the dependencies are the same
|
||||
# derivations for every source file and every stub, and nothing is built at evaluation
|
||||
cargoArtifacts = craneLib.buildDepsOnly (
|
||||
builtins.removeAttrs commonArgs [ "src" ]
|
||||
// {
|
||||
dummySrc = craneLib.mkDummySrc {
|
||||
src = lib'.manifestSource pkgs.lib;
|
||||
cargoLock = lockFile;
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
individualCrateArgs = commonArgs // {
|
||||
inherit cargoArtifacts;
|
||||
doCheck = false;
|
||||
doDoc = false;
|
||||
};
|
||||
|
||||
fullBuild = craneLib.buildPackage (
|
||||
individualCrateArgs
|
||||
// {
|
||||
pname = "komorebi-workspace";
|
||||
COMMIT_HASH = commit;
|
||||
}
|
||||
);
|
||||
|
||||
extractBinary =
|
||||
binaryName:
|
||||
pkgs.runCommand "komorebi-${binaryName}"
|
||||
{
|
||||
meta = fullBuild.meta // { };
|
||||
}
|
||||
''
|
||||
mkdir -p $out/bin
|
||||
cp ${fullBuild}/bin/${binaryName}.exe $out/bin/
|
||||
'';
|
||||
in
|
||||
{
|
||||
inherit
|
||||
craneLib
|
||||
src
|
||||
real
|
||||
workspaceArgs
|
||||
stubbedPackages
|
||||
individualCrateArgs
|
||||
fullBuild
|
||||
msvcEnv
|
||||
;
|
||||
komorebi = extractBinary "komorebi";
|
||||
komorebic = extractBinary "komorebic";
|
||||
komorebic-no-console = extractBinary "komorebic-no-console";
|
||||
komorebi-bar = extractBinary "komorebi-bar";
|
||||
komorebi-gui = extractBinary "komorebi-gui";
|
||||
komorebi-shortcuts = extractBinary "komorebi-shortcuts";
|
||||
komorebi-testwin = extractBinary "komorebi-testwin";
|
||||
komorebi-e2e-agent = extractBinary "komorebi-e2e-agent";
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit mkWindowsSdk mkMsvcEnv mkKomorebiPackages;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
# komorebi for Windows, cross-built with xwin (x86_64-pc-windows-msvc): the `windows-*` packages,
|
||||
# apps and checks, and the Windows e2e guest. Built on Linux (and on Apple silicon); the binaries run
|
||||
# on Windows only.
|
||||
{
|
||||
inputs,
|
||||
self,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
let
|
||||
lib' = import ../lib.nix { inherit inputs; };
|
||||
windows = import ./build.nix { inherit inputs self; };
|
||||
in
|
||||
{
|
||||
perSystem =
|
||||
{ pkgs, system, ... }:
|
||||
let
|
||||
windowsSdk = windows.mkWindowsSdk pkgs;
|
||||
build = windows.mkKomorebiPackages { inherit pkgs windowsSdk; };
|
||||
# the binaries the e2e guest runs: the same build, but with a
|
||||
# constant commit stamp, so a new commit (or a dirty tree) that does
|
||||
# not change a source file reuses it. The commit under test is
|
||||
# KOMOREBI_E2E_COMMIT, not what the binary says.
|
||||
e2eBuild = windows.mkKomorebiPackages {
|
||||
inherit pkgs windowsSdk;
|
||||
commit = "e2e";
|
||||
};
|
||||
|
||||
# OVMF without SMM and with the TPM support Windows 11 Setup asks for
|
||||
ovmfWithTpm = (pkgs.OVMF.override { tpmSupport = true; }).fd;
|
||||
e2eWindows = pkgs.writeShellApplication {
|
||||
name = "e2e-windows";
|
||||
runtimeInputs = [
|
||||
pkgs.qemu
|
||||
pkgs.swtpm
|
||||
(pkgs.python3.withPackages (p: [ p.pillow ]))
|
||||
];
|
||||
text = ''
|
||||
: "''${E2E_GOLDEN:?set E2E_GOLDEN to the golden image directory}"
|
||||
out=''${1:?usage: e2e-windows OUT SCENARIO...}
|
||||
shift
|
||||
# the binaries under test: this checkout's, or those of another
|
||||
# commit, made by e2e/platforms/qemu_windows/build-ref.sh
|
||||
if [ -n "''${KOMOREBI_E2E_BINS:-}" ]; then
|
||||
bins=$KOMOREBI_E2E_BINS
|
||||
if [ -f "$bins/commit" ]; then
|
||||
KOMOREBI_E2E_COMMIT=$(cat "$bins/commit")
|
||||
fi
|
||||
else
|
||||
bins=$(mktemp -d)
|
||||
trap 'rm -rf "$bins"' EXIT
|
||||
cp ${e2eBuild.komorebi}/bin/komorebi.exe "$bins"
|
||||
cp ${e2eBuild.komorebic}/bin/komorebic.exe "$bins"
|
||||
cp ${e2eBuild.komorebi-testwin}/bin/komorebi-testwin.exe "$bins"
|
||||
cp ${e2eBuild.komorebi-bar}/bin/komorebi-bar.exe "$bins"
|
||||
fi
|
||||
export OVMF_FD=${ovmfWithTpm}
|
||||
export KOMOREBI_E2E_BAR_SCHEMA=${lib'.repoFile "schemas/windows/schema.bar.json"}
|
||||
export KOMOREBI_E2E_COMMIT=''${KOMOREBI_E2E_COMMIT:-${self.rev or "dirty"}}
|
||||
export PYTHONPATH=${lib'.repoFile "e2e/lib"}:${lib'.repoFile "e2e"}
|
||||
exec python -m platforms.qemu_windows.run \
|
||||
"$E2E_GOLDEN" "$bins" "$out" "$@"
|
||||
'';
|
||||
};
|
||||
# the nightly rustfmt of the checks is the one of the dev shell: see nix/dev-shell.nix
|
||||
nightlyRustfmt = pkgs.rust-bin.nightly.latest.rustfmt;
|
||||
in
|
||||
{
|
||||
# the dev shell (nix/dev-shell.nix) cross-compiles with these
|
||||
_module.args = {
|
||||
inherit windowsSdk ovmfWithTpm;
|
||||
inherit (build) msvcEnv;
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (builtins.elem system lib'.windowsSystems) {
|
||||
checks = {
|
||||
windows-clippy = build.craneLib.cargoClippy (
|
||||
build.individualCrateArgs
|
||||
// {
|
||||
cargoClippyExtraArgs = "--all-targets -- -D warnings";
|
||||
}
|
||||
);
|
||||
|
||||
# the nightly rustfmt over the Windows files, as tools/format-all does locally. Not `cargo fmt`:
|
||||
# it runs the stable rustfmt (which ignores the nightly options of rustfmt.toml) and follows
|
||||
# `mod linux;` into files the Windows source does not have.
|
||||
windows-fmt =
|
||||
pkgs.runCommand "komorebi-windows-fmt"
|
||||
{
|
||||
nativeBuildInputs = [ nightlyRustfmt ];
|
||||
}
|
||||
''
|
||||
RUSTFMT=rustfmt bash ${lib'.repoFile "tools/format-all"} --check --root ${build.real}
|
||||
touch $out
|
||||
'';
|
||||
|
||||
windows-toml-fmt = build.craneLib.taploFmt (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
src = pkgs.lib.sources.sourceFilesBySuffices build.real [ ".toml" ];
|
||||
}
|
||||
);
|
||||
|
||||
# cargo deny sees every member of the workspace: leave out the Linux and macOS packages, which
|
||||
# are stubs here and have their own checks (linux-deny, macos-deny)
|
||||
windows-deny = build.craneLib.cargoDeny (
|
||||
build.workspaceArgs
|
||||
// {
|
||||
inherit (build) src;
|
||||
cargoDenyExtraArgs =
|
||||
"--workspace " + pkgs.lib.concatMapStringsSep " " (p: "--exclude ${p}") build.stubbedPackages;
|
||||
}
|
||||
);
|
||||
|
||||
windows-nextest = build.craneLib.cargoNextest build.individualCrateArgs;
|
||||
}
|
||||
// {
|
||||
# the Python of the Windows e2e guest that needs no guest: the
|
||||
# vendored core's tests and those of the runner
|
||||
windows-e2e-tests =
|
||||
pkgs.runCommand "windows-e2e-tests"
|
||||
{
|
||||
nativeBuildInputs = [
|
||||
pkgs.git
|
||||
(pkgs.python3.withPackages (p: [
|
||||
p.pillow
|
||||
p.pytest
|
||||
]))
|
||||
];
|
||||
}
|
||||
''
|
||||
cp -r ${lib'.repoFile "e2e"} e2e
|
||||
chmod -R u+w e2e
|
||||
cd e2e
|
||||
export HOME=$TMPDIR PYTHONPATH=$PWD/lib:$PWD
|
||||
python -m pytest -q -p no:cacheprovider lib/tests platforms/qemu_windows/tests
|
||||
touch $out
|
||||
'';
|
||||
};
|
||||
|
||||
packages = {
|
||||
windows-komorebi = build.komorebi;
|
||||
windows-komorebic = build.komorebic;
|
||||
windows-komorebic-no-console = build.komorebic-no-console;
|
||||
windows-komorebi-bar = build.komorebi-bar;
|
||||
windows-komorebi-gui = build.komorebi-gui;
|
||||
windows-komorebi-shortcuts = build.komorebi-shortcuts;
|
||||
windows-komorebi-testwin = build.komorebi-testwin;
|
||||
windows-komorebi-e2e-agent = build.komorebi-e2e-agent;
|
||||
windows-sdk = windowsSdk;
|
||||
# the test window of the Windows e2e guest, built with the constant
|
||||
# stamp: a new commit does not rebuild what it depends on
|
||||
windows-komorebi-testwin-e2e = e2eBuild.komorebi-testwin;
|
||||
windows-komorebi-full = build.fullBuild;
|
||||
windows-default = build.fullBuild;
|
||||
};
|
||||
|
||||
apps = {
|
||||
windows-komorebi = {
|
||||
type = "app";
|
||||
program = "${build.komorebi}/bin/komorebi.exe";
|
||||
};
|
||||
windows-komorebic = {
|
||||
type = "app";
|
||||
program = "${build.komorebic}/bin/komorebic.exe";
|
||||
};
|
||||
windows-komorebic-no-console = {
|
||||
type = "app";
|
||||
program = "${build.komorebic-no-console}/bin/komorebic-no-console.exe";
|
||||
};
|
||||
windows-komorebi-bar = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-bar}/bin/komorebi-bar.exe";
|
||||
};
|
||||
windows-komorebi-gui = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-gui}/bin/komorebi-gui.exe";
|
||||
};
|
||||
windows-komorebi-shortcuts = {
|
||||
type = "app";
|
||||
program = "${build.komorebi-shortcuts}/bin/komorebi-shortcuts.exe";
|
||||
};
|
||||
windows-default = {
|
||||
type = "app";
|
||||
program = "${build.fullBuild}/bin/komorebi.exe";
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs (system == "x86_64-linux") {
|
||||
# the neutral scenarios against a throwaway Windows guest:
|
||||
# E2E_GOLDEN=<golden image dir> nix run .#e2e-windows -- \
|
||||
# OUT SCENARIO...
|
||||
# KOMOREBI_E2E_BINS=<dir from build-ref.sh> tests another commit
|
||||
# the golden image is built once with
|
||||
# e2e/platforms/qemu_windows/build-golden.sh
|
||||
e2e-windows = {
|
||||
type = "app";
|
||||
program = pkgs.lib.getExe e2eWindows;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
+172
-16
@@ -1,22 +1,168 @@
|
||||
# The source of a build from the one Cargo workspace of this repository.
|
||||
# The source of a build of one platform, cut from the one Cargo workspace of this repository.
|
||||
#
|
||||
# Cargo has to load every member of the workspace, but a build of one platform needs the sources of
|
||||
# that platform's crates only. `real` is the filtered source (the platform's crates, the crates of the
|
||||
# root workspace they depend on, the root manifest and lock); every other member (`isReal` is false)
|
||||
# is added as its own manifest with an empty library and a `main` that does nothing. An edit of a
|
||||
# crate of another platform then changes nothing here, and an edit of another platform's manifest
|
||||
# changes only the stub copy of it.
|
||||
# import ./workspace-src.nix { pkgs; craneLib; repoRoot; platform = "windows" | "linux" | "macos"; }
|
||||
#
|
||||
# workspaceSrc { pkgs; repoRoot; real; isReal = member: bool; }
|
||||
# Cargo has to load every member of the workspace (the root manifest lists the members of all three
|
||||
# platforms), but a build of one platform needs the sources of that platform's crates only. The result:
|
||||
#
|
||||
# real the filtered source: the members of the platform, the root manifest and lock, the
|
||||
# platform's files of the crates the platforms share, and the data files they read
|
||||
# src `real` plus, for every other member, its own manifest with an empty library and a `main`
|
||||
# that does nothing (a stub: cargo refuses a workspace with a member that is not there, and
|
||||
# a lock file that has packages the workspace does not have fails under --locked)
|
||||
# members the members of the platform; stubbed the others; stubbedPackages their package names (for
|
||||
# `cargo deny --exclude`)
|
||||
#
|
||||
# An edit under one platform therefore changes nothing in the derivations of the others, except where
|
||||
# the edit is in a crate they share or in the root manifest, lock or toolchain files.
|
||||
{
|
||||
pkgs,
|
||||
craneLib,
|
||||
repoRoot,
|
||||
real,
|
||||
isReal,
|
||||
platform,
|
||||
}:
|
||||
let
|
||||
inherit (pkgs) lib;
|
||||
members = (builtins.fromTOML (builtins.readFile "${real}/Cargo.toml")).workspace.members;
|
||||
root = toString repoRoot;
|
||||
|
||||
allMembers = (builtins.fromTOML (builtins.readFile (repoRoot + "/Cargo.toml"))).workspace.members;
|
||||
|
||||
# the crates of the root workspace that the KDE packages depend on, by path (nix/linux/root-crates.json,
|
||||
# kept equal to `cargo tree` by tools/kde-closure-check); komorebi-bar and komorebi-bar-core (the egui
|
||||
# bar) are not in it, so an edit of the bar does not rebuild the KDE packages
|
||||
linuxShared = builtins.fromJSON (builtins.readFile ./linux/root-crates.json) ++ [
|
||||
"komorebi-daemon"
|
||||
];
|
||||
|
||||
linuxOnly = [
|
||||
"komorebi-linux"
|
||||
"komorebi-hotkeys"
|
||||
];
|
||||
macosOnly = [ "komorebi-macos" ];
|
||||
|
||||
membersOf = {
|
||||
# everything but the other two platforms' daemons
|
||||
windows = builtins.filter (m: !(builtins.elem m (linuxOnly ++ macosOnly))) allMembers;
|
||||
linux = linuxOnly ++ linuxShared;
|
||||
macos =
|
||||
macosOnly
|
||||
++ [
|
||||
"komorebic"
|
||||
"komorebi-client"
|
||||
"komorebi-bar"
|
||||
"komorebi-daemon"
|
||||
"komorebi-layouts"
|
||||
"komorebi-scrolling"
|
||||
"komorebi-themes"
|
||||
]
|
||||
++ builtins.filter (m: lib.hasPrefix "crates/" m) allMembers;
|
||||
};
|
||||
|
||||
members = builtins.filter (m: builtins.elem m membersOf.${platform}) allMembers;
|
||||
stubbed = builtins.filter (m: !(builtins.elem m members)) allMembers;
|
||||
stubbedPackages = map (
|
||||
m: (builtins.fromTOML (builtins.readFile (repoRoot + "/${m}/Cargo.toml"))).package.name
|
||||
) stubbed;
|
||||
|
||||
# the crates one entry point serves for every platform: each keeps its own platform's modules and
|
||||
# tests (named by prefix) and drops the other platforms'
|
||||
sharedCrates = [
|
||||
"komorebic"
|
||||
"komorebi-client"
|
||||
"komorebi-bar"
|
||||
"komorebi-daemon"
|
||||
];
|
||||
markers = {
|
||||
windows = "(src/windows(\\.rs|/.*)|tests/windows_.*)";
|
||||
linux = "(src/linux(\\.rs|/.*)|tests/linux_.*)";
|
||||
macos = "(src/macos(\\.rs|/.*)|tests/macos_.*)";
|
||||
};
|
||||
otherMarkers = builtins.attrValues (removeAttrs markers [ platform ]);
|
||||
ofOtherPlatform =
|
||||
rel:
|
||||
builtins.any (
|
||||
crate:
|
||||
lib.hasPrefix "${crate}/" rel
|
||||
&& builtins.any (
|
||||
marker: builtins.match marker (lib.removePrefix "${crate}/" rel) != null
|
||||
) otherMarkers
|
||||
) sharedCrates;
|
||||
|
||||
# the directories of the source (a file is kept only under one of them)
|
||||
roots =
|
||||
members
|
||||
++ [
|
||||
"docs"
|
||||
"schemas"
|
||||
".cargo"
|
||||
]
|
||||
# the configurations that the config_parity test of komorebi-linux loads
|
||||
++ lib.optional (platform == "linux") "spikes/config-parity";
|
||||
underRoot = rel: builtins.any (r: rel == r || lib.hasPrefix "${r}/" rel) roots;
|
||||
# a directory above a root (`crates` for `crates/komorebi-core`)
|
||||
aboveRoot = rel: builtins.any (r: lib.hasPrefix "${rel}/" r) roots;
|
||||
|
||||
# data files that the Rust sources and tests read, outside the Cargo sources
|
||||
extra =
|
||||
rel:
|
||||
# the test inputs of every crate
|
||||
(builtins.match ".*/(tests|fixtures|golden)/.*" rel != null)
|
||||
|| {
|
||||
windows =
|
||||
# the whole of docs/ (they are embedded in komorebic and the bar) except the other platforms' and
|
||||
# the developer notes; the macOS CLI pages are read by a test of komorebic-core
|
||||
(
|
||||
lib.hasPrefix "docs/" rel
|
||||
&& !(builtins.any (p: lib.hasPrefix p rel) [
|
||||
"docs/linux/"
|
||||
"docs/macos/"
|
||||
"docs/dev/"
|
||||
])
|
||||
)
|
||||
|| lib.hasPrefix "docs/macos/cli/" rel
|
||||
|| lib.hasPrefix "schemas/" rel
|
||||
|| lib.hasPrefix "komorebic/fixtures/" rel;
|
||||
linux =
|
||||
# the script komorebi loads into KWin and the JSON the tests and the daemon read
|
||||
(lib.hasSuffix ".js" rel || lib.hasSuffix ".json" rel)
|
||||
&& !(lib.hasPrefix "docs/" rel || lib.hasPrefix "schemas/" rel)
|
||||
|| lib.hasPrefix "schemas/linux/" rel
|
||||
|| lib.hasPrefix "spikes/config-parity/" rel
|
||||
|| builtins.elem rel [
|
||||
# the example configuration and the sample key bindings that `komorebic quickstart` includes
|
||||
"docs/linux/komorebi.example.json"
|
||||
"docs/linux/skhdrc.sample"
|
||||
# the page that shows the example configuration, which a test compares with the file
|
||||
"docs/linux/example-configurations.md"
|
||||
# the example a test loads, to see that the docs show one that works
|
||||
"docs/linux/usage/wallpapers.md"
|
||||
];
|
||||
macos =
|
||||
lib.hasSuffix ".json" rel && !(lib.hasPrefix "docs/" rel || lib.hasPrefix "schemas/" rel)
|
||||
|| lib.hasPrefix "docs/macos/" rel
|
||||
|| lib.hasPrefix "schemas/macos/" rel
|
||||
|| lib.hasPrefix "komorebic/fixtures/" rel;
|
||||
}
|
||||
.${platform};
|
||||
|
||||
real = lib.cleanSourceWith {
|
||||
src = repoRoot;
|
||||
filter =
|
||||
path: type:
|
||||
let
|
||||
rel = lib.removePrefix "${root}/" path;
|
||||
isRootFile = !(lib.hasInfix "/" rel);
|
||||
in
|
||||
if type == "directory" then
|
||||
rel == root || aboveRoot rel || (underRoot rel && !(ofOtherPlatform rel))
|
||||
else
|
||||
# the files at the top: Cargo.toml, Cargo.lock, rust-toolchain.toml, rustfmt.toml, deny.toml
|
||||
(isRootFile && craneLib.filterCargoSources path type)
|
||||
|| (
|
||||
underRoot rel && !(ofOtherPlatform rel) && ((craneLib.filterCargoSources path type) || extra rel)
|
||||
);
|
||||
};
|
||||
|
||||
stub = member: ''
|
||||
mkdir -p $out/${member}/src
|
||||
cp ${
|
||||
@@ -28,9 +174,19 @@ let
|
||||
: > $out/${member}/src/lib.rs
|
||||
echo 'fn main() {}' > $out/${member}/src/main.rs
|
||||
'';
|
||||
|
||||
src = pkgs.runCommand "komorebi-${platform}-src" { } ''
|
||||
cp -r ${real} $out
|
||||
chmod -R u+w $out
|
||||
${lib.concatMapStrings stub stubbed}
|
||||
'';
|
||||
in
|
||||
pkgs.runCommand "komorebi-workspace-src" { } ''
|
||||
cp -r ${real} $out
|
||||
chmod -R u+w $out
|
||||
${lib.concatMapStrings stub (builtins.filter (m: !(isReal m)) members)}
|
||||
''
|
||||
{
|
||||
inherit
|
||||
real
|
||||
src
|
||||
members
|
||||
stubbed
|
||||
stubbedPackages
|
||||
;
|
||||
}
|
||||
Reference in new issue
Block a user