Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
576 lines (495 loc) · 28.9 KB
/
Copy pathMakefile
File metadata and controls
576 lines (495 loc) · 28.9 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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
COMMIT := $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
VERSION := $(shell git describe --tags --abbrev=0 2>/dev/null || echo "0.1.0-beta")
# Tags carry the v prefix, nothing built from them does: one form from here on.
override VERSION := $(patsubst v%,%,$(VERSION))
LDFLAGS := -X github.com/KeibiSoft/KeibiDrop/pkg/logic/common.Version=$(VERSION) \
-X github.com/KeibiSoft/KeibiDrop/pkg/logic/common.CommitHash=$(COMMIT)
DIST := dist
GOARCH := $(shell go env GOARCH)
GOOS := $(shell go env GOOS)
# Every go command here runs the Go that go.mod names, as CI does (setup-go reads
# go.mod), so a newer or older local Go builds the same binaries. An explicit
# GOTOOLCHAIN wins: the release job sets local.
GO_MOD_VERSION := $(shell awk '/^go /{print $$2; exit}' go.mod)
export GOTOOLCHAIN ?= go$(GO_MOD_VERSION)
# ── Windows: CGO env for WinFSP (cgofuse requires its headers + lib) ──────────
# Uses the 8.3 short path to avoid spaces breaking the linker -L flag.
# LIBCLANG_PATH is needed by bindgen (Rust build.rs) to locate libclang.dll.
ifeq ($(GOOS),windows)
WINFSP_DIR := C:/PROGRA~2/WinFsp
export CPATH := $(WINFSP_DIR)/inc/fuse
export CGO_LDFLAGS := -L$(WINFSP_DIR)/lib
export LIBCLANG_PATH := C:/Program Files/LLVM/bin
EXE := .exe
endif
# ── Build ──────────────────────────────────────────────────
build-cli:
go build -ldflags="$(LDFLAGS)" -o keibidrop-cli$(EXE) cmd/cli/keibidrop-cli.go
build-kd:
go build -ldflags="$(LDFLAGS)" -o kd$(EXE) ./cmd/kd
# kdmcp is the MCP server an AI agent launches. One self-contained binary with
# no Go dependencies outside this module. Built with cgo like every other
# KeibiDrop binary, so it carries the FUSE mount, which is the reason an agent
# uses KeibiDrop instead of a copy tool.
# -trimpath keeps build paths out of the shipped binary.
build-kdmcp:
go build -trimpath -ldflags="-s -w $(LDFLAGS)" -o kdmcp$(EXE) ./cmd/kdmcp
build-static-rust-bridge:
go build -ldflags="$(LDFLAGS)" -buildmode=c-archive -o libkeibidrop.a ./rustbridge
build-rust: protoc build-static-rust-bridge
cd rust && cargo build --release
# Windows needs the GNU toolchain for the Rust half. build-static-rust-bridge
# above produces a Go c-archive, and Go emits Windows objects for the MinGW
# linker, so MSVC link.exe rejects the .pdata unwind records inside go.o with
# LNK1223. Targeting x86_64-pc-windows-gnu hands the archive to the ld that
# produced it. The result is copied to the normal release path so
# package-windows and the signing step find it where they already look.
RUST_WINDOWS_TARGET := x86_64-pc-windows-gnu
build-rust-windows: protoc build-static-rust-bridge
cd rust && cargo build --release --target $(RUST_WINDOWS_TARGET)
mkdir -p rust/target/release
cp rust/target/$(RUST_WINDOWS_TARGET)/release/keibidrop-rust.exe rust/target/release/keibidrop-rust.exe
build-all: build-rust build-cli build-kd build-kdmcp
# Cross-compile for macOS arm64 (from Intel) or x86_64 (from arm64)
# Usage: make cross-macos CROSS_ARCH=arm64 (from Intel Mac, target M1/M2)
# make cross-macos CROSS_ARCH=amd64 (from M1/M2, target Intel)
CROSS_ARCH ?= arm64
CROSS_RUST_TARGET_arm64 := aarch64-apple-darwin
CROSS_RUST_TARGET_amd64 := x86_64-apple-darwin
CROSS_RUST_TARGET := $(CROSS_RUST_TARGET_$(CROSS_ARCH))
cross-macos:
@echo "Cross-compiling for macOS $(CROSS_ARCH)..."
# Go static lib for Rust FFI
CGO_ENABLED=1 GOARCH=$(CROSS_ARCH) go build -ldflags="$(LDFLAGS)" -buildmode=c-archive -o libkeibidrop.a ./rustbridge
# Rust UI
rustup target add $(CROSS_RUST_TARGET) 2>/dev/null || true
cd rust && cargo build --release --target $(CROSS_RUST_TARGET)
# Go CLI binaries
CGO_ENABLED=1 CGO_CFLAGS="-arch $(if $(filter arm64,$(CROSS_ARCH)),arm64,x86_64)" \
CGO_LDFLAGS="-arch $(if $(filter arm64,$(CROSS_ARCH)),arm64,x86_64)" \
GOARCH=$(CROSS_ARCH) go build -ldflags="$(LDFLAGS)" -o keibidrop-cli-$(CROSS_ARCH) cmd/cli/keibidrop-cli.go
CGO_ENABLED=1 CGO_CFLAGS="-arch $(if $(filter arm64,$(CROSS_ARCH)),arm64,x86_64)" \
CGO_LDFLAGS="-arch $(if $(filter arm64,$(CROSS_ARCH)),arm64,x86_64)" \
GOARCH=$(CROSS_ARCH) go build -ldflags="$(LDFLAGS)" -o kd-$(CROSS_ARCH) ./cmd/kd
@echo "Done. Binaries: keibidrop-cli-$(CROSS_ARCH), kd-$(CROSS_ARCH)"
@echo "Rust UI: rust/target/$(CROSS_RUST_TARGET)/release/keibidrop-rust"
# Package cross-compiled DMG
cross-macos-dmg: cross-macos $(DIST)
@echo "Packaging cross-compiled macOS .dmg for $(CROSS_ARCH)..."
mkdir -p $(DIST)/dmg-cross/KeibiDrop.app/Contents/MacOS $(DIST)/dmg-cross/KeibiDrop.app/Contents/Resources
cp rust/target/$(CROSS_RUST_TARGET)/release/keibidrop-rust $(DIST)/dmg-cross/KeibiDrop.app/Contents/MacOS/keibidrop
cp keibidrop-cli-$(CROSS_ARCH) $(DIST)/dmg-cross/KeibiDrop.app/Contents/MacOS/keibidrop-cli
cp kd-$(CROSS_ARCH) $(DIST)/dmg-cross/KeibiDrop.app/Contents/MacOS/kd
cp assets/icons/keibidrop.icns $(DIST)/dmg-cross/KeibiDrop.app/Contents/Resources/keibidrop.icns
sed 's/VERSION_PLACEHOLDER/$(VERSION)/g' assets/Info.plist.tmpl > $(DIST)/dmg-cross/KeibiDrop.app/Contents/Info.plist
ln -s /Applications $(DIST)/dmg-cross/Applications
hdiutil create -volname "KeibiDrop $(VERSION)" \
-srcfolder $(DIST)/dmg-cross -ov -format UDZO \
$(DIST)/keibidrop-$(VERSION)-darwin-$(CROSS_ARCH).dmg
rm -rf $(DIST)/dmg-cross
@echo "Created $(DIST)/keibidrop-$(VERSION)-darwin-$(CROSS_ARCH).dmg"
# ── Test & Lint ────────────────────────────────────────────
# Heavy throughput benchmarks (run them explicitly) and the slow git-clone
# integration are skipped in the default suite. Single source of truth: CI
# (.github/workflows/ci.yml) runs `make test`, so this list stays in sync.
TEST_SKIP := BlockSizeSweep|WorkerCountSweep|PullFileProfile|BaselineComparison|FUSEReadOverhead|FUSEWriteThroughput|TransferThroughputNetem|MeasureLatency|OpenCloseLatency|ChunkLatency|PullFileThroughput|EncryptedGRPC|TransferThroughput|SecureConnThroughput|RoundTripFUSETransfer|FUSEtoFUSE_GitClone
test:
go test -v -count=1 -timeout 600s -skip '$(TEST_SKIP)' ./tests/...
# Deterministic concurrency-race guards under the race detector. Scoped to the
# in-process unit tests (no FUSE mount) across pkg/filesystem, pkg/session,
# pkg/logic/common and pkg/logic/service so it stays fast and cannot trip the
# unrelated cgofuse mount-teardown race that end-to-end FUSE tests hit under
# -race. Covers the Release async-notify race, the handle-reuse and
# prefetch-rename guards, the SecureConn double-close race, the
# onRekeyNeeded session-nil race, and the peer-path/read-size input guards.
test-race:
go test -race -count=1 -timeout 180s ./pkg/filesystem/ ./pkg/session/ ./pkg/logic/common/ ./pkg/logic/service/
# Unit suites outside ./tests that no other lane runs (identity, service,
# crypto, discovery, config, CLI, mobile bindings). Keychain suites
# self-skip on runners without a keychain.
test-pkgs:
go test -count=1 -timeout 300s ./pkg/identity/ ./pkg/logic/service/ ./pkg/crypto/ ./pkg/discovery/ ./internal/testkit/ ./cmd/kd/ ./internal/fp/ ./pkg/config/ ./pkg/sync-tracker/ ./pkg/feedback/ ./mobile/ ./cmd/kdmcp/
# Headless Slint UI tests: real ui.slint, no engine, no display. Needs
# libkeibidrop.a (make build-static-rust-bridge) for linking only.
test-ui:
cd rust && cargo test --test ui -- --test-threads=1
# The transport bench harness lives behind -tags bench (not in release builds).
test-bench:
go test -tags bench -count=1 -timeout 180s ./pkg/transport/
# ── Fleet: build + test across the whole REAL fleet (local Mac + Timisoara Linux +
# Singapore Windows) from ONE call. Encodes each env's quirks once (go PATH, source dir,
# buildvcs stamping, Windows cgo/WinFsp 8.3 short-path, PowerShell binding) so we stop
# stumbling on the same setup every time. Prints a loud per-host identity banner.
# make fleet # unit suites on all three hosts
# make fleet SCOPE=full # + ./tests integration suite (needs FUSE per host)
# make fleet WHERE=timisoara # a single host
# make fleet RUN=TestEnsurePeerScope # filter by -run pattern
.PHONY: fleet
fleet:
@KD_RUN='$(RUN)' bash fleet/run.sh '$(or $(WHERE),all)' '$(or $(SCOPE),unit)'
lint:
golangci-lint run ./...
sec:
gosec -exclude-generated -exclude-dir=research_artefacts -conf .gosec.json ./...
# ── Protobuf ──────────────────────────────────────────────
install-proto:
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.11
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.6.2
# NOTE: the pkg/transport/proto pb files carry a //go:build bench first line;
# regeneration drops it, re-add after running this target.
protoc:
PATH="$$PATH:$$(go env GOPATH)/bin" protoc \
--go_opt=module=github.com/KeibiSoft/KeibiDrop \
--go-grpc_opt=module=github.com/KeibiSoft/KeibiDrop \
--go_out=. --go-grpc_out=. \
keibidrop.proto \
pkg/transport/proto/bench.proto \
pkg/transport/proto/control/control.proto
# ── Rust helpers ──────────────────────────────────────────
# rust/build.rs writes rust/src/bindings.rs from libkeibidrop.h on every cargo
# build, with the bindgen that rust/Cargo.lock pins. This target runs that same
# generator, so it and build-rust always agree.
rust-bindings: build-static-rust-bridge
cd rust && cargo check
slint-preview:
slint-viewer rust/src/ui.slint
# ── Packaging ─────────────────────────────────────────────
$(DIST):
mkdir -p $(DIST)
# macOS .dmg — .app bundle with Applications symlink (drag-to-install)
package-macos: $(DIST)
@echo "Packaging macOS .dmg for $(GOARCH)..."
mkdir -p $(DIST)/dmg-staging
# Create .app bundle
mkdir -p $(DIST)/dmg-staging/KeibiDrop.app/Contents/MacOS
mkdir -p $(DIST)/dmg-staging/KeibiDrop.app/Contents/Resources
cp rust/target/release/keibidrop-rust $(DIST)/dmg-staging/KeibiDrop.app/Contents/MacOS/keibidrop
cp keibidrop-cli $(DIST)/dmg-staging/KeibiDrop.app/Contents/MacOS/
cp kd $(DIST)/dmg-staging/KeibiDrop.app/Contents/MacOS/
cp kdmcp $(DIST)/dmg-staging/KeibiDrop.app/Contents/MacOS/
cp assets/icons/keibidrop.icns $(DIST)/dmg-staging/KeibiDrop.app/Contents/Resources/keibidrop.icns
sed 's/VERSION_PLACEHOLDER/$(VERSION)/g' assets/Info.plist.tmpl > $(DIST)/dmg-staging/KeibiDrop.app/Contents/Info.plist
# Sign .app bundle if CODESIGN_IDENTITY is set
@if [ -n "$(CODESIGN_IDENTITY)" ]; then \
codesign --deep --force --options runtime --sign "$(CODESIGN_IDENTITY)" --timestamp $(DIST)/dmg-staging/KeibiDrop.app; \
echo "Signed KeibiDrop.app with $(CODESIGN_IDENTITY)"; \
fi
# Applications symlink for drag-to-install
ln -s /Applications $(DIST)/dmg-staging/Applications
hdiutil create -volname "KeibiDrop $(VERSION)" \
-srcfolder $(DIST)/dmg-staging \
-ov -format UDZO \
$(DIST)/keibidrop-$(VERSION)-darwin-$(GOARCH).dmg
rm -rf $(DIST)/dmg-staging
@echo "Created $(DIST)/keibidrop-$(VERSION)-darwin-$(GOARCH).dmg"
# Linux .tar.gz — universal fallback
package-tar: $(DIST)
@echo "Packaging .tar.gz for $(GOOS)-$(GOARCH)..."
mkdir -p $(DIST)/tar-staging/keibidrop-$(VERSION)
cp rust/target/release/keibidrop-rust $(DIST)/tar-staging/keibidrop-$(VERSION)/keibidrop
cp keibidrop-cli $(DIST)/tar-staging/keibidrop-$(VERSION)/
cp kd $(DIST)/tar-staging/keibidrop-$(VERSION)/
cp kdmcp $(DIST)/tar-staging/keibidrop-$(VERSION)/
cp README.md LICENSE $(DIST)/tar-staging/keibidrop-$(VERSION)/
cd $(DIST)/tar-staging && tar czf ../keibidrop-$(VERSION)-$(GOOS)-$(GOARCH).tar.gz keibidrop-$(VERSION)/
rm -rf $(DIST)/tar-staging
@echo "Created $(DIST)/keibidrop-$(VERSION)-$(GOOS)-$(GOARCH).tar.gz"
# Linux .deb — requires nfpm (go install github.com/goreleaser/nfpm/v2/cmd/nfpm@v2.46.0)
package-deb: $(DIST)
@echo "Packaging .deb for $(GOARCH)..."
VERSION=$(VERSION) GOARCH=$(GOARCH) nfpm package -p deb -f nfpm.yaml -t $(DIST)/
@echo "Created .deb in $(DIST)/"
# Windows .zip — contains kd.exe + keibidrop-cli.exe + keibidrop.exe + README + LICENSE
# WinFsp is NOT bundled — it's a Chocolatey dependency and installed separately.
package-windows: $(DIST)
@echo "Packaging Windows zip for $(GOARCH)..."
mkdir -p $(DIST)/win-staging
cp kd.exe $(DIST)/win-staging/ 2>/dev/null || cp kd $(DIST)/win-staging/kd.exe
cp keibidrop-cli.exe $(DIST)/win-staging/ 2>/dev/null || cp keibidrop-cli $(DIST)/win-staging/keibidrop-cli.exe
cp kdmcp.exe $(DIST)/win-staging/ 2>/dev/null || cp kdmcp $(DIST)/win-staging/kdmcp.exe
cp rust/target/release/keibidrop-rust.exe $(DIST)/win-staging/keibidrop.exe 2>/dev/null || true
cp README.md LICENSE LICENSING.md $(DIST)/win-staging/
ifeq ($(GOOS),windows)
powershell.exe -Command "Compress-Archive -Path '$(DIST)/win-staging/*' -DestinationPath '$(DIST)/keibidrop-$(VERSION)-windows-$(GOARCH).zip' -Force"
else
cd $(DIST)/win-staging && zip -r ../keibidrop-$(VERSION)-windows-$(GOARCH).zip .
endif
rm -rf $(DIST)/win-staging
@echo "Created $(DIST)/keibidrop-$(VERSION)-windows-$(GOARCH).zip"
# MCP bundle. kdmcp links cgofuse, so slices are built natively by the release
# matrix. macOS only: lipo joins the darwin slices.
# make package-mcpb VERSION=x.y.z MCPB_DARWIN_ARM64=.. MCPB_DARWIN_AMD64=.. \
# MCPB_WINDOWS=.. MCPB_LINUX=..
package-mcpb: $(DIST)
@test -n "$(MCPB_DARWIN_ARM64)" || (echo "ERROR: set MCPB_DARWIN_ARM64" && exit 1)
@test -n "$(MCPB_DARWIN_AMD64)" || (echo "ERROR: set MCPB_DARWIN_AMD64" && exit 1)
@test -n "$(MCPB_WINDOWS)" || (echo "ERROR: set MCPB_WINDOWS" && exit 1)
@test -n "$(MCPB_LINUX)" || (echo "ERROR: set MCPB_LINUX" && exit 1)
@echo "Packaging .mcpb for $(VERSION)..."
rm -rf $(DIST)/mcpb-staging
mkdir -p $(DIST)/mcpb-staging/server
lipo -create -output $(DIST)/mcpb-staging/server/kdmcp \
$(MCPB_DARWIN_ARM64) $(MCPB_DARWIN_AMD64)
cp $(MCPB_WINDOWS) $(DIST)/mcpb-staging/server/kdmcp.exe
cp $(MCPB_LINUX) $(DIST)/mcpb-staging/server/kdmcp-linux
chmod +x $(DIST)/mcpb-staging/server/kdmcp $(DIST)/mcpb-staging/server/kdmcp.exe \
$(DIST)/mcpb-staging/server/kdmcp-linux
sed 's/__VERSION__/$(VERSION)/' packaging/mcpb/manifest.json \
> $(DIST)/mcpb-staging/manifest.json
ifneq ($(CODESIGN_IDENTITY),)
codesign --force --options runtime --sign "$(CODESIGN_IDENTITY)" --timestamp \
$(DIST)/mcpb-staging/server/kdmcp
endif
cd $(DIST)/mcpb-staging && zip -qrD ../keibidrop-mcp.mcpb manifest.json server
rm -rf $(DIST)/mcpb-staging
@echo "Created $(DIST)/keibidrop-mcp.mcpb"
@shasum -a 256 $(DIST)/keibidrop-mcp.mcpb
# Serving-peer container image (docker/Dockerfile). Local single-arch build;
# the release workflow publishes the multi-arch image to GHCR on every tag.
IMAGE ?= ghcr.io/keibisoft/keibidrop
docker-image:
docker build -f docker/Dockerfile -t $(IMAGE):$(VERSION) -t $(IMAGE):latest \
--build-arg VERSION=$(VERSION) --build-arg COMMIT=$(COMMIT) .
# Chocolatey .nupkg — requires choco pack + package-windows first
# Choco requires semver without 'v' prefix (e.g. 0.1.1, not v0.1.1).
package-choco: $(DIST)
@echo "Packaging Chocolatey .nupkg ($(VERSION))..."
$(eval WIN_ZIP := $(DIST)/keibidrop-$(VERSION)-windows-$(GOARCH).zip)
$(eval SHA256 := $(shell shasum -a 256 $(WIN_ZIP) 2>/dev/null | cut -d' ' -f1))
@test -n "$(SHA256)" || (echo "ERROR: $(WIN_ZIP) not found — run 'make package-windows' first" && exit 1)
VERSION=$(VERSION) envsubst '$$VERSION' < choco/keibidrop.nuspec.tmpl > $(DIST)/keibidrop.nuspec
mkdir -p $(DIST)/tools
TAG=v$(VERSION) SEMVER=$(VERSION) SHA256=$(SHA256) envsubst '$$TAG$$SEMVER$$SHA256' < choco/tools/chocolateyinstall.ps1.tmpl > $(DIST)/tools/chocolateyinstall.ps1
cp choco/tools/chocolateyuninstall.ps1 $(DIST)/tools/
cd $(DIST) && choco pack keibidrop.nuspec || echo "choco pack failed"
@echo "Created .nupkg in $(DIST)/ (SHA256=$(SHA256))"
# Generate SHA256 checksums for all release artifacts
checksums: $(DIST)
cd $(DIST) && shasum -a 256 keibidrop-* > SHA256SUMS
@echo "Created $(DIST)/SHA256SUMS"
# Local choco install/uninstall test — validates the package before pushing.
# Requires: make package-choco first. Runs elevated (UAC prompt).
test-choco: package-choco
@echo "=== Testing Chocolatey package locally ==="
@echo "Installing keibidrop from local nupkg..."
powershell.exe -Command "Start-Process powershell.exe -Verb RunAs -Wait -ArgumentList \
'-NoProfile -Command \"choco install keibidrop -s C:\\Users\\milam\\Desktop\\code\\KeibiDrop\\dist -y --force 2>&1 | Tee-Object C:\\temp\\choco_test.log; \
Write-Host \\\"--- Verifying binaries ---\\\"; \
if (Get-Command keibidrop-cli.exe -ErrorAction SilentlyContinue) { keibidrop-cli.exe --version } else { Write-Host \\\"FAIL: keibidrop-cli.exe not in PATH\\\" }; \
Write-Host \\\"--- Uninstalling ---\\\"; \
choco uninstall keibidrop -y 2>&1 | Tee-Object -Append C:\\temp\\choco_test.log\"'"
@echo "=== Test log at C:\\temp\\choco_test.log ==="
@cat /c/temp/choco_test.log 2>/dev/null | tr -d '\0' || true
clean-dist:
rm -rf $(DIST)
# ── Mobile ────────────────────────────────────────────────
MOBILE_REPO ?= ../KeibiDropMobile
# Mobile: pin GOTOOLCHAIN to go.mod's Go (gomobile needs >= 1.24), and add x/mobile to
# go.mod transiently (restored after) so the committed go.mod stays in sync with origin.
MOBILE_GOTOOLCHAIN ?= go$(GO_MOD_VERSION)
MOBILE_PREP = cp go.mod go.mod.bak && cp go.sum go.sum.bak && trap '[ -f go.mod.bak ] && mv -f go.mod.bak go.mod; [ -f go.sum.bak ] && mv -f go.sum.bak go.sum; :' EXIT INT TERM && GOTOOLCHAIN=$(MOBILE_GOTOOLCHAIN) go get -tool golang.org/x/mobile/cmd/gobind@$(MOBILE_PKG_VERSION)
# Install gomobile + gobind (run once, or when 'gomobile version' says it's out of date).
# x/mobile has no semver tags, so @latest drifts; pin the pseudo-version instead.
MOBILE_PKG_VERSION := v0.0.0-20260803200217-62cee1672c8e
mobile-tools:
GOTOOLCHAIN=$(MOBILE_GOTOOLCHAIN) go install golang.org/x/mobile/cmd/gomobile@$(MOBILE_PKG_VERSION)
GOTOOLCHAIN=$(MOBILE_GOTOOLCHAIN) go install golang.org/x/mobile/cmd/gobind@$(MOBILE_PKG_VERSION)
build-ios:
@$(MOBILE_PREP) && \
GOTOOLCHAIN=$(MOBILE_GOTOOLCHAIN) GOFLAGS="-mod=mod" \
PATH="$$PATH:$$(go env GOPATH)/bin" \
gomobile bind -target=ios -o KeibiDrop.xcframework ./mobile
rm -rf ios/KeibiDrop/KeibiDrop.xcframework
cp -r KeibiDrop.xcframework ios/KeibiDrop/KeibiDrop.xcframework
# Auto-detect SDK/NDK; override by exporting ANDROID_HOME / ANDROID_NDK_HOME.
ifeq ($(strip $(ANDROID_HOME)),)
ANDROID_HOME := $(firstword $(wildcard $(HOME)/Android/Sdk $(HOME)/Library/Android/sdk /usr/local/share/android-commandlinetools /opt/android-sdk))
endif
ifeq ($(strip $(ANDROID_NDK_HOME)),)
ANDROID_NDK_HOME := $(lastword $(sort $(wildcard $(ANDROID_HOME)/ndk/*)))
endif
build-android:
@$(MOBILE_PREP) && \
ANDROID_HOME=$(ANDROID_HOME) ANDROID_NDK_HOME=$(ANDROID_NDK_HOME) \
GOTOOLCHAIN=$(MOBILE_GOTOOLCHAIN) GOFLAGS="-mod=mod" \
PATH="$$PATH:$$(go env GOPATH)/bin" \
gomobile bind -target=android -androidapi 28 -trimpath \
-ldflags "-s -w -X github.com/KeibiSoft/KeibiDrop/pkg/logic/common.Version=$(VERSION) -X github.com/KeibiSoft/KeibiDrop/pkg/logic/common.CommitHash=$(COMMIT) -extldflags '-Wl,-z,max-page-size=16384'" \
-o keibidrop.aar ./mobile
# Sync mobile app source + frameworks to the private KeibiDropMobile repo.
# Edit in KeibiDrop/ios and KeibiDrop/android, run this, commit in KeibiDropMobile.
sync-mobile:
@echo "Syncing to $(MOBILE_REPO)..."
rsync -av --delete --exclude='build/' --exclude='.DS_Store' ios/ $(MOBILE_REPO)/ios/
rsync -av --delete --exclude='build/' --exclude='.DS_Store' android/ $(MOBILE_REPO)/android/
@if [ -d KeibiDrop.xcframework ]; then \
rsync -av --delete KeibiDrop.xcframework/ $(MOBILE_REPO)/ios/KeibiDrop/KeibiDrop.xcframework/; \
fi
@if [ -f keibidrop.aar ]; then \
cp keibidrop.aar $(MOBILE_REPO)/keibidrop.aar; \
fi
@echo "Done. cd $(MOBILE_REPO) && git add -A && git commit"
SIM_ID ?= C415CC66-0845-4AA9-96CB-178CBC42A44F
# Build + run on iOS Simulator
run-ios-sim: build-ios
rm -rf ios/build
xcodebuild -project ios/KeibiDrop.xcodeproj -scheme KeibiDrop \
-sdk iphonesimulator -destination 'platform=iOS Simulator,id=$(SIM_ID)' \
-derivedDataPath ios/build build
xcrun simctl boot $(SIM_ID) 2>/dev/null || true
open -a Simulator
xcrun simctl install $(SIM_ID) ios/build/Build/Products/Debug-iphonesimulator/KeibiDrop.app
xcrun simctl launch $(SIM_ID) com.keibisoft.keibidrop
restart-ios:
xcrun simctl launch --terminate-running-process booted com.keibisoft.keibidrop
# Build + run on Android device/emulator (requires Android SDK + device connected)
run-android: build-android
cd android && JAVA_HOME="$(shell /usr/libexec/java_home -v 21 2>/dev/null || echo '/Applications/Android Studio.app/Contents/jbr/Contents/Home')" ./gradlew assembleDebug
adb install android/app/build/outputs/apk/debug/app-debug.apk
adb shell am start -n com.keibisoft.keibidrop/.MainActivity
restart-android:
adb shell am force-stop com.keibisoft.keibidrop
adb shell am start -n com.keibisoft.keibidrop/.MainActivity
clean: clean-dist
rm -f keibidrop-cli keibidrop-cli.exe kd kd.exe libkeibidrop.a libkeibidrop.h
rm -rf KeibiDrop.xcframework keibidrop.aar
# ── Run (dev) ─────────────────────────────────────────────
# Alice: ports 26001/26002 Bob: ports 26003/26004
# Relay: override with RELAY=http://localhost:54321 for local testing
RELAY ?= https://keibidroprelay.keibisoft.com/
BRIDGE ?= bridge.keibisoft.com:26600
SCRIPTS := scripts/dev
# On Windows, WinFSP requires drive letters for FUSE mount points.
# On Linux/macOS a subdirectory is fine.
ifeq ($(GOOS),windows)
ALICE_MOUNT ?= K:
BOB_MOUNT ?= L:
else
ALICE_MOUNT ?= MountAlice
BOB_MOUNT ?= MountBob
endif
# Rust UI (FUSE toggle is in the UI, no need for NO_FUSE env)
run-alice:
KEIBIDROP_CONFIG_DIR=$(HOME)/.config/keibidrop-alice TO_MOUNT_PATH=$(ALICE_MOUNT) KEIBIDROP_RELAY=$(RELAY) BRIDGE_ADDR=$(BRIDGE) INBOUND_PORT=26001 OUTBOUND_PORT=26002 bash $(SCRIPTS)/example_run_rust_ui_nofuse.sh
run-bob:
KEIBIDROP_CONFIG_DIR=$(HOME)/.config/keibidrop-bob TO_MOUNT_PATH=$(BOB_MOUNT) KEIBIDROP_RELAY=$(RELAY) BRIDGE_ADDR=$(BRIDGE) INBOUND_PORT=26003 OUTBOUND_PORT=26004 bash $(SCRIPTS)/example_run_rust_ui.sh
# Go CLI
run-cli-alice:
KEIBIDROP_CONFIG_DIR=$(HOME)/.config/keibidrop-alice KEIBIDROP_RELAY=$(RELAY) INBOUND_PORT=26001 OUTBOUND_PORT=26002 bash $(SCRIPTS)/example_run_cli.sh
run-cli-bob:
KEIBIDROP_CONFIG_DIR=$(HOME)/.config/keibidrop-bob KEIBIDROP_RELAY=$(RELAY) INBOUND_PORT=26003 OUTBOUND_PORT=26004 bash $(SCRIPTS)/example_run_peer_cli.sh
# kd daemon (agent, always no-FUSE)
run-kd-alice:
KD_NO_FUSE=1 KD_RELAY=$(RELAY) KD_INBOUND_PORT=26001 KD_OUTBOUND_PORT=26002 bash $(SCRIPTS)/example_run_kd_alice.sh
run-kd-bob:
KD_NO_FUSE=1 KD_RELAY=$(RELAY) KD_INBOUND_PORT=26003 KD_OUTBOUND_PORT=26004 bash $(SCRIPTS)/example_run_kd_bob.sh
# ── Bridge mode (for peers behind firewalls / NAT) ───────
# Both peers connect outbound to the bridge relay. No inbound ports needed.
# Default bridge: bridge.keibisoft.com:26600 (Timisoara)
# Override: make run-bridge-alice BRIDGE=your-server:26600
run-bridge-alice: build-kd
KD_RELAY=https://keibidroprelay.keibisoft.com/ KD_BRIDGE=$(BRIDGE) \
KD_NO_FUSE=1 KD_SAVE_PATH=SaveAlice KD_SOCKET=/tmp/kd-alice.sock \
./kd start
run-bridge-bob: build-kd
KD_RELAY=https://keibidroprelay.keibisoft.com/ KD_BRIDGE=$(BRIDGE) \
KD_NO_FUSE=1 KD_SAVE_PATH=SaveBob KD_SOCKET=/tmp/kd-bob.sock \
./kd start
run-bridge-alice-fuse: build-kd
KD_RELAY=https://keibidroprelay.keibisoft.com/ KD_BRIDGE=$(BRIDGE) \
KD_SAVE_PATH=SaveAlice KD_MOUNT_PATH=MountAlice KD_SOCKET=/tmp/kd-alice.sock \
./kd start
run-bridge-bob-fuse: build-kd
KD_RELAY=https://keibidroprelay.keibisoft.com/ KD_BRIDGE=$(BRIDGE) \
KD_SAVE_PATH=SaveBob KD_MOUNT_PATH=MountBob KD_SOCKET=/tmp/kd-bob.sock \
./kd start
# ── Help ──────────────────────────────────────────────────
help:
@echo "Build:"
@echo " make build-cli Build interactive CLI"
@echo " make build-kd Build agent daemon"
@echo " make build-rust Build Rust/Slint UI (includes protoc + Go static lib)"
@echo " make build-all Build everything"
@echo ""
@echo "Run (dev): Alice=26001/26002 Bob=26003/26004"
@echo " make run-alice Rust UI, Alice (FUSE toggle in UI)"
@echo " make run-bob Rust UI, Bob (FUSE toggle in UI)"
@echo " make run-cli-alice Go CLI, Alice"
@echo " make run-cli-bob Go CLI, Bob"
@echo " make run-kd-alice kd daemon, Alice (local/direct)"
@echo " make run-kd-bob kd daemon, Bob (local/direct)"
@echo " make run-bridge-alice kd via bridge relay, Alice (no-FUSE)"
@echo " make run-bridge-bob kd via bridge relay, Bob (no-FUSE)"
@echo " make run-bridge-alice-fuse kd via bridge relay, Alice (FUSE)"
@echo " make run-bridge-bob-fuse kd via bridge relay, Bob (FUSE)"
@echo ""
@echo "Test & Lint:"
@echo " make test Run all integration tests"
@echo " make lint Run golangci-lint"
@echo " make sec Run gosec security scanner"
@echo ""
@echo "Packaging:"
@echo " make package-macos .dmg for macOS"
@echo " make package-tar .tar.gz archive"
@echo " make package-deb .deb package (needs nfpm)"
@echo " make package-windows .zip for Windows"
@echo " make package-choco Chocolatey .nupkg"
@echo " make checksums SHA256SUMS for dist/"
@echo ""
@echo "Mobile:"
@echo " make mobile-tools Install gomobile + gobind (once)"
@echo " make build-ios Build iOS framework (.xcframework)"
@echo " make build-android Build Android library (.aar)"
@echo " make run-ios-sim Build + run on iOS Simulator"
@echo " make run-android-emu Build + run on Android emulator"
@echo " make sync-mobile Sync ios/ android/ to KeibiDropMobile repo"
@echo ""
@echo "Other:"
@echo " make protoc Regenerate gRPC stubs"
@echo " make rust-bindings Regenerate Rust FFI bindings"
@echo " make clean Remove build artifacts"
# ── WAN Testing (Mac <-> VPS) ─────────────────────────────────────────────────
wan-deploy: build-kd
bash scripts/wan/deploy.sh
wan-clean:
bash scripts/wan/clean.sh
wan-start:
bash scripts/wan/start.sh
wan-benchmark:
bash scripts/wan/benchmark.sh
wan-test: wan-clean wan-start wan-benchmark
# ── Android Dev Helpers ───────────────────────────────────────────────
# Push text from Mac clipboard to Android device clipboard + paste into focused field.
# Usage: make android-push-clip FP=<fingerprint>
# Tap peer code field on Android first, then run this.
android-push-clip:
@if [ -z "$(FP)" ]; then echo "Usage: make android-push-clip FP=<fingerprint>"; exit 1; fi
adb shell input text '$(FP)'
# Pull fingerprint from Android screen to Mac clipboard.
# Works by dumping the UI tree and finding the fingerprint-length text.
android-pull-clip:
@adb shell uiautomator dump /sdcard/ui.xml >/dev/null 2>&1; \
adb pull /sdcard/ui.xml /tmp/_kd_ui.xml >/dev/null 2>&1; \
FP=$$(grep -o 'text="[^"]*"' /tmp/_kd_ui.xml | grep -E '[A-Za-z0-9_-]{60,}' | tail -1 | sed 's/text="//;s/"//'); \
if [ -z "$$FP" ]; then echo "No fingerprint found on screen. Make sure the app is open."; exit 1; fi; \
echo "$$FP" | tr -d '\n' | pbcopy; \
echo "Pulled: $$FP"
# Deploy latest AAR + APK to connected Android device.
android-deploy: build-android
cp keibidrop.aar ../KeibiDropMobile/keibidrop.aar
JAVA_HOME=/usr/local/opt/openjdk@21/libexec/openjdk.jdk/Contents/Home \
cd ../KeibiDropMobile/android && ./gradlew assembleDebug
adb install -r ../KeibiDropMobile/android/app/build/outputs/apk/debug/app-debug.apk
adb shell am force-stop com.keibisoft.keibidrop
adb shell am start -n com.keibisoft.keibidrop/.MainActivity
.PHONY: build-cli build-kd build-kdmcp build-static-rust-bridge build-rust build-rust-windows build-all \
test test-race lint sec install-proto protoc rust-bindings slint-preview \
package-macos package-tar package-deb package-windows package-choco package-mcpb \
checksums clean-dist clean \
run-alice run-bob \
run-cli-alice run-cli-bob \
run-kd-alice run-kd-bob \
run-bridge-alice run-bridge-bob run-bridge-alice-fuse run-bridge-bob-fuse \
mobile-tools build-ios build-android run-ios-sim run-android-emu sync-mobile \
wan-deploy wan-clean wan-start wan-benchmark wan-test help \
android-push-clip android-pull-clip android-deploy