[1;33m[WARNING][0m No existing semantic tags found. Starting from v0.0.0
v0.0.1 - Reorganize ISO build tree, add docs/plans/scripts, and stage Phase 2 Slice B+C service integration artifacts
This commit is contained in:
32
stack/build-common/Dockerfile.alpine-musl
Normal file
32
stack/build-common/Dockerfile.alpine-musl
Normal file
@@ -0,0 +1,32 @@
|
||||
FROM alpine:3.19 AS base
|
||||
|
||||
RUN apk add --no-cache \
|
||||
build-base \
|
||||
musl-dev \
|
||||
git \
|
||||
cmake \
|
||||
autoconf \
|
||||
automake \
|
||||
libtool \
|
||||
pkgconf \
|
||||
openssl-dev \
|
||||
openssl-libs-static \
|
||||
zlib-dev \
|
||||
zlib-static \
|
||||
curl-dev \
|
||||
curl-static \
|
||||
libsecp256k1-dev \
|
||||
sqlite-dev \
|
||||
sqlite-static
|
||||
|
||||
# Alpine provides libsecp256k1 shared objects, but we need a static archive
|
||||
# for fully-static musl linking. Build and install libsecp256k1.a in /usr/local.
|
||||
RUN git clone --depth 1 https://github.com/bitcoin-core/secp256k1.git /tmp/secp256k1 && \
|
||||
cd /tmp/secp256k1 && \
|
||||
./autogen.sh && \
|
||||
./configure --enable-static --disable-shared --prefix=/usr/local && \
|
||||
make -j"$(nproc)" && \
|
||||
make install && \
|
||||
rm -rf /tmp/secp256k1
|
||||
|
||||
WORKDIR /src
|
||||
32
stack/build-common/README.md
Normal file
32
stack/build-common/README.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Shared Alpine/musl static builder pattern
|
||||
|
||||
This directory defines the common static build base used by `stack/*` C99 binaries.
|
||||
|
||||
## Why this exists
|
||||
|
||||
Per [F30](../../plans/threat_model.md#46-image-build-and-reproducibility), every n-OS-tr C binary must be built in Alpine and statically linked against musl so `ldd` reports `not a dynamic executable`.
|
||||
|
||||
## Files
|
||||
|
||||
- `Dockerfile.alpine-musl`: shared Alpine 3.19 base with common musl/static build dependencies.
|
||||
- `build_static.sh`: generic wrapper that:
|
||||
- accepts `<target-dir>`
|
||||
- picks `linux/amd64` or `linux/arm64` using `uname -m` (or `ARCH=arm64` override)
|
||||
- builds the shared base image and the target app image
|
||||
- extracts the built binary to `<target-dir>/build/<basename>_static_<arch>`
|
||||
|
||||
## Invocation pattern from subtrees
|
||||
|
||||
Each stack component keeps its own `Dockerfile.alpine-musl` and a thin wrapper script:
|
||||
|
||||
```bash
|
||||
./stack/<component>/build_static.sh
|
||||
```
|
||||
|
||||
The component wrapper calls this shared script as:
|
||||
|
||||
```bash
|
||||
../build-common/build_static.sh .
|
||||
```
|
||||
|
||||
from inside that component directory.
|
||||
110
stack/build-common/build_static.sh
Executable file
110
stack/build-common/build_static.sh
Executable file
@@ -0,0 +1,110 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <target-dir>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET_DIR="$1"
|
||||
TARGET_ABS="$(cd "$TARGET_DIR" && pwd)"
|
||||
COMMON_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
BASENAME="$(basename "$TARGET_ABS")"
|
||||
BUILD_DIR="$TARGET_ABS/build"
|
||||
DOCKERFILE="$TARGET_ABS/Dockerfile.alpine-musl"
|
||||
|
||||
if [ ! -f "$DOCKERFILE" ]; then
|
||||
echo "ERROR: Missing Dockerfile: $DOCKERFILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! command -v docker >/dev/null 2>&1; then
|
||||
echo "ERROR: docker is not installed or not in PATH"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "ERROR: docker daemon is not reachable"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
HOST_ARCH="$(uname -m)"
|
||||
REQUESTED_ARCH="${ARCH:-}"
|
||||
|
||||
if [ -n "$REQUESTED_ARCH" ]; then
|
||||
case "$REQUESTED_ARCH" in
|
||||
arm64|aarch64)
|
||||
PLATFORM="linux/arm64"
|
||||
OUTPUT_ARCH="arm64"
|
||||
;;
|
||||
amd64|x86_64)
|
||||
PLATFORM="linux/amd64"
|
||||
OUTPUT_ARCH="x86_64"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: Unsupported ARCH='$REQUESTED_ARCH' (supported: arm64, amd64)"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
case "$HOST_ARCH" in
|
||||
x86_64)
|
||||
PLATFORM="linux/amd64"
|
||||
OUTPUT_ARCH="x86_64"
|
||||
;;
|
||||
aarch64|arm64)
|
||||
PLATFORM="linux/arm64"
|
||||
OUTPUT_ARCH="arm64"
|
||||
;;
|
||||
*)
|
||||
echo "WARNING: Unknown host architecture '$HOST_ARCH', defaulting to linux/amd64"
|
||||
PLATFORM="linux/amd64"
|
||||
OUTPUT_ARCH="$HOST_ARCH"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
OUTPUT_NAME="${BASENAME}_static_${OUTPUT_ARCH}"
|
||||
BASE_IMAGE_TAG="n-os-tr/alpine-musl-base:3.19"
|
||||
APP_IMAGE_TAG="n-os-tr/${BASENAME}-musl-builder:latest"
|
||||
|
||||
mkdir -p "$BUILD_DIR"
|
||||
|
||||
echo "=========================================="
|
||||
echo "n-OS-tr Alpine/musl static build"
|
||||
echo "=========================================="
|
||||
echo "Target: $TARGET_ABS"
|
||||
echo "Platform: $PLATFORM"
|
||||
echo "Output: $BUILD_DIR/$OUTPUT_NAME"
|
||||
echo ""
|
||||
|
||||
echo "[1/3] Building shared base image ($BASE_IMAGE_TAG)"
|
||||
docker build \
|
||||
--platform "$PLATFORM" \
|
||||
-f "$COMMON_DIR/Dockerfile.alpine-musl" \
|
||||
-t "$BASE_IMAGE_TAG" \
|
||||
"$COMMON_DIR"
|
||||
|
||||
echo "[2/3] Building application image ($APP_IMAGE_TAG)"
|
||||
docker build \
|
||||
--platform "$PLATFORM" \
|
||||
-f "$DOCKERFILE" \
|
||||
-t "$APP_IMAGE_TAG" \
|
||||
"$TARGET_ABS"
|
||||
|
||||
echo "[3/3] Extracting binary"
|
||||
CONTAINER_ID="$(docker create "$APP_IMAGE_TAG" "/$BASENAME")"
|
||||
trap 'docker rm -f "$CONTAINER_ID" >/dev/null 2>&1 || true' EXIT
|
||||
|
||||
docker cp "$CONTAINER_ID:/$BASENAME" "$BUILD_DIR/$OUTPUT_NAME"
|
||||
chmod +x "$BUILD_DIR/$OUTPUT_NAME"
|
||||
|
||||
FILE_INFO="$(file "$BUILD_DIR/$OUTPUT_NAME")"
|
||||
echo "$FILE_INFO"
|
||||
|
||||
if LDD_OUT="$(ldd "$BUILD_DIR/$OUTPUT_NAME" 2>&1 || true)"; then
|
||||
echo "$LDD_OUT"
|
||||
fi
|
||||
|
||||
echo "Built: $BUILD_DIR/$OUTPUT_NAME"
|
||||
echo "Size: $(stat -c '%s bytes' "$BUILD_DIR/$OUTPUT_NAME")"
|
||||
Reference in New Issue
Block a user