Building Packages from Source in Alpine Linux: A Complete Developer Guide
I’ll show you how to build packages from source in Alpine Linux. After working with custom software for years, I’ve found Alpine’s package building system is actually pretty straightforward once you get the hang of it.
Introduction
Sometimes you need software that isn’t in the official repositories. Maybe it’s a newer version, custom patches, or something totally unique to your project. That’s where building from source comes in handy.
Alpine uses APKBUILD files to define how packages get built. It’s like a recipe that tells the system where to get source code, how to compile it, and what files to include in the final package.
Why You Need This
- Install software not available in repositories
- Apply custom patches or configurations
- Create packages for internal distribution
- Contribute packages to Alpine Linux community
Prerequisites
You’ll need these things first:
- Alpine Linux system with development tools
- Basic knowledge of shell scripting
- Understanding of compilation process
- Internet connection for downloading sources
Step 1: Set Up Build Environment
Install Development Tools
Let’s start by installing the tools needed for building packages.
What we’re doing: Setting up a complete Alpine package development environment.
# Install build dependencies
apk add alpine-sdk
# Add your user to abuild group
addgroup $USER abuild
# Create abuild directories
mkdir -p ~/packages/mypackage
cd ~/packages/mypackageCode explanation:
- alpine-sdk: Meta-package containing all build tools (gcc, make, abuild, etc.)
- addgroup $USER abuild: Allows your user to build packages
- mkdir -p ~/packages/mypackage: Creates directory structure for package development
Expected Output:
(1/25) Installing binutils (2.40-r7)
(2/25) Installing gcc (12.2.1_git20220924-r10)
...
OK: 234 MiB in 58 packagesConfigure Package Signing
What we’re doing: Setting up package signing for security.
# Generate signing key
abuild-keygen -a -i
# Create abuild configuration
echo "PACKAGER_PRIVKEY=\"$HOME/.abuild/your_email-private_key.rsa\"" > ~/.abuild/abuild.confCode explanation:
- abuild-keygen -a -i: Creates RSA key pair for package signing
- -a: Appends public key to /etc/apk/keys automatically
- -i: Installs the key in the system keyring
Tip: Keep your private key safe! If you lose it, you’ll need to regenerate it and re-sign all your packages.
Step 2: Create Your First APKBUILD
Basic APKBUILD Structure
Let’s create a simple APKBUILD file for a common tool.
What we’re doing: Creating an APKBUILD file to build a package from source.
# Create APKBUILD file
vi APKBUILDBasic APKBUILD template:
# Contributor: Your Name <[email protected]>
# Maintainer: Your Name <[email protected]>
pkgname=hello-world
pkgver=1.0.0
pkgrel=0
pkgdesc="Simple hello world program"
url="https://github.com/example/hello-world"
arch="all"
license="MIT"
makedepends="gcc libc-dev"
source="$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz"
builddir="$srcdir/$pkgname-$pkgver"
build() {
    cd "$builddir"
    make
}
package() {
    cd "$builddir"
    make DESTDIR="$pkgdir" install
}
sha512sums="
abcd1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef  hello-world-1.0.0.tar.gz
"APKBUILD explanation:
- pkgname: Package name (must match directory name)
- pkgver: Version number of the software
- pkgrel: Package release number (increment for Alpine-specific changes)
- makedepends: Build-time dependencies
- source: Where to download source code
- build(): Function that compiles the software
- package(): Function that installs files into package
Generate Checksums
What we’re doing: Creating security checksums for source files.
# Download source and generate checksums
abuild checksum
# Verify the checksums
abuild verifyCode explanation:
- abuild checksum: Downloads source files and generates SHA-512 checksums
- abuild verify: Verifies downloaded files match expected checksums
Step 3: Build the Package
Test Build Process
Now let’s actually build our package.
What we’re doing: Compiling source code and creating an Alpine package.
# Clean any previous builds
abuild clean
# Fetch source code
abuild fetch
# Verify source integrity
abuild verify
# Unpack and prepare source
abuild unpack
# Build the package
abuild -rCode explanation:
- abuild clean: Removes build artifacts from previous runs
- abuild fetch: Downloads source files specified in APKBUILD
- abuild verify: Checks file integrity using checksums
- abuild unpack: Extracts source archives
- abuild -r: Builds package with dependency resolution
Expected Output:
>>> hello-world: Building community/hello-world 1.0.0-r0 (using abuild 3.11.0-r0)
>>> hello-world: Checking sanity of /home/user/packages/mypackage/APKBUILD...
>>> hello-world: Analyzing dependencies...
>>> hello-world: Installing for build: build-base gcc libc-dev
>>> hello-world: Cleaning up srcdir
>>> hello-world: Cleaning up pkgdir
>>> hello-world: Fetching hello-world-1.0.0.tar.gz::https://github.com/example/hello-world/archive/v1.0.0.tar.gz
>>> hello-world: Checking sha512sums...
hello-world-1.0.0.tar.gz: OK
>>> hello-world: Unpacking /var/cache/distfiles/hello-world-1.0.0.tar.gz...
>>> hello-world: hello-world-1.0.0*
>>> hello-world: Entering fakeroot...
>>> hello-world: Running package()...
>>> hello-world: Tracing dependencies...
>>> hello-world: Package size: 4.0 KB
>>> hello-world: Compressing data...
>>> hello-world: Create checksum...
>>> hello-world: Create hello-world-1.0.0-r0.apkInstall Your Package
What we’re doing: Installing the freshly built package.
# Install the built package
sudo apk add ~/packages/mypackage/hello-world-1.0.0-r0.apk
# Test the installed package
hello-worldWarning: Always test your packages thoroughly before distributing them. A broken package can cause system issues.
Step 4: Advanced APKBUILD Features
Multiple Subpackages
What we’re doing: Creating packages with separate components (binaries, documentation, development files).
# Advanced APKBUILD with subpackages
vi APKBUILDAdvanced APKBUILD example:
# Contributor: Your Name <[email protected]>
# Maintainer: Your Name <[email protected]>
pkgname=advanced-tool
pkgver=2.1.0
pkgrel=0
pkgdesc="Advanced development tool with multiple components"
url="https://github.com/example/advanced-tool"
arch="all"
license="GPL-3.0-or-later"
makedepends="
    cmake
    samurai
    libc-dev
    libssl-dev
    "
subpackages="
    $pkgname-dev
    $pkgname-doc
    $pkgname-bash-completion:bashcomp:noarch
    "
source="$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz
        fix-compilation.patch
        "
builddir="$srcdir/$pkgname-$pkgver"
prepare() {
    default_prepare
    
    # Apply custom patches
    cd "$builddir"
    patch -p1 < "$srcdir/fix-compilation.patch"
}
build() {
    cd "$builddir"
    
    cmake -B build \
        -DCMAKE_INSTALL_PREFIX=/usr \
        -DCMAKE_BUILD_TYPE=Release \
        -DBUILD_SHARED_LIBS=True
    
    cmake --build build
}
check() {
    cd "$builddir"
    cmake --build build --target test
}
package() {
    cd "$builddir"
    DESTDIR="$pkgdir" cmake --install build
}
dev() {
    default_dev
    amove usr/include
    amove usr/lib/pkgconfig
}
doc() {
    default_doc
    amove usr/share/man
}
bashcomp() {
    pkgdesc="Bash completion for $pkgname"
    install_if="$pkgname=$pkgver-r$pkgrel bash-completion"
    
    amove usr/share/bash-completion
}
sha512sums="
1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef  advanced-tool-2.1.0.tar.gz
abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890  fix-compilation.patch
"Advanced features explanation:
- subpackages: Creates separate packages for development files, documentation, etc.
- prepare(): Function for patching source code before build
- check(): Function for running test suite
- amove: Alpine function to move files between subpackages
- install_if: Automatically installs subpackage when conditions are met
Custom Build Functions
What we’re doing: Creating specialized build functions for complex software.
# Example for Python package
build() {
    cd "$builddir"
    python3 setup.py build
}
package() {
    cd "$builddir"
    python3 setup.py install --prefix=/usr --root="$pkgdir"
}
# Example for Go package
build() {
    cd "$builddir"
    export GOPATH="$srcdir/go"
    go build -v -o "$pkgname"
}
package() {
    cd "$builddir"
    install -Dm755 "$pkgname" "$pkgdir/usr/bin/$pkgname"
}Practical Examples
Example 1: Building a Simple C Program
What we’re doing: Creating a package for a basic C application.
# Create project structure
mkdir -p ~/packages/simple-calc
cd ~/packages/simple-calc
# Create APKBUILD
cat > APKBUILD << 'EOF'
# Contributor: Your Name <[email protected]>
# Maintainer: Your Name <[email protected]>
pkgname=simple-calc
pkgver=1.0.0
pkgrel=0
pkgdesc="Simple command-line calculator"
url="https://github.com/example/simple-calc"
arch="all"
license="MIT"
makedepends="gcc libc-dev"
source="$pkgname-$pkgver.tar.gz::$url/archive/v$pkgver.tar.gz"
builddir="$srcdir/$pkgname-$pkgver"
build() {
    cd "$builddir"
    gcc -o simple-calc main.c -lm
}
package() {
    cd "$builddir"
    install -Dm755 simple-calc "$pkgdir/usr/bin/simple-calc"
}
sha512sums="SKIP"
EOF
# Generate checksums and build
abuild checksum
abuild -rCode explanation:
- gcc -o simple-calc main.c -lm: Compiles C source with math library
- install -Dm755: Installs binary with proper permissions
- sha512sums="SKIP": Temporary setting for development (don’t use in production!)
Example 2: Building with Configuration Options
What we’re doing: Building software with custom compile-time options.
# APKBUILD with configure script
build() {
    cd "$builddir"
    
    ./configure \
        --prefix=/usr \
        --sysconfdir=/etc \
        --mandir=/usr/share/man \
        --localstatedir=/var \
        --enable-ssl \
        --disable-debug \
        --with-system-libraries
        
    make
}
package() {
    cd "$builddir"
    make DESTDIR="$pkgdir" install
    
    # Remove unnecessary files
    rm -rf "$pkgdir/usr/share/doc"
}Troubleshooting
Build Failures
Problem: Package fails to build with compilation errors Solution: Check dependencies and build configuration
# Check build log for errors
abuild -r 2>&1 | tee build.log
# Verify all dependencies are installed
abuild deps
# Test build in clean environment
abuild clean && abuild -rDependency Issues
Problem: Missing dependencies during build Solution: Add required packages to makedepends
# Find what package provides a missing file
apk search cmd:gcc
apk search so:libssl.so.1.1
# Add to APKBUILD makedepends
makedepends="gcc libc-dev openssl-dev"Package Size Issues
Problem: Package is larger than expected Solution: Optimize package contents
# Check what's in your package
tar -tzf simple-calc-1.0.0-r0.apk
# Strip debug symbols
strip "$pkgdir/usr/bin/simple-calc"
# Remove unnecessary files
rm -rf "$pkgdir/usr/share/doc"Best Practices
- 
Version Management: Use semantic versioning # Good versioning pkgver=1.2.3 pkgrel=0 # Reset to 0 for new upstream version # Increment pkgrel for Alpine-specific changes pkgrel=1 # First Alpine-specific change
- 
Security Practices: - Always verify checksums
- Keep dependencies minimal
- Use official sources when possible
- Test packages thoroughly
 
- 
Code Quality: - Follow Alpine packaging guidelines
- Use proper file permissions
- Include appropriate metadata
- Add helpful package descriptions
 
Verification
To verify your package is working correctly:
# Check package contents
apk info -L simple-calc
# Verify package metadata
apk info simple-calc
# Test package functionality
simple-calc --helpWrapping Up
You just learned how to build packages from source in Alpine Linux:
- Set up a complete development environment
- Created APKBUILD files with proper structure
- Built and installed custom packages
- Handled advanced features like subpackages
- Troubleshot common build issues
Building your own packages gives you complete control over your software stack. I use this process for all my custom tools and it’s saved me countless hours of manual compilation. The Alpine package system is really well designed once you understand the basics.
 
   
   
  