首页
/ Gitea 源码构建完全指南:Make 任务、Build Tags、LDFLAGS 路径定制与交叉编译

Gitea 源码构建完全指南:Make 任务、Build Tags、LDFLAGS 路径定制与交叉编译

2026-09-05 14:45:35作者:尤峻淳Whitney

本文基于 Gitea 仓库的官方构建文档 docs/build-source.md 展开,系统讲解从源码编译 Gitea 的完整流程:如何选择分支与测试 Pull Request、如何使用 make 任务与 bindata/pam/gogit 等构建标签、如何通过 LDFLAGS 在编译期固化 CustomConf/AppWorkPath/CustomPath 等默认路径、如何借助 Go 工具链变量做交叉编译,以及如何用 ENABLE_SOURCEMAP 控制前端 Source Map 的生成粒度。读完本文,你可以独立完成生产级二进制的编译、打包器路径定制和跨平台产物构建,并能理解每一步背后的源码实现依据。

前置环境准备

在开始构建之前,需要先按照 docs/build-setup.md 准备好工具链。该文档列出的核心依赖包括:

  • Go:版本以 go.mod 中声明的为准;使用与 CI 相同的 Go 版本可以避免不同 Go 发行版之间的 gofmt 差异。
  • Node.js 与 pnpm:用于构建 JavaScript 和 CSS,最低支持版本以 package.jsonengines.node 声明的为准,推荐最新 LTS。Gitea 用 pnpm 管理前端依赖,make 目标会自动调用它。
  • Make:驱动构建、Lint 与测试;Windows 上可通过 MSYS2 或 Chocolatey 安装。
  • Python + uv(可选):仅在本地运行 make lint-templatesmake lint-yamlmake lint-actions 时需要,安装 uv 后 make 会自动创建环境(uv sync)。
  • Git LFS:集成测试需要。

克隆仓库后,大多数构建/测试目标会自行拉取所需依赖;若想一次性预取,可运行 make deps(或按分组的 make deps-frontendmake deps-backendmake deps-toolsmake deps-py)。

选择构建分支与测试 Pull Request

克隆下来的仓库默认停留在 main 分支,它是下一个大版本的开发分支(即 main nightly)。按需求可以选择不同的构建来源:

  • 版本化分支(versioned branch):下一个小版本稳定版的分支,即 stable nightly;
  • 版本化 tag:与官方发布的版本号一一对应。

如果要验证某个 Pull Request 的代码,可以按 PR 编号直接 fetch 它(以 PR #123456 为例):

git fetch origin pull/123456/head:pr-123456

然后将构建切换到该本地分支 pr-123456 即可。这一方式不需要在 fork 中合并 PR 目标分支,是验证上游 PR 构建行为的常用手段。

构建流程:make 任务与构建标签

Gitea 提供了一系列 make 任务 来简化构建过程。最常用的是 make build,从 Makefile 可以看到它的内部编排:

build: frontend backend ## build everything

frontend: $(FRONTEND_DEST) ## build frontend files

backend: generate-backend $(EXECUTABLE) ## build backend files

build 会先构建前端(产物目标为 public/assets/.vite/manifest.json),再构建后端二进制;backend 目标还会先执行 generate-backend 运行 go generate。最终的可执行文件由如下的 go build 命令产出(见 Makefile):

$(EXECUTABLE): $(GO_SOURCES) $(TAGS_PREREQ)
	CGO_ENABLED="$(CGO_ENABLED)" CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build -v $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o $@

这条命令揭示了构建的三个关键控制点:

  1. -tags '$(TAGS)':编译标签,决定功能开关;
  2. -ldflags '-s -w $(LDFLAGS)':链接期注入版本与默认路径等变量,-s -w 用于剥离符号表与 DWARF 调试信息以减小体积;
  3. CGO_ENABLED/CGO_CFLAGS:控制 CGO 参与程度,交叉编译时尤其重要(下文详述)。

此外,Makefile 还会自动向 LDFLAGS 追加版本信息(见 Makefile):

LDFLAGS := $(LDFLAGS) -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"

版本号优先取自 store-version 文件,否则由 git describe --tags --always 推导;构建 main 分支时版本号会被标记为 main-nightly

可用的构建标签(TAGS)

根据需求,可在 TAGS 中加入以下构建标签:

  • bindata:将所有前端资源、模板、选项文件等打包进单个单体二进制(monolithic binary)。这是发行版与生产构建的必备标签,产物不依赖外部资产目录即可运行。
  • pam:启用对 PAM(Linux Pluggable Authentication Modules)的支持,可用于认证系统本地用户或扩展到 PAM 提供的其他认证方式。
  • gogit:(EXPERIMENTAL)实验性地改用 go-git 实现来执行 Git 命令,主要用于缓解某些 Windows 平台上的性能问题,POSIX 系统无需开启。

包含全部资产的标准构建命令为:

TAGS="bindata" make build

构建 Windows 二进制时(开启 gogit 以缓解 Windows 特有的性能问题):

GOOS=windows TAGS="bindata gogit" make build

通过 LDFLAGS 修改默认路径

Gitea 在运行时会从若干“基准位置”查找资源,这些位置由三个变量控制:

  • CustomPath:默认取当前工作目录下的 custom/ 目录,存放自定义模板、覆盖资源等;
  • CustomConf:配置文件路径,默认为 $(CustomPath)/conf/app.ini
  • AppWorkPath:以当前工作目录作为相对路径的基准(仓库默认存储位置等相对于此解析)。

这三个值对开发者很友好,但可能与下游发行版(packager)的路径偏好冲突。对于需要使用 /etc/gitea/app.ini 这类系统路径的打包者,应在构建期通过环境变量 LDFLAGS-X 注入这些值,例如:

LDFLAGS='-X "module.Var1=Value1" -X "module.Var2=Value2"' TAGS="bindata" make build

官方文档给出的具体注入项(变量名以文档为准,其中模块路径前缀为 gitea.dev/modules/...):

变量 LDFLAGS 注入项 作用
CustomConf -X "gitea.dev/modules/setting.CustomConf=/etc/gitea/app.ini" 配置文件默认路径
AppWorkPath -X "gitea.dev/modules/setting.AppWorkPath=/var/lib/gitea" 工作目录基准(仓库数据根)
CustomPath -X "gitea.dev/modules/setting.CustomPath=/var/lib/gitea/custom" 自定义资源目录
默认 PID 文件位置 -X "gitea.dev/cmd.PIDFile=/run/gitea.pid" web 服务写 PID 文件的位置

这些 -X 字符串可以任意组合追加到 LDFLAGS 变量中,再像上文一样带 TAGS 执行 make build

从源码结构看,这些变量是普通的 Go 包级变量,Go 链接器在 -X 注入时会在编译期完成赋值:

  • PIDFile 定义于 cmd/web.go,并带有 // PIDFile could be set from build tag 注释,正是为构建期覆盖而设计;
  • AppWorkPathCustomPathCustomConf 属于 modules/setting 包,在 modules/setting/path.go 中被解析与回填;当 AppWorkPath 未被注入时,代码回退为可执行文件所在目录(modules/setting/path.goAppWorkPath = filepath.Dir(AppPath)),这解释了为什么开发态“当前工作目录”约定能够生效。

构建完成后,运行 gitea help 可以查看你的二进制实际计算出的这些默认值,是验证 LDFLAGS 注入是否生效的便捷手段。

交叉编译(Cross Build)

Gitea 直接复用 Go 工具链的 GOOS/GOARCH 环境变量做交叉构建。例如构建 Linux ARM64 产物:

GOOS=linux GOARCH=arm64 TAGS="bindata" make build

需要留意 Makefile 中的一条注释:release 系列目标“始终使用 Go 的原生交叉编译”,即默认纯 Go 交叉编译;若需要在交叉编译中启用 CGO,应改用 build 目标并正确设置 TAGS/LDFLAGS/CGO_CFLAGS,让 $(EXECUTABLE) 规则去执行 go build。这也意味着:

  • 纯静态、无 CGO 依赖的场景(如仅 bindata 标签、CGO_ENABLED=0)可直接交叉编译;
  • 涉及 CGO(如 sqlite 驱动、PAM 等)时,目标平台的 C 工具链是否可用会直接影响能否完成编译,交叉编译时应谨慎选择标签组合。

发布用的批量交叉构建由 tools/build-release.sh 驱动,make release 会依次完成 frontendrelease-binaries(调用 build-release.sh 产出各平台二进制)、release-copyrelease-compressrelease-sources 等步骤(见 Makefile)。

Shell 自动补全

补全脚本可以直接从构建出的二进制生成:

gitea completion <shell>

<shell> 支持 bashfishpwshzsh 四个取值。具体的加载方式(例如写入 ~/.bashrc 还是 zsh 的 fpath)参见 completion 命令自身的帮助输出。

前端 Source Map 控制

Gitea 前端默认生成“精简版”(reduced)Source Map 以节省空间,该行为由 ENABLE_SOURCEMAP 环境变量控制:

  • ENABLE_SOURCEMAP=true:生成全部 Source Map,开发构建的默认值
  • ENABLE_SOURCEMAP=reduced:生成受限 Source Map,生产构建的默认值
  • ENABLE_SOURCEMAP=false:完全不生成 Source Map。

vite.config.ts 可以确认这一判定逻辑:

// ENABLE_SOURCEMAP accepts the following values:
// true - all sourcemaps enabled, the default in development
// reduced - sourcemaps only for index.js, the default in production
// false - all sourcemaps disabled
let enableSourcemap: string;
if ('ENABLE_SOURCEMAP' in env) {
  enableSourcemap = ['true', 'false'].includes(env.ENABLE_SOURCEMAP!) ? env.ENABLE_SOURCEMAP! : 'reduced';
} else {
  enableSourcemap = isProduction ? 'reduced' : 'true';
}

即:显式设置了 ENABLE_SOURCEMAP 时,只有 true/false 被原样采纳,其余取值(包括 reduced)统一按 reduced 处理;未设置时,按 NODE_ENV 区分开发与生产,分别取 truereduced

reduced 模式的具体行为由 vite.config.ts 中的 reducedSourcemapPlugin 插件实现:构建完成后(closeBundle 钩子)扫描输出目录中的 {js,css}/*.map,只保留以下前缀的入口文件对应 map,其余全部删除:

js/index.*          js/iife.*
js/swagger.*        js/external-render-frontend.*
js/external-render-helper.*
js/user-events.sharedworker.*

也就是说,reduced 模式并非“只有一个 map”,而是保留主入口与少数独立运行(IIFE、worker 等)入口的 Source Map,删除按 hash 拆分的懒加载 chunk 的 map,从而在调试能力与发布体积之间取得平衡。另外,vite.config.tssourcemap: enableSourcemap !== 'false' 表明:只要不是 false,打包阶段都会先生成完整 map,reduced 是后处理裁剪的结果。

小结

  • 环境依赖与取码流程见 docs/build-setup.md,本文聚焦其后的构建环节;
  • 分支策略:main(main nightly)→ 版本化分支(stable nightly)→ 版本化 tag,PR 验证用 git fetch origin pull/<编号>/head
  • 生产/发行构建的核心命令是 TAGS="bindata" make build,Windows 产物追加 gogit 标签并设置 GOOS=windows
  • 打包器定制路径通过 LDFLAGS-X 注入 CustomConf/AppWorkPath/CustomPath/PIDFile,用 gitea help 复核;
  • 交叉编译复用 GOOS/GOARCH,CGO 场景注意 Makefile 中 releasebuild 目标的差异;
  • Source Map 三档(true/reduced/false)分别对应开发全量、生产精简(仅保留主入口 map)、完全关闭,其裁剪逻辑可直接在 vite.config.ts 中验证。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384