.dockerignore 排除 .git/,容器内 build.rs 跑不了 git 命令,导致 x-yggdrasil-git / git_hash / commit_date 响应头和启动日志全是 "unknown" (version 来自 CARGO_PKG_VERSION 不受影响)。 三级取值链(build.rs env_or_git): YGG_BUILD_* 环境变量 → 本地 git 命令 → "unknown" 第一级 std::env::var 优先读 docker --build-arg 注入的值,第二级保留 本地 cargo build 的既有行为,兜底不变。 - Dockerfile: 主应用 server build 前加 ARG+ENV 块(ARG 仅 RUN 可见, build.rs 由 cargo 调用非 RUN,故需 export 成 ENV 让 cargo build 继承) - Makefile: GIT_DESCRIBE/HASH/DATE 在宿主采集,GIT_BUILD_ARGS 复用块 注入 docker/docker-amd64/docker-multiarch 三个 target - deploy-to-linux skill: 两处 docker buildx build 命令(首装 + 更新) 加同名 --build-arg,附说明
225 lines
11 KiB
Makefile
225 lines
11 KiB
Makefile
.PHONY: dev build build-linux build-freebsd freebsd-sysroot docker docker-amd64 docker-apple docker-multiarch css css-watch clean build-libs build-editor build-codemirror build-lightbox build-core build-xterm highlight-css katex-css test doc doc-open start lint fix restore-webp
|
||
|
||
build:
|
||
@rm -rf static/
|
||
@cd libs && pnpm install --frozen-lockfile
|
||
@$(MAKE) build-libs
|
||
@$(MAKE) highlight-css
|
||
@$(MAKE) katex-css
|
||
@tailwindcss -i input.css -o public/style.css --minify
|
||
@$(MAKE) doc
|
||
@dx build --release --debug-symbols=false
|
||
@$(MAKE) restore-webp
|
||
|
||
build-linux:
|
||
@cd libs && pnpm install --frozen-lockfile
|
||
@$(MAKE) build-libs
|
||
@$(MAKE) highlight-css
|
||
@$(MAKE) katex-css
|
||
@tailwindcss -i input.css -o public/style.css --minify
|
||
@dx build @client --release --debug-symbols=false --wasm-js-cfg false
|
||
@dx build @server --release --debug-symbols=false --target x86_64-unknown-linux-musl --wasm-js-cfg false --features server
|
||
@$(MAKE) restore-webp
|
||
@echo ""
|
||
@echo "Linux build complete! The server binary is at target/dx/yggdrasil/release/web/server"
|
||
@echo "Remember to deploy it alongside the target/dx/yggdrasil/release/web/public directory."
|
||
@echo "When running the server, ensure DIOXUS_ASSET_DIR is set or the public directory is in CWD."
|
||
|
||
# FreeBSD 15.1 base.txz 版本与下载源。sysroot 仅需 ./lib 与 ./usr/lib(crt 对象 + 系统库)。
|
||
FREEBSD_VERSION ?= 15.1-RELEASE
|
||
FREEBSD_BASE_URL ?= https://download.freebsd.org/ftp/releases/amd64/amd64/$(FREEBSD_VERSION)/base.txz
|
||
FREEBSD_SYSROOT := $(CURDIR)/.freebsd-sysroot
|
||
|
||
# 下载并解压 FreeBSD base.txz 到 .freebsd-sysroot/,供交叉链接(crt 对象 + 系统库)。
|
||
# 幂等:若 sysroot 已存在则跳过下载。
|
||
freebsd-sysroot:
|
||
@if [ -d "$(FREEBSD_SYSROOT)/usr/lib" ] && [ -d "$(FREEBSD_SYSROOT)/lib" ]; then \
|
||
echo "FreeBSD sysroot already present at $(FREEBSD_SYSROOT)"; \
|
||
else \
|
||
echo "Downloading FreeBSD $(FREEBSD_VERSION) base.txz..."; \
|
||
curl -fL --retry 3 -o /tmp/freebsd-base.txz "$(FREEBSD_BASE_URL)"; \
|
||
mkdir -p "$(FREEBSD_SYSROOT)"; \
|
||
echo "Extracting crt objects and system libs..."; \
|
||
tar -xf /tmp/freebsd-base.txz -C "$(FREEBSD_SYSROOT)" ./lib ./usr/lib; \
|
||
rm -f /tmp/freebsd-base.txz; \
|
||
echo "FreeBSD sysroot ready at $(FREEBSD_SYSROOT)"; \
|
||
fi
|
||
|
||
# 交叉编译 FreeBSD x86_64 release server 二进制。
|
||
# 前置:clang + lld 已装(pacman -S clang lld)、rustup target add x86_64-unknown-freebsd、
|
||
# `make freebsd-sysroot`。sysroot 路径经 CARGO_TARGET_*_RUSTFLAGS 注入,避免在
|
||
# .cargo/config.toml 里硬编码机器相关路径。server 二进制用 cargo 直出(dx CLI 对该
|
||
# target 未经验证);前端 wasm 与静态资源与 build-linux 相同,不在此重复构建。
|
||
build-freebsd:
|
||
@$(MAKE) freebsd-sysroot
|
||
@SYSROOT="$(FREEBSD_SYSROOT)"; \
|
||
RUSTFLAGS_FREEBSD="-C linker=clang -C link-arg=--target=x86_64-unknown-freebsd -C link-arg=-fuse-ld=lld -C link-arg=--sysroot=$$SYSROOT -C link-arg=-L$$SYSROOT/usr/lib -C link-arg=-L$$SYSROOT/lib"; \
|
||
echo "Cross-compiling yggdrasil server for FreeBSD x86_64..."; \
|
||
CARGO_TARGET_X86_64_UNKNOWN_FREEBSD_RUSTFLAGS="$$RUSTFLAGS_FREEBSD" \
|
||
cargo build --release --target x86_64-unknown-freebsd --features server --bin yggdrasil
|
||
@echo ""
|
||
@echo "FreeBSD build complete! Server binary: target/x86_64-unknown-freebsd/release/yggdrasil"
|
||
@echo "Deploy it to FreeBSD 15+ alongside the static public/ directory."
|
||
@echo "Runtime needs (bundled in FreeBSD base): libc.so.7 libthr.so.3 libkvm.so.7 etc."
|
||
|
||
# 兜底:dx build 0.7.9 会把 public/ 下的 .webp 重编码成 VP8L 无损静图
|
||
# (动画帧被丢弃,静图体积反增 7-8 倍),与文档承诺的"原样拷贝"不符。
|
||
# SVG/ICO 等其他格式不受影响,故只需覆盖 .webp。
|
||
# 遍历所有 dx 产物目录(release/debug),用源 public/ 的同名文件覆盖回去。
|
||
# 仅覆盖产物中已存在的 .webp,不引入源里新增但 dx 未生成的文件。
|
||
# 参考:https://dioxuslabs.com/learn/0.7/essentials/ui/assets/
|
||
# 上游修复后可移除此 target 及 build/build-linux 里的调用。
|
||
restore-webp:
|
||
@find target/dx -type d -path "*/web/public" 2>/dev/null | while read prod; do \
|
||
find "$$prod" -type f -name "*.webp" 2>/dev/null | while read p; do \
|
||
rel=$${p#$$prod/}; \
|
||
src="public/$$rel"; \
|
||
if [ -f "$$src" ]; then \
|
||
cp "$$src" "$$p"; \
|
||
else \
|
||
echo "restore-webp: 源缺失,跳过 $$rel"; \
|
||
fi; \
|
||
done; \
|
||
done
|
||
|
||
highlight-css:
|
||
@cargo run --bin generate_highlight_css
|
||
|
||
# 把 npm 包 katex 的 dist/ 拷贝到 public/katex/(服务端 katex-rs 不打包 CSS)。
|
||
# KaTeX 的 katex.min.css 用相对 URL 引 fonts/,故 fonts/ 必须与 CSS 同级。
|
||
# 只拷 woff2(现代浏览器全支持,省去 woff/ttf ~70% 字体体积)。
|
||
# katex 作为 libs/ workspace 根 devDependency,pnpm install 后在 libs/node_modules/katex/。
|
||
katex-css:
|
||
@echo "Copying KaTeX CSS + woff2 fonts to public/katex/..."
|
||
@mkdir -p public/katex/fonts
|
||
@cp libs/node_modules/katex/dist/katex.min.css public/katex/katex.min.css
|
||
@cp libs/node_modules/katex/dist/fonts/*.woff2 public/katex/fonts/
|
||
@echo "KaTeX CSS ready at public/katex/"
|
||
|
||
# 并行构建全部 libs/ 子项目(pnpm -r 拓扑顺序,无相互依赖则并发)。
|
||
# 依赖安装由调用方负责(build/build-linux 用 pnpm install --frozen-lockfile,
|
||
# dev 假设 node_modules 已存在)。
|
||
build-libs:
|
||
@cd libs && pnpm -r run build
|
||
|
||
# 单库便利 target(替代旧的 build-<name>,用 pnpm --filter 精确定位)。
|
||
build-editor: ; @cd libs && pnpm --filter @yggdrasil/tiptap-editor run build
|
||
build-codemirror: ; @cd libs && pnpm --filter @yggdrasil/codemirror-editor run build
|
||
build-lightbox: ; @cd libs && pnpm --filter @yggdrasil/lightbox run build
|
||
build-core: ; @cd libs && pnpm --filter @yggdrasil/core run build
|
||
build-xterm: ; @cd libs && pnpm --filter @yggdrasil/xterm-terminal run build
|
||
build-mermaid: ; @cd libs && pnpm --filter @yggdrasil/mermaid-renderer run build
|
||
|
||
dev: build-libs highlight-css katex-css
|
||
@echo "Cleaning static/..."
|
||
@rm -rf static/
|
||
@echo "Building CSS..."
|
||
@$(MAKE) css
|
||
@echo "Starting dx serve..."
|
||
@SSR_CACHE_SECS=0 dx serve --addr 0.0.0.0
|
||
|
||
css:
|
||
@tailwindcss -i input.css -o public/style.css
|
||
|
||
css-watch:
|
||
@tailwindcss -i input.css -o public/style.css --watch
|
||
|
||
test:
|
||
@cargo test
|
||
@cd libs && pnpm -r run test
|
||
|
||
# JS + Rust 一次性检查(不改动文件)。
|
||
lint:
|
||
@echo "==> Biome check (libs)"
|
||
@cd libs && pnpm exec biome check . && pnpm typecheck
|
||
@echo "==> Cargo clippy (Rust)"
|
||
@cargo clippy --all-targets --all-features -- -D warnings
|
||
|
||
# JS + Rust 自动修复(直接写入文件)。
|
||
# 顺序:Biome → cargo fix(应用编译器建议,重写代码)→ cargo fmt(格式化 Rust)
|
||
# → dx fmt(格式化 RSX 宏)。两道格式化收尾,保证最终文件状态整洁。
|
||
fix:
|
||
@echo "==> Biome format (libs, 写入文件)"
|
||
@cd libs && pnpm exec biome format --write .
|
||
@echo "==> Cargo fix (Rust, 应用编译器建议)"
|
||
@cargo fix --allow-dirty
|
||
@echo "==> Cargo fmt (Rust, 格式化)"
|
||
@cargo fmt
|
||
@echo "==> Dioxus fmt (RSX 宏, 格式化)"
|
||
@dx fmt
|
||
|
||
# 只编译当前 crate 的文档(--no-deps 跳过依赖,--document-private-items
|
||
# 让纯 binary crate 的内部模块/私有项也进文档,否则页面基本是空的)。
|
||
# RUSTDOCFLAGS 把 rustdoc 的 --default-theme=ayu 透传过去——cargo doc 本身
|
||
# 无主题参数,但会把该环境变量转交给底层 rustdoc。注意它是默认值,浏览器
|
||
# 若已记住上次的主题选择(localStorage)则不会被覆盖。
|
||
#
|
||
# 生成后拷贝到 public/doc/,让文档随 Dioxus 静态目录发布。先清空旧目录再
|
||
# 整体拷贝,避免删除模块后残留旧文件。rustdoc 内部用相对路径引用资源
|
||
# (如 ../../static.files/),原样挂载不会断链。
|
||
#
|
||
# 额外生成 public/doc/index.html 重定向页:Dioxus 在 dev 用
|
||
# nest_service("/doc", ServeDir) 托管该目录,ServeDir 访问目录根时默认
|
||
# 返回 index.html。用 meta refresh + JS 跳转到真正的文档入口
|
||
# yggdrasil/index.html,这样裸路径 /doc 也能直达文档,且不与 Dioxus 的
|
||
# /doc/* 路由冲突(手动注册 /doc 会在 merge 时 panic)。
|
||
doc:
|
||
@RUSTDOCFLAGS="--default-theme=ayu" cargo doc --no-deps --document-private-items
|
||
@rm -rf public/doc
|
||
@cp -r target/doc public/doc
|
||
@printf '<!DOCTYPE html><html><head><meta charset="utf-8"><meta http-equiv="refresh" content="0;url=yggdrasil/index.html"><title>Redirecting…</title></head><body><script>location.replace("yggdrasil/index.html")</script></body></html>' > public/doc/index.html
|
||
|
||
# 同 doc,生成完自动用浏览器打开。
|
||
doc-open:
|
||
@RUSTDOCFLAGS="--default-theme=ayu" cargo doc --no-deps --document-private-items --open
|
||
|
||
# Multi-arch image build via buildx. The Dockerfile builds each platform leg
|
||
# natively (amd64→x86_64 musl, arm64→aarch64 musl), so no cross-compiler or
|
||
# QEMU is needed. Docker Desktop ships a buildx builder that handles this.
|
||
#
|
||
# make docker native arch only, load into local daemon (for testing)
|
||
# make docker-amd64 x86_64 only, load into local daemon (buildx + QEMU on Apple Silicon)
|
||
# make docker-apple x86_64 only, via Apple Container CLI (macOS 26+, Apple Silicon native; no Docker needed)
|
||
# make docker-multiarch build amd64+arm64 and push to a registry
|
||
# (multi-arch manifests can't be --load-ed locally)
|
||
#
|
||
# Push examples:
|
||
# make docker-multiarch IMAGE=ghcr.io/owner/yggdrasil:latest
|
||
# make docker-multiarch IMAGE=user/yggdrasil:v1 PLATFORMS=linux/amd64
|
||
#
|
||
# git 信息透传:.dockerignore 排除 .git/,容器内 build.rs 跑不了 git 命令,
|
||
# 所以在宿主(本 Makefile 里)采集后用 --build-arg 注入。Dockerfile 把 ARG
|
||
# 再 export 成 ENV,build.rs 的 std::env::var 优先读它。三个值在 Make 变量
|
||
# 里采集一次,所有 docker target 复用;git 不可用时退化为空串,Dockerfile
|
||
# 默认值也是空,build.rs 最终降级为 "unknown",不阻断构建。
|
||
IMAGE ?= yggdrasil
|
||
PLATFORMS ?= linux/amd64,linux/arm64
|
||
GIT_DESCRIBE := $(shell git describe --tags --always --dirty 2>/dev/null)
|
||
GIT_HASH := $(shell git rev-parse HEAD 2>/dev/null)
|
||
GIT_DATE := $(shell git log -1 --format=%cd --date=iso-strict 2>/dev/null)
|
||
# build-arg 复用块:每个 docker target 展开一次。空值也传(让 Dockerfile 默认接管)。
|
||
GIT_BUILD_ARGS = --build-arg YGG_BUILD_GIT_DESCRIBE="$(GIT_DESCRIBE)" \
|
||
--build-arg YGG_BUILD_GIT_HASH="$(GIT_HASH)" \
|
||
--build-arg YGG_BUILD_GIT_COMMIT_DATE="$(GIT_DATE)"
|
||
docker:
|
||
@docker buildx build --load $(GIT_BUILD_ARGS) -t yggdrasil .
|
||
|
||
# Cross-build x86_64 into the local daemon. buildx 仿真非原生架构,无需修改 Dockerfile
|
||
# (它本就按 dpkg --print-architecture 自适应选 musl target)。Apple Silicon 上走 QEMU,
|
||
# 比 native 慢;产物可直接 docker run / docker save 导出。
|
||
docker-amd64:
|
||
@docker buildx build --platform linux/amd64 --load $(GIT_BUILD_ARGS) -t yggdrasil:amd64 .
|
||
|
||
docker-multiarch:
|
||
@docker buildx build --platform $(PLATFORMS) $(GIT_BUILD_ARGS) -t $(IMAGE) --push .
|
||
|
||
clean:
|
||
@cargo clean
|
||
@rm -f public/style.css public/highlight.css
|
||
@rm -rf public/katex
|
||
@rm -rf public/mermaid
|
||
@rm -rf public/doc
|
||
@rm -rf static/
|
||
@rm -rf uploads/.cache
|
||
@rm -rf libs/node_modules libs/*/node_modules
|