forked from cjpais/Handy
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathflake.nix
More file actions
281 lines (254 loc) · 9.68 KB
/
flake.nix
File metadata and controls
281 lines (254 loc) · 9.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
{
description = "Handy - A free, open source, and extensible speech-to-text application that works completely offline";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# bun2nix: generates per-package Nix fetchurl expressions from bun.lock,
# replacing the old FOD approach where a single hash covered the entire
# node_modules directory (that hash would break on bun version changes).
# See: https://github.com/nix-community/bun2nix
bun2nix = {
url = "github:nix-community/bun2nix/2.0.8";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
bun2nix,
}:
let
supportedSystems = [
"x86_64-linux"
"aarch64-linux"
];
forAllSystems = nixpkgs.lib.genAttrs supportedSystems;
# Read version from Cargo.toml
cargoToml = fromTOML (builtins.readFile ./src-tauri/Cargo.toml);
version = cargoToml.package.version;
in
{
packages = forAllSystems (
system:
let
pkgs = import nixpkgs {
inherit system;
overlays = [ bun2nix.overlays.default ];
};
lib = pkgs.lib;
in
{
handy = pkgs.rustPlatform.buildRustPackage {
pname = "handy";
inherit version;
src = self;
cargoRoot = "src-tauri";
cargoLock = {
lockFile = ./src-tauri/Cargo.lock;
# Automatically fetch git dependencies using builtins.fetchGit.
# This eliminates the need for manual outputHashes that had to be
# updated every time a git dependency changed in Cargo.lock.
# Safe for standalone flakes (not allowed in nixpkgs, it is needed something like crate2nix).
allowBuiltinFetchGit = true;
};
postPatch = ''
${pkgs.jq}/bin/jq 'del(.build.beforeBuildCommand) | .bundle.createUpdaterArtifacts = false' \
src-tauri/tauri.conf.json > $TMPDIR/tauri.conf.json
cp $TMPDIR/tauri.conf.json src-tauri/tauri.conf.json
# Strip postinstall hook — it runs check-nix-deps.ts which is only
# needed during local development, not inside the Nix sandbox.
${pkgs.jq}/bin/jq 'del(.scripts.postinstall)' \
package.json > $TMPDIR/package.json
cp $TMPDIR/package.json package.json
# Point libappindicator-sys to the Nix store path
substituteInPlace \
$cargoDepsCopy/libappindicator-sys-*/src/lib.rs \
--replace-fail \
"libayatana-appindicator3.so.1" \
"${pkgs.libayatana-appindicator}/lib/libayatana-appindicator3.so.1"
# Disable cbindgen in ferrous-opencc (calls cargo metadata which fails in sandbox)
# Upstream removed this call in v0.3.1+
substituteInPlace $cargoDepsCopy/ferrous-opencc-0.2.3/build.rs \
--replace-fail '.expect("Unable to generate bindings")' '.ok();'
substituteInPlace $cargoDepsCopy/ferrous-opencc-0.2.3/build.rs \
--replace-fail '.write_to_file("opencc.h");' '// skipped'
'';
# Bun dependencies: fetched per-package using hashes from .nix/bun.nix.
# This file is auto-generated by `bunx bun2nix -o .nix/bun.nix` and
# kept in sync via the postinstall hook in package.json.
# To regenerate manually: bun scripts/check-nix-deps.ts
bunDeps = pkgs.bun2nix.fetchBunDeps {
bunNix = ./.nix/bun.nix;
};
nativeBuildInputs = with pkgs; [
cargo-tauri.hook
pkg-config
wrapGAppsHook4
bun
# pkgs.bun2nix (from overlay), not the flake input — `with pkgs;`
# doesn't shadow function arguments in Nix.
pkgs.bun2nix.hook # Sets up node_modules from pre-fetched bun cache
jq
cmake
llvmPackages.libclang
shaderc
];
preBuild = ''
# bun2nix.hook has already set up node_modules from pre-fetched cache.
# Build the frontend with bun (tsc + vite).
export HOME=$TMPDIR
bun run build
'';
# Tests require runtime resources (audio devices, model files, GPU/Vulkan)
# not available in the Nix build sandbox
doCheck = false;
# The tauri hook's installPhase expects target/ in cwd, but our
# cargoRoot puts it under src-tauri/. Override to extract the DEB.
installPhase = ''
runHook preInstall
mkdir -p $out
cd src-tauri
mv target/${pkgs.stdenv.hostPlatform.rust.rustcTarget}/release/bundle/deb/*/data/usr/* $out/
runHook postInstall
'';
buildInputs = with pkgs; [
webkitgtk_4_1
gtk3
glib
glib-networking
libsoup_3
alsa-lib
onnxruntime
libayatana-appindicator
libevdev
libx11
libxtst
gtk-layer-shell
openssl
vulkan-loader
vulkan-headers
shaderc
# Required for WebKitGTK audio/video
gst_all_1.gstreamer
gst_all_1.gst-plugins-base
gst_all_1.gst-plugins-good
gst_all_1.gst-plugins-bad
gst_all_1.gst-plugins-ugly
];
env = {
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
BINDGEN_EXTRA_CLANG_ARGS = "-isystem ${pkgs.llvmPackages.libclang.lib}/lib/clang/${lib.getVersion pkgs.llvmPackages.libclang}/include -isystem ${pkgs.glibc.dev}/include";
ORT_LIB_LOCATION = "${pkgs.onnxruntime}/lib";
OPENSSL_NO_VENDOR = "1";
# Tell Gstreamer where to find plugins
GST_PLUGIN_SYSTEM_PATH_1_0 = "${pkgs.lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" (
with pkgs.gst_all_1;
[
gstreamer
gst-plugins-base
gst-plugins-good
gst-plugins-bad
gst-plugins-ugly
]
)}";
};
preFixup = ''
gappsWrapperArgs+=(
--set WEBKIT_DISABLE_DMABUF_RENDERER 1
--set ALSA_PLUGIN_DIR "${pkgs.pipewire}/lib/alsa-lib:${pkgs.alsa-plugins}/lib/alsa-lib"
--prefix LD_LIBRARY_PATH : "${
lib.makeLibraryPath [
pkgs.vulkan-loader
pkgs.onnxruntime
]
}"
)
'';
meta = {
description = "A free, open source, and extensible speech-to-text application that works completely offline";
homepage = "https://github.com/cjpais/Handy";
license = lib.licenses.mit;
mainProgram = "handy";
platforms = supportedSystems;
};
};
default = self.packages.${system}.handy;
}
);
# NixOS module for system-level integration (udev, input group)
nixosModules.default =
{ lib, pkgs, ... }:
{
imports = [ ./nix/module.nix ];
programs.handy.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.handy;
};
# Home-manager module for per-user service
homeManagerModules.default =
{ lib, pkgs, ... }:
{
imports = [ ./nix/hm-module.nix ];
services.handy.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.handy;
};
# Development shell for building from source
devShells = forAllSystems (
system:
let
pkgs = import nixpkgs {
inherit system;
};
in
{
default = pkgs.mkShell {
buildInputs = with pkgs; [
# Rust
rustc
cargo
rust-analyzer
clippy
# Frontend
nodejs
bun
# Tauri CLI
cargo-tauri
# Native deps
pkg-config
openssl
alsa-lib
libsoup_3
webkitgtk_4_1
gtk3
gtk-layer-shell
glib
libxtst
libevdev
llvmPackages.libclang
cmake
vulkan-headers
vulkan-loader
shaderc
libappindicator
];
LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath [ pkgs.libappindicator ]}";
GST_PLUGIN_SYSTEM_PATH_1_0 = "${pkgs.lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" (
with pkgs.gst_all_1;
[
gstreamer
gst-plugins-base
gst-plugins-good
gst-plugins-bad
gst-plugins-ugly
]
)}";
# Same as wrapGAppsHook4
XDG_DATA_DIRS = "${pkgs.gsettings-desktop-schemas}/share/gsettings-schemas/${pkgs.gsettings-desktop-schemas.name}:${pkgs.gtk3}/share/gsettings-schemas/${pkgs.gtk3.name}:${pkgs.hicolor-icon-theme}/share";
shellHook = ''
echo "Handy development environment"
bun install
echo "Run 'bun run tauri dev' to start"
'';
};
}
);
};
}