From b47a6d94bb0b94e0d87f13e113e3815254542ee7 Mon Sep 17 00:00:00 2001 From: ohh Date: Mon, 9 Mar 2026 19:14:21 +0800 Subject: [PATCH] build: add ARM64 (aarch64) architecture support - Add architecture detection to build.sh and scripts/build_deps.sh - Add --arch flag for cross-compilation support - Use architecture-specific dependency directories - Update CMakeLists.txt to detect and display target architecture - Add ARM64 build jobs to CI/CD workflows - Update release packaging to include architecture in filename --- .github/workflows/ci.yml | 34 ++++++++++++++++++-- .github/workflows/release.yml | 59 +++++++++++++++++++++++++++++++++-- CMakeLists.txt | 29 ++++++++++++++--- build.sh | 31 +++++++++++++++--- scripts/build_deps.sh | 55 +++++++++++++++++++++++++++++--- 5 files changed, 188 insertions(+), 20 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f0b20b..81540f4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,8 @@ on: branches: [main, develop] jobs: - build: + build-x86_64: + name: Build (x86_64) runs-on: ubuntu-22.04 container: ubuntu:20.04 env: @@ -27,7 +28,36 @@ jobs: uses: actions/cache@v4 with: path: 3rd_party - key: deps-${{ runner.os }}-iceoryx2.0.3-cyclonedds0.10.2 + key: deps-${{ runner.os }}-x86_64-iceoryx2.0.3-cyclonedds0.10.2 + + - name: Build dependencies + run: ./scripts/build_deps.sh + + - name: Build and Test + run: ./build.sh -t -r + + build-aarch64: + name: Build (aarch64) + runs-on: ubuntu-22.04-arm + container: ubuntu:20.04 + env: + DEBIAN_FRONTEND: noninteractive + BUILD_TYPE: Release + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + apt-get update + apt-get install -y cmake g++ libacl1-dev git + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: 3rd_party + key: deps-${{ runner.os }}-aarch64-iceoryx2.0.3-cyclonedds0.10.2 - name: Build dependencies run: ./scripts/build_deps.sh diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f9a23a9..d51ed11 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,8 @@ permissions: contents: write jobs: - build: + build-x86_64: + name: Build Release (x86_64) runs-on: ubuntu-22.04 container: ubuntu:20.04 env: @@ -28,7 +29,7 @@ jobs: uses: actions/cache@v4 with: path: 3rd_party - key: deps-${{ runner.os }}-cyclonedds0.10.2-shm + key: deps-${{ runner.os }}-x86_64-cyclonedds0.10.2-shm - name: Build run: | @@ -52,12 +53,57 @@ jobs: name: ${{ env.PKG_NAME }} path: ${{ env.PKG_NAME }}.tar.gz + build-aarch64: + name: Build Release (aarch64) + runs-on: ubuntu-22.04-arm + container: ubuntu:20.04 + env: + DEBIAN_FRONTEND: noninteractive + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install dependencies + run: | + apt-get update + apt-get install -y cmake g++ ninja-build libacl1-dev git + + - name: Cache dependencies + uses: actions/cache@v4 + with: + path: 3rd_party + key: deps-${{ runner.os }}-aarch64-cyclonedds0.10.2-shm + + - name: Build + run: | + ./build.sh -c + + - name: Run tests + run: ./build/tests/cddsctl_tests + + - name: Package + run: | + VERSION=${GITHUB_REF#refs/tags/v} + PKG_NAME="cddsctl-${VERSION}-linux-aarch64" + mkdir -p ${PKG_NAME}/bin + cp build/cli/cddsctl ${PKG_NAME}/bin/ + tar -czvf ${PKG_NAME}.tar.gz ${PKG_NAME} + echo "PKG_NAME=${PKG_NAME}" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: ${{ env.PKG_NAME }} + path: ${{ env.PKG_NAME }}.tar.gz + release: + name: Create Release runs-on: ubuntu-22.04 container: ubuntu:20.04 env: DEBIAN_FRONTEND: noninteractive - needs: build + needs: [build-x86_64, build-aarch64] steps: - name: Install dependencies @@ -94,11 +140,18 @@ jobs: echo "" >> RELEASE_NOTES.md echo "## Installation" >> RELEASE_NOTES.md echo "" >> RELEASE_NOTES.md + echo "### x86_64" >> RELEASE_NOTES.md echo "\`\`\`bash" >> RELEASE_NOTES.md echo "tar -xzf cddsctl-${VERSION}-linux-x86_64.tar.gz" >> RELEASE_NOTES.md echo "sudo mv cddsctl-${VERSION}-linux-x86_64/bin/cddsctl /usr/local/bin/" >> RELEASE_NOTES.md echo "\`\`\`" >> RELEASE_NOTES.md echo "" >> RELEASE_NOTES.md + echo "### ARM64 (aarch64)" >> RELEASE_NOTES.md + echo "\`\`\`bash" >> RELEASE_NOTES.md + echo "tar -xzf cddsctl-${VERSION}-linux-aarch64.tar.gz" >> RELEASE_NOTES.md + echo "sudo mv cddsctl-${VERSION}-linux-aarch64/bin/cddsctl /usr/local/bin/" >> RELEASE_NOTES.md + echo "\`\`\`" >> RELEASE_NOTES.md + echo "" >> RELEASE_NOTES.md echo "Built with CycloneDDS 0.10.2 and iceoryx 2.0.5 (shared memory)." >> RELEASE_NOTES.md echo "SHM is used automatically when a compatible RouDi daemon is running; otherwise falls back to UDP." >> RELEASE_NOTES.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 19a1fd9..56cde67 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,24 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) +# Detect target architecture +if(CMAKE_SYSTEM_PROCESSOR) + set(TARGET_ARCH "${CMAKE_SYSTEM_PROCESSOR}") +else() + execute_process(COMMAND uname -m OUTPUT_VARIABLE TARGET_ARCH OUTPUT_STRIP_TRAILING_WHITESPACE) +endif() + +# Normalize architecture names +if(TARGET_ARCH MATCHES "^(x86_64|amd64)$") + set(TARGET_ARCH_NAME "x86_64") +elseif(TARGET_ARCH MATCHES "^(aarch64|arm64)$") + set(TARGET_ARCH_NAME "aarch64") +else() + set(TARGET_ARCH_NAME "${TARGET_ARCH}") +endif() + +message(STATUS "Target architecture: ${TARGET_ARCH_NAME}") + # Debug symbols for all build types add_compile_options(-g) @@ -28,11 +46,11 @@ foreach(LINE ${VERSION_LINES}) endif() endforeach() -# Third-party library paths -set(YAMLCPP_DIR ${CDDSCTL_3RD_PARTY}/yaml-cpp) -set(ICEORYX_DIR ${CDDSCTL_3RD_PARTY}/iceoryx) -set(CYCLONEDDS_DIR ${CDDSCTL_3RD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}) -set(CYCLONEDDS_CXX_DIR ${CDDSCTL_3RD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}) +# Third-party library paths (architecture-specific) +set(YAMLCPP_DIR ${CDDSCTL_3RD_PARTY}/yaml-cpp-${TARGET_ARCH_NAME}) +set(ICEORYX_DIR ${CDDSCTL_3RD_PARTY}/iceoryx-${TARGET_ARCH_NAME}) +set(CYCLONEDDS_DIR ${CDDSCTL_3RD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}-${TARGET_ARCH_NAME}) +set(CYCLONEDDS_CXX_DIR ${CDDSCTL_3RD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}-${TARGET_ARCH_NAME}) list(APPEND CMAKE_PREFIX_PATH ${YAMLCPP_DIR} ${ICEORYX_DIR} ${CYCLONEDDS_DIR} ${CYCLONEDDS_CXX_DIR}) # CycloneDDS depends on iceoryx, need to find iceoryx targets first (static libs) @@ -86,6 +104,7 @@ message(STATUS "========================================") message(STATUS "cddsctl Configuration") message(STATUS "========================================") message(STATUS "Version: ${PROJECT_VERSION}") +message(STATUS "Architecture: ${TARGET_ARCH_NAME}") message(STATUS "Build Examples: ${BUILD_EXAMPLES}") message(STATUS "========================================") message(STATUS "") diff --git a/build.sh b/build.sh index ddc6545..c078c97 100755 --- a/build.sh +++ b/build.sh @@ -15,7 +15,21 @@ else exit 1 fi -# 默认并行数 +# Detect architecture +ARCH=$(uname -m) +case "${ARCH}" in + x86_64) + ARCH_NAME="x86_64" + ;; + aarch64|arm64) + ARCH_NAME="aarch64" + ;; + *) + ARCH_NAME="${ARCH}" + ;; +esac + +# Default parallel jobs JOBS=$(nproc 2>/dev/null || echo 4) usage() { @@ -76,25 +90,31 @@ while [[ $# -gt 0 ]]; do esac done +# Architecture-specific dependency paths +ICEORYX_PREFIX="${THIRD_PARTY}/iceoryx-${ARCH_NAME}" +CYCLONEDDS_PREFIX="${THIRD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}-${ARCH_NAME}" +CYCLONEDDS_CXX_PREFIX="${THIRD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}-${ARCH_NAME}" +YAMLCPP_PREFIX="${THIRD_PARTY}/yaml-cpp-${ARCH_NAME}" + # Check if dependencies exist YAMLCPP_OK=0 ICEORYX_OK=0 CYCLONEDDS_OK=0 CYCLONEDDS_CXX_OK=0 -if [[ -f "${THIRD_PARTY}/yaml-cpp/lib/libyaml-cpp.a" ]]; then +if [[ -f "${YAMLCPP_PREFIX}/lib/libyaml-cpp.a" ]]; then YAMLCPP_OK=1 fi -if [[ -f "${THIRD_PARTY}/iceoryx/lib/libiceoryx_posh.a" ]]; then +if [[ -f "${ICEORYX_PREFIX}/lib/libiceoryx_posh.a" ]]; then ICEORYX_OK=1 fi -if [[ -f "${THIRD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}/lib/libddsc.a" ]]; then +if [[ -f "${CYCLONEDDS_PREFIX}/lib/libddsc.a" ]]; then CYCLONEDDS_OK=1 fi -if [[ -f "${THIRD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}/lib/libddscxx.a" ]]; then +if [[ -f "${CYCLONEDDS_CXX_PREFIX}/lib/libddscxx.a" ]]; then CYCLONEDDS_CXX_OK=1 fi @@ -136,6 +156,7 @@ echo "==> Building with ${JOBS} jobs..." cmake --build "${BUILD_DIR}" -j "${JOBS}" echo "==> Build complete!" +echo " Architecture: ${ARCH_NAME}" echo " CLI: ${BUILD_DIR}/cli/cddsctl" if [[ $RUN_TESTS -eq 1 ]]; then diff --git a/scripts/build_deps.sh b/scripts/build_deps.sh index caefedb..7945f64 100755 --- a/scripts/build_deps.sh +++ b/scripts/build_deps.sh @@ -10,6 +10,25 @@ THIRD_PARTY="${PROJECT_ROOT}/3rd_party" BUILD_DIR="${THIRD_PARTY}/build" JOBS=$(nproc 2>/dev/null || echo 4) +# Detect architecture +ARCH=$(uname -m) +case "${ARCH}" in + x86_64) + ARCH_NAME="x86_64" + ;; + aarch64|arm64) + ARCH_NAME="aarch64" + ;; + *) + echo "Warning: Unsupported architecture '${ARCH}', defaulting to ${ARCH}" + ARCH_NAME="${ARCH}" + ;; +esac + +# Cross-compilation support +CROSS_COMPILE=0 +CROSS_ARCH="" + # Load versions from .versions file VERSIONS_FILE="${PROJECT_ROOT}/.versions" if [[ -f "${VERSIONS_FILE}" ]]; then @@ -19,11 +38,11 @@ else exit 1 fi -# Install prefixes -ICEORYX_PREFIX="${THIRD_PARTY}/iceoryx" -CYCLONEDDS_PREFIX="${THIRD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}" -CYCLONEDDS_CXX_PREFIX="${THIRD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}" -YAMLCPP_PREFIX="${THIRD_PARTY}/yaml-cpp" +# Install prefixes (architecture-specific) +ICEORYX_PREFIX="${THIRD_PARTY}/iceoryx-${ARCH_NAME}" +CYCLONEDDS_PREFIX="${THIRD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}-${ARCH_NAME}" +CYCLONEDDS_CXX_PREFIX="${THIRD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}-${ARCH_NAME}" +YAMLCPP_PREFIX="${THIRD_PARTY}/yaml-cpp-${ARCH_NAME}" usage() { echo "Usage: $0 [OPTIONS]" @@ -31,6 +50,7 @@ usage() { echo "Options:" echo " -c, --clean Clean build (remove build directory first)" echo " -j N Number of parallel jobs (default: $JOBS)" + echo " --arch ARCH Target architecture for cross-compilation (x86_64, aarch64)" echo " -h, --help Show this help" } @@ -46,6 +66,27 @@ while [[ $# -gt 0 ]]; do JOBS="$2" shift 2 ;; + --arch) + CROSS_ARCH="$2" + CROSS_COMPILE=1 + case "${CROSS_ARCH}" in + x86_64|aarch64) + ARCH_NAME="${CROSS_ARCH}" + echo "==> Cross-compiling for ${ARCH_NAME}" + ;; + *) + echo "Error: Unsupported architecture '${CROSS_ARCH}'" + echo "Supported architectures: x86_64, aarch64" + exit 1 + ;; + esac + # Update prefixes with new architecture + ICEORYX_PREFIX="${THIRD_PARTY}/iceoryx-${ARCH_NAME}" + CYCLONEDDS_PREFIX="${THIRD_PARTY}/cyclonedds-${CYCLONEDDS_VERSION}-${ARCH_NAME}" + CYCLONEDDS_CXX_PREFIX="${THIRD_PARTY}/cyclonedds-cxx-${CYCLONEDDS_VERSION}-${ARCH_NAME}" + YAMLCPP_PREFIX="${THIRD_PARTY}/yaml-cpp-${ARCH_NAME}" + shift 2 + ;; -h|--help) usage exit 0 @@ -189,6 +230,10 @@ echo "" echo "=========================================" echo "Dependencies built successfully!" echo "=========================================" +echo "Architecture: ${ARCH_NAME}" +if [[ ${CROSS_COMPILE} -eq 1 ]]; then + echo "Build type: Cross-compiled" +fi echo "yaml-cpp: ${YAMLCPP_PREFIX}" echo "iceoryx: ${ICEORYX_PREFIX}" echo "CycloneDDS: ${CYCLONEDDS_PREFIX}"