AgentSkillsCN

archlinux-pkgbuild/compiled-languages

适用于打包编译型语言生态(Go、Rust、Haskell、OCaml、Free Pascal、Java)时使用——构建标志、依赖关系、可重复性。

SKILL.md
--- frontmatter
name: archlinux-pkgbuild/compiled-languages
description: Use when packaging compiled language ecosystems (Go, Rust, Haskell, OCaml, Free Pascal, Java) - build flags, dependencies, reproducibility

Compiled Language Ecosystems

For core PKGBUILD workflow, use archlinux-pkgbuild

This sub-skill covers compiled language packaging patterns where source code is transformed into native binaries or bytecode.

Quick Reference

LanguageArchitectureKey ToolInstall Location
Gox86_64go build/usr/bin/
Rustx86_64cargo/usr/bin/
Haskellx86_64ghc/usr/lib/$compiler/site-local/
OCamlx86_64/anydune/ocamlfind/usr/lib/ocaml/
Free Pascalx86_64fpc/usr/lib/fpc/$ver/units/
Javaanyjavac/maven/usr/share/java/

Go Packages

Go packages use Go modules for dependency management and require specific build flags.

Go Key Rules

RuleDescription
Package naminggo-modulename for Go-specific tools, otherwise use program name
go dependencyAdd go to makedepends
Go modulesUse go mod download -modcacherw in prepare()
GOPATHSet GOPATH="${srcdir}" to keep modules in build environment
Build flagsAlways use PIE, trimpath, external linkmode for RELRO
ReproducibilityUse -trimpath and set GOPATH for reproducible builds

Go Build Flags (MANDATORY)

Export these before building:

bash
export CGO_CPPFLAGS="${CPPFLAGS}"
export CGO_CFLAGS="${CFLAGS}"
export CGO_CXXFLAGS="${CXXFLAGS}"
export CGO_LDFLAGS="${LDFLAGS}"
export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"

Flag meanings:

FlagPurpose
-buildmode=piePIE compilation for binary hardening
-trimpathRemove full paths for reproducible builds
-mod=readonlyPrevent module file updates
-modcacherwMake module cache writable (cleanup)
-linkmode=externalUse external linker for RELRO support

Go Template

bash
pkgname=example
pkgver=1.0.0
pkgrel=1
pkgdesc="Example Go application"
arch=('x86_64')
url="https://example.com"
license=('MIT')
makedepends=('go')
source=("https://example.com/$pkgname-$pkgver.tar.gz")
sha256sums=('...')

prepare() {
    cd "$pkgname-$pkgver"
    
    # Download Go modules
    export GOPATH="${srcdir}"
    go mod download -modcacherw
    
    # Create output directory
    mkdir -p build
}

build() {
    cd "$pkgname-$pkgver"
    
    export CGO_CPPFLAGS="${CPPFLAGS}"
    export CGO_CFLAGS="${CFLAGS}"
    export CGO_CXXFLAGS="${CXXFLAGS}"
    export CGO_LDFLAGS="${LDFLAGS}"
    export GOPATH="${srcdir}"
    export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw"
    
    go build -o build .
}

check() {
    cd "$pkgname-$pkgver"
    go test ./...
}

package() {
    cd "$pkgname-$pkgver"
    install -Dm755 build/$pkgname "$pkgdir/usr/bin/$pkgname"
    install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

Go Common Issues

IssueCauseFix
No RELROMissing CGO_LDFLAGS or -linkmode=externalExport CGO_LDFLAGS, use -linkmode=external
Not reproducibleMissing -trimpath or GOPATH not setAdd -trimpath, set GOPATH="${srcdir}"
Makefile ignores flagsUpstream Makefile overrides GOFLAGSPatch Makefile or skip it
GOPATH growsDefault GOPATH usedSet GOPATH="${srcdir}" in prepare()

Rust Packages

Rust packages are built with Cargo and follow Rust's packaging conventions.

Rust Key Rules

RuleDescription
Package namingUse program name (not rust-* prefix)
Cargo.lockMust be present (use cargo vendor or prepare() if missing)
Architecturex86_64 (Rust doesn't officially support building for 'any')
makedependsAlways include rust and cargo
Vendored dependenciesUse cargo vendor for offline builds
Build flagsUse --release --locked
Install methodUse cargo install with --root

Rust Template

bash
pkgname=example-rust
pkgver=1.0.0
pkgrel=1
pkgdesc="Example Rust application"
arch=('x86_64')
url="https://github.com/user/example"
license=('MIT')
depends=('gcc-libs')
makedepends=('rust' 'cargo')
source=("$pkgname-$pkgver.tar.gz::https://static.crates.io/crates/$pkgname/$pkgname-$pkgver.crate")
sha256sums=('...')

prepare() {
    cd "$pkgname-$pkgver"
    
    # Update lockfile if needed
    cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
}

build() {
    cd "$pkgname-$pkgver"
    
    export RUSTUP_TOOLCHAIN=stable
    export CARGO_TARGET_DIR=target
    cargo build --release --locked
}

check() {
    cd "$pkgname-$pkgver"
    
    export RUSTUP_TOOLCHAIN=stable
    cargo test --release --locked
}

package() {
    cd "$pkgname-$pkgver"
    
    cargo install \
        --offline \
        --no-track \
        --path . \
        --root "$pkgdir/usr"
    
    # Install license
    install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

Rust Build Flags Explanation

FlagPurpose
--releaseOptimized build (not debug)
--lockedUse Cargo.lock exactly as-is
--frozenLike --locked but also fails if lockfile missing
--offlineNo network access during build
--no-trackDon't record installation in cargo registry
--targetSpecify target triple

Rust Common Issues

IssueCauseFix
Network access during buildNot using --locked/--frozenUse --locked flag, run cargo fetch in prepare()
Missing Cargo.lockUpstream doesn't commit itRun cargo generate-lockfile in prepare()
Wrong optimizationDebug build installedUse --release flag
Outdated dependenciesLockfile not updatedRun cargo update in prepare() if intentional
Build artifacts in /rootCARGO_TARGET_DIR not setExport CARGO_TARGET_DIR=target

Haskell Packages

Haskell packages use GHC (Glasgow Haskell Compiler) and require coordinated rebuilds.

Haskell Key Rules

RuleDescription
Package naminghaskell-libraryname (all lowercase, match Hackage name)
ArchitectureAlways x86_64 (all Haskell code is arch-dependent)
SourcePrefer Hackage (hackage.haskell.org)
DependenciesUse ghc-libs (runtime) and ghc (build time)
RegistrationInstall register.sh/unregister.sh scripts
Coordinated updatesLibrary updates require rebuilding ALL dependents

Haskell Template

bash
# Maintainer: Your Name <youremail at domain dot com>
_hkgname=example
pkgname=haskell-example
pkgver=1.0.0
pkgrel=1
pkgdesc="Example Haskell library"
arch=('x86_64')
url="https://hackage.haskell.org/package/$_hkgname"
license=('BSD')
depends=('ghc-libs' 'haskell-base')
makedepends=('ghc')
source=("https://hackage.haskell.org/packages/archive/$_hkgname/$pkgver/$_hkgname-$pkgver.tar.gz")
sha256sums=('...')

build() {
    cd "$_hkgname-$pkgver"
    
    runhaskell Setup configure -O --enable-shared --enable-debug-info \
        --enable-executable-dynamic --disable-library-vanilla \
        --prefix=/usr --docdir="/usr/share/doc/$pkgname" --datasubdir=$pkgname \
        --enable-tests \
        --dynlibdir=/usr/lib --libsubdir=\$compiler/site-local/\$pkgid \
        --ghc-option=-optl-Wl\,-z\,relro\,-z\,now \
        --ghc-option='-pie'
    
    runhaskell Setup build $MAKEFLAGS
    runhaskell Setup register --gen-script
    runhaskell Setup unregister --gen-script
    sed -i -r -e "s|ghc-pkg.*update[^ ]* |&'--force' |" register.sh
    sed -i -r -e "s|ghc-pkg.*unregister[^ ]* |&'--force' |" unregister.sh
}

check() {
    cd "$_hkgname-$pkgver"
    runhaskell Setup test
}

package() {
    cd "$_hkgname-$pkgver"
    
    install -D -m744 register.sh "$pkgdir/usr/share/haskell/register/$pkgname.sh"
    install -D -m744 unregister.sh "$pkgdir/usr/share/haskell/unregister/$pkgname.sh"
    runhaskell Setup copy --destdir="$pkgdir"
    install -D -m644 "LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
    rm -f "${pkgdir}/usr/share/doc/${pkgname}/LICENSE"
}

Haskell Common Issues

IssueCauseFix
Dependency not foundDependent not rebuiltRebuild all reverse dependencies
Build fails after updateIncompatible library versionsCheck upstream changelog, may need revert
Missing registration scriptsScripts not installedInstall register.sh/unregister.sh
Library not found at runtimeghc-libs not in dependsAdd ghc-libs to depends
Wrong architectureSet to 'any'Always use x86_64

OCaml Packages

OCaml packages contain libraries and bindings for the OCaml language.

OCaml Key Rules

RuleDescription
Package namingocaml-*modulename* (lowercase, hyphens)
Library directory/usr/lib/ocaml/
META filesUse ocaml-findlib for installation (ocamlfind install)
OCAMLFIND_DESTDIRSet to $pkgdir/usr/lib/ocaml with -mkdir option
Dune build systemPreferred modern build system for OCaml
Strip optionAdd options=('!strip') for bytecode-only packages
ArchitectureUse x86_64 only if native code; any if bytecode only
DependenciesAlways include ocaml in depends, ocaml-findlib if using META

OCaml Template (Dune)

bash
pkgname=ocaml-example
pkgver=1.0.0
pkgrel=1
pkgdesc="Example OCaml library"
arch=('x86_64')
url="https://github.com/example/ocaml-example"
license=('MIT')
depends=('ocaml')
makedepends=('dune' 'ocaml-findlib')
source=("https://github.com/example/ocaml-example/archive/$pkgver.tar.gz")
sha256sums=('...')

build() {
    cd "$srcdir/ocaml-example-$pkgver"
    dune build --release --verbose
}

package() {
    cd "$srcdir/ocaml-example-$pkgver"
    DESTDIR="$pkgdir" dune install --prefix=/usr --libdir=/usr/lib/ocaml
    
    # Remove .install file
    rm -f "$pkgdir/usr/lib/ocaml/example"/*.install
}

OCaml Common Issues

IssueCauseFix
Files installed to /usr/lib/ocaml/site-libOld directory conventionSet OCAMLFIND_DESTDIR=$pkgdir/usr/lib/ocaml
Strip errors on bytecodeBinary stripping breaks bytecodeAdd options=('!strip')
Wrong architecturePackage has both native/bytecodeUse x86_64 if native code exists
Missing META fileocaml-findlib not usedAdd ocaml-findlib to makedepends

Free Pascal Packages

Free Pascal Compiler (FPC) packages for Pascal/Delphi-compatible projects.

Free Pascal Key Rules

RuleDescription
Package namingUse project name (cross-compile: fpc32- or fpc-cpu-system-)
fpc dependencyAdd fpc to makedepends or depends
Units location/usr/lib/fpc/$_fpcver/units/$_unitdir/
Architecturex86_64 (or any for cross-compile, x86_64 for multilib)
Static librariesAdd staticlibs to options if installing import libs
Cross-compile stripAdd !strip for non-Unix targets

Free Pascal Template

bash
pkgname=example
pkgver=1.0.0
pkgrel=1
pkgdesc="Example Free Pascal application"
arch=('x86_64')
url="https://example.com"
license=('GPL')
depends=('fpc')
source=("https://example.com/$pkgname-$pkgver.tar.gz")
sha256sums=('...')

build() {
    cd "$pkgname-$pkgver"
    
    # Build with FPC
    fpc -O3 -XX -CX src/example.pas
}

package() {
    cd "$pkgname-$pkgver"
    
    # Determine FPC paths
    local _unitdir=$(fpc -iSP)-$(fpc -iSO)
    local _fpcver=$(fpc -iV)
    
    # Install binary
    install -Dm755 example "$pkgdir/usr/bin/example"
    
    # Install compiled units
    install -dm755 "$pkgdir/usr/lib/fpc/$_fpcver/units/$_unitdir/$pkgname"
    install -Dm644 *.o *.ppu *.a "$pkgdir/usr/lib/fpc/$_fpcver/units/$_unitdir/$pkgname/"
}

Free Pascal Common Issues

IssueCauseFix
Units in wrong locationWrong pathUse /usr/lib/fpc/$_fpcver/units/$_unitdir/
Missing fpc dependencyNot in makedepends/dependsAdd to appropriate array
Strip breaks cross-compileUnix strip on non-Unix binaryAdd !strip to options
Missing staticlibsImport library without flagAdd staticlibs to options

Java Packages

Java packages require special handling for classpath management and dependency isolation.

Java Key Rules

RuleDescription
Package namingjava-libraryname for generic names, otherwise use program name
JAR locationAll JARs in /usr/share/java/myprogram/ (including bundled deps)
Shell wrapperRequired for end-user programs (in /usr/bin/)
CLASSPATHSet via -cp option (not environment variable)
Dependenciesjava-runtime (runtime) or java-environment (build time)
Refactor dependenciesSeparate common/large libraries into own packages when possible

Java Template

bash
pkgname=example-java
pkgver=1.0.0
pkgrel=1
pkgdesc="Example Java application"
arch=('any')
url="https://example.com"
license=('GPL')
depends=('java-runtime>=8')
makedepends=('java-environment>=8' 'maven')
source=("https://example.com/$pkgname-$pkgver.tar.gz")
sha256sums=('...')

build() {
    cd "$pkgname-$pkgver"
    mvn clean package
}

package() {
    cd "$pkgname-$pkgver"
    
    # Install main JAR and dependencies
    install -dm755 "$pkgdir/usr/share/java/$pkgname"
    install -Dm644 target/*.jar "$pkgdir/usr/share/java/$pkgname/"
    install -Dm644 lib/*.jar "$pkgdir/usr/share/java/$pkgname/"
    
    # Create wrapper script
    install -Dm755 /dev/stdin "$pkgdir/usr/bin/$pkgname" << 'EOF'
#!/bin/sh
# Build classpath
CP=""
for jar in /usr/share/java/example-java/*.jar; do
    CP="$CP:$jar"
done

# Run main class
exec /usr/bin/java -cp "$CP" com.example.MainClass "$@"
EOF
    
    # Install license
    install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

Java Common Issues

IssueCauseFix
JAVA_HOME tests in scriptsUpstream script checks JAVA_HOMERemove checks, use /usr/bin/java directly
Bundled dependenciesAll deps in single directoryInitially OK, refactor common deps over time
Wrong wrapper locationScript in /opt or /usr/shareMust be in /usr/bin
CLASSPATH environmentSet via exportUse -cp flag instead