Skip to content

Commit 99696da

Browse files
Bartek Wronavogel76
authored andcommitted
Build multiarch (x86_64 + aarch64) hived image for mainnet & mirrornet
Add multi-arch production image support. The amd64 image is compiled natively; the aarch64 image is CROSS-compiled (never emulated) using the buildroot toolchain and preinstalled aarch64 RocksDB baked into ci-base-image (hive/common-ci-configuration!377). Dockerfile: - build stage pinned to --platform=$BUILDPLATFORM so the heavy C++ compile always runs natively; for $TARGETARCH=arm64 it cross-compiles via $CROSS_ROOT/Toolchain.cmake with the preinstalled aarch64 vendor RocksDB. Cross-build specifics: unset the x64 OPENSSL_* env so find_package(OpenSSL) hits the sysroot; provide a static qemu-aarch64 (CMAKE emulator) so the assertion-id generators run; export the cross CC/CXX/AR/LD so fc's autotools secp256k1 cross-compiles; force-static readline/ncurses so hived needs only glibc at runtime. - instance stage parameterised by INSTANCE_BASE_IMAGE and built --platform=$TARGETPLATFORM. Default keeps the pre-published minimal-runtime image (x64 fast path); multiarch builds set INSTANCE_BASE_IMAGE=minimal-runtime to build the runtime inline per-arch from ubuntu:24.04. - TEMPORARY: CI_BASE_IMAGE pinned to the cci!377 image; repoint after that MR merges. build_instance.sh: HIVE_BUILD_PLATFORMS triggers a multi-arch manifest build (--platform, --push, inline runtime base); single-arch --load path unchanged. .gitlab-ci.yaml: gated prepare_hived_image_multiarch (mainnet) and mirrornet_node_build_multiarch jobs, restricted via rules to develop / master / protected tags / manual BUILD_MULTIARCH=true, so feature/MR pipelines stay x86_64-only. The single-arch jobs keep running every pipeline. Depends on hive/common-ci-configuration!377. Validated locally against the cci!377 image: aarch64 build stage builds 620/620 using the preinstalled RocksDB, and the assembled aarch64 mainnet image runs hived/cli_wallet (glibc-only runtime deps).
1 parent 55efd7e commit 99696da

8 files changed

Lines changed: 510 additions & 29 deletions

File tree

.gitlab-ci.yaml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,69 @@ mirrornet_node_build:
247247
docker push ${IMAGE_NAME_PREFIX}${CI_COMMIT_TAG}
248248
fi
249249
250+
# --- Multiarch (x86_64 + aarch64) production images ---------------------------------------
251+
# Build a multi-arch manifest: amd64 compiled natively + arm64 CROSS-compiled (never emulated)
252+
# using the toolchain + preinstalled aarch64 RocksDB baked into ci-base-image. The arm64 runtime
253+
# layer is built inline from the multiarch ubuntu:24.04 base (emulated apt only). A manifest
254+
# cannot be loaded into the local daemon, so it is pushed.
255+
#
256+
# Gated to develop, master, protected tags, or a manual BUILD_MULTIARCH=true trigger, so feature/MR
257+
# pipelines stay x86_64-only and fast. The single-arch prepare_hived_image / mirrornet_node_build
258+
# jobs above keep running every pipeline (they also export x86_64 binaries for the replay/test jobs).
259+
.prepare_hived_image_multiarch:
260+
extends: .docker_image_builder_job
261+
stage: build
262+
needs:
263+
- job: detect_changes
264+
optional: true
265+
variables:
266+
# IMAGE_PATH: "" for mainnet, "/mirrornet" for mirrornet (set per job)
267+
IMAGE_PATH: ""
268+
rules:
269+
- if: '$CI_COMMIT_BRANCH == "develop"'
270+
- if: '$CI_COMMIT_BRANCH == "master"'
271+
- if: '$CI_COMMIT_TAG && $CI_COMMIT_REF_PROTECTED == "true"'
272+
- if: '$BUILD_MULTIARCH == "true"'
273+
when: manual
274+
- when: never
275+
tags:
276+
- bigjob
277+
script:
278+
- |
279+
set -euo pipefail
280+
echo "$HIVED_CI_IMGBUILDER_PASSWORD" | docker login -u "$HIVED_CI_IMGBUILDER_USER" registry.gitlab.syncad.com --password-stdin
281+
# Register qemu/binfmt for the (cheap, emulated) arm64 runtime stage. The cross-compiled
282+
# build stage runs natively on the amd64 builder and is NOT emulated.
283+
docker run --rm --privileged tonistiigi/binfmt --install arm64,amd64 || true
284+
# A docker-container buildx builder (required to produce & push a manifest list) is already
285+
# created and selected by the .docker_image_builder_job before_script as "docker-container-builder",
286+
# wired to the dind endpoint + registry BUILDKIT_CONFIG_ARG. Reuse it rather than creating a second
287+
# builder here (a bare "docker buildx create --driver docker-container" lacks that endpoint/config
288+
# and fails). build_instance.sh's buildx build runs on this active builder.
289+
# Build + push the multi-arch manifest (tagged with the commit short SHA).
290+
"$CI_PROJECT_DIR/scripts/ci-helpers/build_instance.sh" \
291+
"$CI_COMMIT_SHORT_SHA" "$CI_PROJECT_DIR" registry.gitlab.syncad.com/hive/hive \
292+
--network-type="$HIVE_NETWORK_TYPE" \
293+
--platforms="linux/amd64,linux/arm64"
294+
# Apply published tags onto the pushed multi-arch manifest (no pull needed).
295+
SRC="registry.gitlab.syncad.com/hive/hive${IMAGE_PATH}:${CI_COMMIT_SHORT_SHA}"
296+
apply_tag() { docker buildx imagetools create -t "registry.gitlab.syncad.com/hive/hive${IMAGE_PATH}:$1" "$SRC"; }
297+
[[ "$CI_COMMIT_BRANCH" == "develop" ]] && apply_tag latest || true
298+
[[ "$CI_COMMIT_BRANCH" == "master" ]] && apply_tag stable || true
299+
if [[ -n "${CI_COMMIT_TAG:-}" && "$CI_COMMIT_REF_PROTECTED" == "true" ]]; then apply_tag "$CI_COMMIT_TAG"; fi
300+
301+
prepare_hived_image_multiarch:
302+
extends: .prepare_hived_image_multiarch
303+
variables:
304+
HIVE_NETWORK_TYPE: mainnet
305+
IMAGE_PATH: ""
306+
307+
mirrornet_node_build_multiarch:
308+
extends: .prepare_hived_image_multiarch
309+
variables:
310+
HIVE_NETWORK_TYPE: mirrornet
311+
IMAGE_PATH: "/mirrornet"
312+
250313
extended_block_log_creation:
251314
extends: .extended_block_log_creation
252315
stage: build

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,17 @@ set( INSTALLER_APP_ID "68ad7005-8eee-49c9-95ce-9eed97e5b347" )
3030
set(CMAKE_EXPORT_COMPILE_COMMANDS "ON")
3131
set(CMAKE_VERBOSE_MAKEFILE "ON")
3232

33-
# Compiler caching support (sccache preferred, ccache fallback)
33+
# Compiler caching support (sccache preferred, ccache fallback).
34+
# Disabled when cross-compiling: wrapping the buildroot aarch64 cross-gcc with sccache mishandles
35+
# the -MF dependency-file output (the in-tree equihash/blake2b C compile fails with
36+
# "opening dependency file ...o.d: No such file or directory"). The gated cross build runs
37+
# infrequently, so losing the cache there is acceptable. Native (x86_64) builds are unaffected.
3438
find_program(SCCACHE_PROGRAM sccache)
3539
find_program(CCACHE_PROGRAM ccache)
3640

37-
if(SCCACHE_PROGRAM)
41+
if(CMAKE_CROSSCOMPILING)
42+
message(STATUS "Cross-compiling: compiler caching (sccache/ccache) disabled")
43+
elseif(SCCACHE_PROGRAM)
3844
message(STATUS "Found sccache: ${SCCACHE_PROGRAM}")
3945
set(CMAKE_C_COMPILER_LAUNCHER "${SCCACHE_PROGRAM}")
4046
set(CMAKE_CXX_COMPILER_LAUNCHER "${SCCACHE_PROGRAM}")

Dockerfile

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,16 @@ ARG CI_REGISTRY_IMAGE=registry.gitlab.syncad.com/hive/hive/
66
ARG CI_IMAGE_TAG=ubuntu24.04-py3.14-1
77
ARG BUILD_IMAGE_TAG
88
ARG IMAGE_TAG_PREFIX
9-
# CI base image for build stage - must be at top level for FROM to see it
10-
# Using commit hash instead of tag to pin to a specific docker image for build repeatability.
11-
# Tags can be moved/overwritten, but commit hashes are immutable. May switch to tags in future.
12-
ARG CI_BASE_IMAGE=registry.gitlab.syncad.com/hive/common-ci-configuration/ci-base-image:fddc56669a22b53e6d75a6d697ee8a0f42a7ce52
9+
# CI base image for build stage - must be at top level for FROM to see it.
10+
# Pinned to the published ci-base-image version tag that ships the aarch64 cross toolchain +
11+
# preinstalled aarch64 RocksDB (hive/common-ci-configuration!377).
12+
ARG CI_BASE_IMAGE=registry.gitlab.syncad.com/hive/common-ci-configuration/ci-base-image:pypa_2_28-pg18-arm-1
13+
14+
# Runtime base for the final `instance` image. Default: the pre-published, commit-tagged
15+
# minimal-runtime image (x86_64 fast path). Multiarch builds pass
16+
# INSTANCE_BASE_IMAGE=minimal-runtime to build the runtime inline per-arch from the
17+
# multiarch ubuntu:24.04 base, so no separately-published multiarch minimal-runtime is needed.
18+
ARG INSTANCE_BASE_IMAGE=${CI_REGISTRY_IMAGE}minimal-runtime:${CI_IMAGE_TAG}
1319

1420
FROM phusion/baseimage:noble-1.0.1 AS runtime
1521

@@ -51,8 +57,15 @@ USER hived
5157
WORKDIR /home/hived
5258

5359
# Build stage uses centralized ci-base-image from common-ci-configuration
54-
# This image includes: build toolchain, sccache, Pythons 3.8 - 3.14, glibc 2.28, Docker CLI, hived user
55-
FROM ${CI_BASE_IMAGE} AS build
60+
# This image includes: build toolchain, sccache, Pythons 3.8 - 3.14, glibc 2.28, Docker CLI, hived user.
61+
# Pinned to the native build platform ($BUILDPLATFORM) so the heavy C++ compile is NEVER emulated;
62+
# aarch64 targets are cross-compiled (not emulated) using the toolchain baked into ci-base-image.
63+
FROM --platform=${BUILDPLATFORM} ${CI_BASE_IMAGE} AS build
64+
65+
# Target architecture (set automatically by BuildKit: amd64 | arm64). amd64 builds
66+
# natively; arm64 cross-compiles via $CROSS_ROOT/Toolchain.cmake (+ preinstalled aarch64 vendor libs).
67+
ARG TARGETARCH
68+
ENV TARGETARCH=${TARGETARCH}
5669

5770
ARG BUILD_HIVE_TESTNET=OFF
5871
ENV BUILD_HIVE_TESTNET=${BUILD_HIVE_TESTNET}
@@ -89,10 +102,20 @@ RUN <<-EOF
89102
sudo mkdir -p "${INSTALLATION_DIR}"
90103
sudo chown hived:users "${INSTALLATION_DIR}"
91104

105+
# For aarch64 targets, cross-compile using the toolchain + preinstalled aarch64 vendor libs
106+
# (RocksDB) baked into ci-base-image. The whole cross environment is set up by build.sh's
107+
# --cross-root (it picks up the preinstalled RocksDB from $HIVE_AARCH64_VENDOR_DIR). amd64 builds
108+
# natively (no extra args).
109+
CROSS_ARGS=()
110+
if [ "${TARGETARCH}" = "arm64" ]; then
111+
CROSS_ARGS+=( --cross-root="${CROSS_ROOT}" )
112+
fi
113+
92114
./source/${HIVE_SUBDIR}/scripts/build.sh --source-dir="./source/${HIVE_SUBDIR}" --binary-dir="./build" \
93115
--cmake-arg="-DBUILD_HIVE_TESTNET=${BUILD_HIVE_TESTNET}" \
94116
--cmake-arg="-DHIVE_CONVERTER_BUILD=${HIVE_CONVERTER_BUILD}" \
95117
--cmake-arg="-DHIVE_LINT=${HIVE_LINT}" \
118+
"${CROSS_ARGS[@]}" \
96119
--flat-binary-directory="${INSTALLATION_DIR}" \
97120
--clean-after-build
98121

@@ -105,7 +128,7 @@ RUN <<-EOF
105128
sudo chown -R hived:users "${INSTALLATION_DIR}/"*
106129
EOF
107130

108-
FROM ${CI_REGISTRY_IMAGE}minimal-runtime:$CI_IMAGE_TAG AS instance
131+
FROM --platform=${TARGETPLATFORM} ${INSTANCE_BASE_IMAGE} AS instance
109132

110133
ARG BUILD_TIME
111134
ARG GIT_COMMIT_SHA

0 commit comments

Comments
 (0)