Imported from NeuralBlitz/Mito (
.opencode/skills/build-tools/SKILL.md). Install upstream withnpx skills add NeuralBlitz/Mito --skill build-tools. Copyright stays with the author.
Build Tools
Category: DevOps
Skill Level: Intermediate
Domain: Software Compilation, CI/CD, Automation, DevOps
Overview
Build Tools are software utilities that automate the process of compiling source code, managing dependencies, packaging applications, and running tests. They form the foundation of modern software development workflows, enabling consistent, repeatable, and efficient build processes.
Description
Build tools have evolved from simple command-line compilers to sophisticated automation platforms that manage complex dependency graphs, execute multi-stage build pipelines, and integrate seamlessly with continuous integration and deployment systems. Understanding build tools is essential for developers who need to optimize build times, ensure consistent builds across environments, and integrate their code into automated delivery pipelines.
Modern build systems operate at multiple levels of the software stack. Low-level tools handle compilation of source code into executables or libraries, managing compilation units, include paths, and compiler flags. Dependency managers resolve and download external libraries, ensuring reproducible builds across different machines and environments. Build orchestrators coordinate multiple build steps, run tests, create artifacts, and publish releases. Each layer requires specific configuration and understanding to use effectively.
The choice of build tool often depends on the programming language, project complexity, and organizational requirements. Make and its modern variants (CMake, Ninja) dominate C and C++ projects, while Maven and Gradle serve the Java ecosystem. npm and Yarn manage JavaScript dependencies, pip and Poetry handle Python packages, and Cargo has become the standard for Rust development. Understanding the principles underlying these tools—dependency resolution, incremental builds, parallelization, and artifact caching—translates across ecosystems.
Build caching and incremental compilation dramatically impact developer productivity, especially in large monorepos. Modern tools track file dependencies and rebuild only what changed, while distributed caches can share build artifacts across teams. Build profiling tools help identify bottlenecks, and optimizing build configuration can reduce feedback cycles from minutes to seconds. These optimizations become critical as projects grow and CI/CD pipelines must execute within tight time windows.
Prerequisites
- Command-line proficiency and shell scripting knowledge
- Understanding of software compilation and interpretation concepts
- Familiarity with version control and dependency management
- Knowledge of continuous integration principles
Core Competencies
- Configuring and using language-specific package managers
- Writing build scripts and Makefiles
- Setting up multi-stage Docker builds for efficient image creation
- Integrating build tools with CI/CD pipelines
- Optimizing build performance through caching and parallelization
- Managing cross-platform and multi-environment builds
Implementation
# Makefile for multi-language project
.SILENT: build test clean
# Configuration
PROJECT_NAME := neuralblitz
VERSION := 1.0.0
BUILD_DIR := build
ARTIFACTS_DIR := artifacts
# Go configuration
GO_MOD_PATH := opencode-lrs-agents-nbx
GO_BUILD_OUTPUT := $(BUILD_DIR)/$(PROJECT_NAME)
# Python configuration
PYTHON_SRC := NBX-LRS
PYTHON_VENV := .venv
PYTHON_BIN := $(PYTHON_VENV)/bin
# Node configuration
NODE_SRC := NB-Ecosystem
NODE_BUILD := $(NODE_SRC)/dist
# Environment
export PATH := $(PYTHON_BIN):$(PATH)
# Default target
all: install build test package
.PHONY: install
install: $(PYTHON_BIN)/pip npm-install go-mod-download
@echo "Installing dependencies..."
$(PYTHON_BIN)/pip:
@echo "Setting up Python virtual environment..."
python3 -m venv $(PYTHON_VENV)
$(PYTHON_BIN)/pip install --upgrade pip
$(PYTHON_BIN)/pip install -r $(PYTHON_SRC)/requirements.txt
.PHONY: npm-install
npm-install:
@echo "Installing npm dependencies..."
cd $(NODE_SRC) && npm install
.PHONY: go-mod-download
go-mod-download:
@echo "Downloading Go modules..."
cd $(GO_MOD_PATH) && go mod download
.PHONY: build
build: go-build python-build npm-build
@echo "Build complete!"
go-build:
@echo "Building Go binary..."
cd $(GO_MOD_PATH) && go build -o $(GO_BUILD_OUTPUT) ./cmd/server
python-build:
@echo "Building Python application..."
$(PYTHON_BIN)/python -m py_compile $(PYTHON_SRC)/neuralblitz_v50/**/*.py
npm-build:
@echo "Building npm application..."
cd $(NODE_SRC) && npm run build
.PHONY: test
test: go-test python-test npm-test
@echo "All tests passed!"
go-test:
@echo "Running Go tests..."
cd $(GO_MOD_PATH) && go test ./... -v
python-test:
@echo "Running Python tests..."
$(PYTHON_BIN)/pytest $(PYTHON_SRC)/tests/ -v --tb=short
npm-test:
@echo "Running npm tests..."
cd $(NODE_SRC) && npm test
.PHONY: clean
clean:
@echo "Cleaning build artifacts..."
rm -rf $(BUILD_DIR) $(ARTIFACTS_DIR)
rm -rf $(PYTHON_VENV) $(NODE_SRC)/node_modules
cd $(GO_MOD_PATH) && go clean -cache
.PHONY: package
package: build
@echo "Creating distribution packages..."
mkdir -p $(ARTIFACTS_DIR)
# Create Go artifact
cp $(GO_BUILD_OUTPUT) $(ARTIFACTS_DIR)/
# Create Python wheel
$(PYTHON_BIN)/pip wheel $(PYTHON_SRC) -w $(ARTIFACTS_DIR)/
# Archive npm build
cd $(NODE_BUILD) && tar -czf ../../$(ARTIFACTS_DIR)/frontend.tar.gz .
@echo "Artifacts created in $(ARTIFACTS_DIR)/"
.PHONY: docker-build
docker-build:
@echo "Building Docker images..."
docker build -t $(PROJECT_NAME):$(VERSION) -t $(PROJECT_NAME):latest .
.PHONY: profile
profile:
@echo "Profiling build performance..."
time $(MAKE) build
# Help target
help:
@echo "Available targets:"
@echo " all - Install, build, test, and package"
@echo " install - Install all dependencies"
@echo " build - Build all components"
@echo " test - Run all tests"
@echo " clean - Remove build artifacts"
@echo " package - Create distribution packages"
@echo " docker-build - Build Docker images"
# GitHub Actions workflow for multi-language build
name: Multi-Language Build Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
GO_VERSION: '1.21'
PYTHON_VERSION: '3.11'
NODE_VERSION: '20'
jobs:
lint:
name: Lint & Security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Run Go linter
run: |
cd opencode-lrs-agents-nbx
make lint || echo "Linting skipped"
- name: Run Python linter
run: |
python -m pip install ruff
ruff check NBX-LRS/
- name: Run npm audit
run: |
cd NB-Ecosystem
npm audit --audit-level=high
test:
name: Test Suite
runs-on: ubuntu-latest
needs: lint
strategy:
matrix:
component: [go, python, node]
steps:
- uses: actions/checkout@v4
- name: Set up Go
if: matrix.component == 'go'
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Set up Python
if: matrix.component == 'python'
uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- name: Set up Node
if: matrix.component == 'node'
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache Go modules
if: matrix.component == 'go'
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Python packages
if: matrix.component == 'python'
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
restore-keys: |
${{ runner.os }}-pip-
- name: Cache Node modules
if: matrix.component == 'node'
uses: actions/cache@v4
with:
path: NB-Ecosystem/node_modules
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Run Go tests
if: matrix.component == 'go'
run: |
cd opencode-lrs-agents-nbx
make test
- name: Run Python tests
if: matrix.component == 'python'
run: |
export PYTHONPATH=/home/runner/workspace/NB-Ecosystem/lib/python3.11/site-packages:$PYTHONPATH
cd NBX-LRS && python3 comprehensive_test_suite.py
- name: Run Node tests
if: matrix.component == 'node'
run: |
cd NB-Ecosystem && npm test
build:
name: Build & Package
runs-on: ubuntu-latest
needs: test
outputs:
go-artifact: ${{ steps.build-go.outputs.path }}
python-artifact: ${{ steps.build-python.outputs.path }}
node-artifact: ${{ steps.build-node.outputs.path }}
steps:
- uses: actions/checkout@v4
- name: Build Go binary
id: build-go
run: |
cd opencode-lrs-agents-nbx
make build
echo "path=$(ls -la ../build/neuralblitz)" >> $GITHUB_OUTPUT
- name: Build Python package
id: build-python
run: |
cd NBX-LRS
python3 -m build .
- name: Build Node application
id: build-node
run: |
cd NB-Ecosystem
npm run build
- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: go-binary
path: build/neuralblitz
- name: Upload Python package
uses: actions/upload-artifact@v4
with:
name: python-package
path: NBX-LRS/dist/
docker:
name: Docker Build
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name == 'push' }}
tags: neuralblitz:${{ github.sha }}, neuralblitz:latest
cache-from: type=gha
cache-to: type=gha,mode=max
deploy:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: [build, docker]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
environment: staging
steps:
- name: Deploy to staging
run: |
echo "Deploying to staging environment..."
# Deployment commands would go here
# Multi-stage Docker build for optimized images
# Stage 1: Builder stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
# Copy Go module files first for better caching
COPY opencode-lrs-agents-nbx/go.mod opencode-lrs-agents-nbx/go.sum ./
RUN go mod download && go mod verify
# Copy source and build
COPY opencode-lrs-agents-nbx/ ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o /app/server ./cmd/server
# Stage 2: Python stage
FROM python:3.11-slim AS python-builder
WORKDIR /app
# Copy requirements and install dependencies
COPY NBX-LRS/requirements.txt ./
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Copy application
COPY NBX-LRS/ ./
# Stage 3: Node stage
FROM node:20-alpine AS node-builder
WORKDIR /app
COPY NB-Ecosystem/package*.json ./
RUN npm ci --only=production
COPY NB-Ecosystem/ ./
RUN npm run build
# Stage 4: Final runtime stage
FROM gcr.io/distroless/cc-debian12:stable AS runtime
# Install runtime dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
&& rm -rf /var/lib/apt/lists/*
# Create non-root user
RUN addgroup -g 1000 appgroup && \
adduser -u 1000 -G appgroup -s /bin/sh -D appuser
# Copy artifacts from builder stages
COPY --from=builder /app/server /app/server
COPY --from=python-builder /install /usr/local
COPY --from=node-builder /app/dist /app/dist
# Create directories
RUN mkdir -p /app/logs /app/data && chown -R appuser:appgroup /app
# Switch to non-root user
USER appuser
# Environment variables
ENV PYTHONPATH=/usr/local/lib/python3.11/site-packages
ENV NODE_ENV=production
# Expose ports
EXPOSE 5000 5173
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:5000/health || exit 1
# Entrypoint
ENTRYPOINT ["/app/server"]
# Python build script with dependency management
import subprocess
import sys
import os
from pathlib import Path
class BuildManager:
def __init__(self, project_root: Path):
self.project_root = project_root
self.python_venv = project_root / ".venv"
self.build_dir = project_root / "build"
self.artifacts_dir = project_root / "artifacts"
def run_command(
self,
cmd: list,
cwd: Path = None,
env: dict = None
) -> subprocess.CompletedProcess:
"""Run a command and return the result."""
merged_env = os.environ.copy()
if env:
merged_env.update(env)
return subprocess.run(
cmd,
cwd=cwd or self.project_root,
env=merged_env,
check=True,
capture_output=True,
text=True
)
def setup_virtual_environment(self) -> None:
"""Create and populate Python virtual environment."""
print("Setting up Python virtual environment...")
if not self.python_venv.exists():
subprocess.run(
[sys.executable, "-m", "venv", str(self.python_venv)],
check=True
)
pip_path = self.python_venv / "bin" / "pip"
self.run_command([str(pip_path), "install", "--upgrade", "pip"])
self.run_command(
[str(pip_path), "install", "-r", "requirements.txt"],
cwd=self.project_root / "NBX-LRS"
)
def compile_python(self) -> Path:
"""Compile Python source files."""
print("Compiling Python source...")
python_path = self.python_venv / "bin" / "python"
# Compile all Python files
for py_file in (self.project_root / "NBX-LRS").rglob("*.py"):
self.run_command(
[str(python_path), "-m", "py_compile", str(py_file)]
)
print("Python compilation complete")
return self.python_venv
def run_tests(self) -> bool:
"""Run the test suite."""
print("Running tests...")
python_path = self.python_venv / "bin" / "python"
result = subprocess.run(
[str(python_path), "-m", "pytest", "NBX-LRS/tests/", "-v"],
capture_output=True,
text=True
)
print(result.stdout)
if result.returncode != 0:
print(result.stderr, file=sys.stderr)
return result.returncode == 0
def create_package(self) -> Path:
"""Create distribution package."""
print("Creating Python package...")
self.build_dir.mkdir(exist_ok=True)
self.artifacts_dir.mkdir(exist_ok=True)
python_path = self.python_venv / "bin" / "python"
# Build wheel and source distribution
self.run_command(
[str(python_path), "-m", "build"],
cwd=self.project_root / "NBX-LRS"
)
# Copy artifacts
dist_dir = self.project_root / "NBX-LRS" / "dist"
for artifact in dist_dir.glob("*"):
print(f"Created artifact: {artifact.name}")
return dist_dir
def full_build(self) -> bool:
"""Execute full build pipeline."""
print("Starting full build...")
try:
self.setup_virtual_environment()
self.compile_python()
if not self.run_tests():
print("Tests failed, aborting build")
return False
self.create_package()
print("Build completed successfully")
return True
except subprocess.CalledProcessError as e:
print(f"Build failed: {e}")
return False
if __name__ == "__main__":
root = Path("/home/runner/workspace")
builder = BuildManager(root)
success = builder.full_build()
sys.exit(0 if success else 1)
Use Cases
- Automating compilation and packaging of multi-language projects
- Setting up CI/CD pipelines with proper caching strategies
- Creating optimized Docker images with multi-stage builds
- Managing complex dependency graphs in monorepos
- Optimizing build times through parallelization and caching
- Standardizing build processes across development teams
Artifacts
- Makefiles and build scripts for various platforms
- GitHub Actions and GitLab CI configuration files
- Docker multi-stage build configurations
- Package.json and requirements.txt files
- Build cache configurations for distributed builds
Related Skills
- Continuous Integration
- Docker
- CI/CD Pipelines
- Dependency Management
- Scripting