1# Build Patterns
2
3Language-specific templates for AUR packages. These templates use
4`cd "${pkgname}-${pkgver}"`, which suits suffix-less and `-bin` packages. For
5`-git` packages, use `cd "$pkgname"` instead (the source entry
6`"$pkgname::git+..."` clones into `$pkgname`).
7
8Based on the Arch Wiki's
9[Go](https://wiki.archlinux.org/title/Go_package_guidelines) and
10[Rust](https://wiki.archlinux.org/title/Rust_package_guidelines) package
11guidelines.
12
13## Go
14
15`makedepends=('go')`
16
17### Module caching
18
19Keep Go modules in the build environment rather than polluting `~/go`:
20
21```bash
22prepare() {
23 cd "${pkgname}-${pkgver}"
24 mkdir -p build/
25 export GOPATH="${srcdir}"
26 go mod download -modcacherw
27}
28```
29
30If upstream lacks `go.mod`, initialise it before downloading (file an issue upstream):
31
32```bash
33prepare() {
34 cd "$pkgname-$pkgver"
35 go mod init "${url#https://}"
36 go mod tidy
37}
38```
39
40### Building
41
42The standard approach exports CGO flags and uses `GOFLAGS`:
43
44```bash
45build() {
46 cd "${pkgname}-${pkgver}"
47 export CGO_CPPFLAGS="${CPPFLAGS}"
48 export CGO_CFLAGS="${CFLAGS}"
49 export CGO_CXXFLAGS="${CXXFLAGS}"
50 export CGO_LDFLAGS="${LDFLAGS}"
51 export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
52 go build -o build .
53}
54```
55
56When upstream embeds version info via `-ldflags`, pass flags explicitly instead:
57
58```bash
59build() {
60 cd "${pkgname}-${pkgver}"
61 export CGO_CPPFLAGS="${CPPFLAGS}"
62 export CGO_CFLAGS="${CFLAGS}"
63 export CGO_CXXFLAGS="${CXXFLAGS}"
64 export CGO_LDFLAGS="${LDFLAGS}"
65 go build \
66 -trimpath \
67 -buildmode=pie \
68 -mod=readonly \
69 -modcacherw \
70 -o build/"$pkgname" \
71 -ldflags "-linkmode external -extldflags \"${LDFLAGS}\"" \
72 .
73}
74```
75
76Use `-o build` with a `mkdir -p build/` in `prepare()` to control output
77location. For projects with multiple binaries: `go build -o build ./cmd/...`
78
79If upstream uses a Makefile, verify it passes hardening flags — many overwrite
80`GOFLAGS`. Bypass the Makefile if needed and invoke `go build` directly.
81
82### Testing and packaging
83
84```bash
85check() {
86 cd "${pkgname}-${pkgver}"
87 go test ./...
88}
89
90package() {
91 cd "${pkgname}-${pkgver}"
92 install -Dm755 build/"$pkgname" "$pkgdir"/usr/bin/"$pkgname"
93}
94```
95
96### FULL RELRO
97
98If `namcap` reports `ELF file lacks FULL RELRO`, add `-bindnow` to ldflags
99(requires Go ≥ 1.23):
100
101```bash
102-ldflags "-linkmode external -extldflags \"${LDFLAGS}\" -bindnow"
103```
104
105Or in the `GOFLAGS` style:
106
107```bash
108export GOFLAGS="-buildmode=pie -trimpath -ldflags='-linkmode=external -bindnow' -mod=readonly -modcacherw"
109```
110
111### Vendored dependencies
112
113If upstream ships a `vendor/` directory with `modules.txt`, change
114`-mod=readonly` to `-mod=vendor`.
115
116## Rust
117
118`makedepends=('cargo')`
119
120### Source
121
122Prefer source tarballs or GitHub release archives. When unavailable, use
123crates.io:
124
125```bash
126source=("$pkgname-$pkgver.tar.gz::https://static.crates.io/crates/$pkgname/$pkgname-$pkgver.crate")
127```
128
129Note: crates.io archives often lack test files, license files, and other assets.
130
131### Prepare, build, check
132
133```bash
134prepare() {
135 cd "$pkgname-$pkgver"
136 export RUSTUP_TOOLCHAIN=stable
137 cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')"
138}
139
140build() {
141 cd "$pkgname-$pkgver"
142 export RUSTUP_TOOLCHAIN=stable
143 export CARGO_TARGET_DIR=target
144 cargo build --frozen --release --all-features
145}
146
147check() {
148 cd "$pkgname-$pkgver"
149 export RUSTUP_TOOLCHAIN=stable
150 export CARGO_TARGET_DIR=target
151 cargo test --frozen --all-features
152}
153```
154
155- `--locked` / `--frozen`: Respect `Cargo.lock` exactly for reproducible builds.
156- `CARGO_TARGET_DIR=target`: Avoids user-preference side effects outside chroots.
157- `RUSTUP_TOOLCHAIN=stable`: Ensures default toolchain (unnecessary if upstream has `rust-toolchain.toml`).
158- Do **not** use `--release` for `check()` — it enables optimisations that hide bugs.
159- For cargo workspaces (check for `[workspace]` in `Cargo.toml`), add `--workspace` to `cargo test`.
160
161### Packaging
162
163```bash
164package() {
165 cd "$pkgname-$pkgver"
166 install -Dm0755 -t "$pkgdir/usr/bin/" "target/release/$pkgname"
167}
168```
169
170For multiple binaries:
171
172```bash
173package() {
174 cd "$pkgname-$pkgver"
175 find target/release \
176 -maxdepth 1 \
177 -executable \
178 -type f \
179 -exec install -Dm0755 -t "$pkgdir/usr/bin/" {} +
180}
181```
182
183### VCS packages
184
185For `-git` packages where upstream doesn't keep `Cargo.lock` in sync between
186releases, add `cargo update` before `cargo fetch` in `prepare()`.