From 90ffe65fab1a204ac8c0b7e88d435ec6da8febc9 Mon Sep 17 00:00:00 2001 From: matt Date: Sun, 26 Apr 2026 00:50:59 +0100 Subject: [PATCH] Added refactored CI - Added Ubuntu builds --- .github/workflows/ci.yml | 587 +++++++++------- CMakeLists.txt | 83 ++- build.sh | 896 +++++++++---------------- cmake_modules/DebPackageFilename.cmake | 77 ++- deps/packages-coverage.txt | 1 + deps/packages-quality.txt | 2 + deps/packages-sbom.txt | 2 + deps/packages-trixie.txt | 14 + deps/packages-ubuntu24.txt | 14 + src/Common/Data.cpp | 4 +- src/Messenger/MessageInStream.cpp | 13 +- 11 files changed, 821 insertions(+), 872 deletions(-) mode change 100755 => 100644 build.sh create mode 100644 deps/packages-coverage.txt create mode 100644 deps/packages-quality.txt create mode 100644 deps/packages-sbom.txt create mode 100644 deps/packages-trixie.txt create mode 100644 deps/packages-ubuntu24.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4f084b9..67bf895c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,314 +1,387 @@ name: CI on: - push: - branches: - - main - - develop - - 'feature/*' - - 'bugfix/*' - - newdev - paths-ignore: - - '**.md' - - 'docs/**' - - '.gitignore' - - '.github/**' - pull_request: + push: branches: - main - - develop - newdev - paths-ignore: - - '**.md' - - 'docs/**' - - '.gitignore' - - '.github/**' - workflow_dispatch: - inputs: - version: - description: 'Build version (leave empty for auto-generated)' - required: false - default: '' - type: string - architecture: - description: 'Architecture to build (all, amd64, arm64, armhf)' - required: false - default: 'amd64' - type: choice - options: - - all - - amd64 - - arm64 - - armhf - distribution: - description: 'Debian distribution to build (trixie, bookworm, all)' - required: false - default: 'all' - type: choice - options: - - all - - trixie - - bookworm - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }}/aasdk + +permissions: + contents: read jobs: - prepare: - runs-on: ubuntu-latest - outputs: - matrix: ${{ steps.matrix.outputs.matrix }} - distribution: ${{ steps.matrix.outputs.distribution }} + quality-coverage-quick-build: + name: Quality + Coverage + Quick Build + runs-on: ubuntu-24.04 steps: - - name: Generate build matrix - id: matrix + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Install dependencies run: | - # Determine distributions - if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then - DISTRO_INPUT="${{ github.event.inputs.distribution }}" - else - DISTRO_INPUT="all" - fi + chmod +x ./build.sh + CODE_QUALITY=ON ENABLE_COVERAGE=ON BUILD_SBOM=ON ./build.sh --install-deps - # Determine architectures - ARCH_INPUT="${{ github.event.inputs.architecture }}" - if [ -z "$ARCH_INPUT" ] || [ "$ARCH_INPUT" = "all" ]; then - ARCHES="amd64 arm64 armhf" - else - ARCHES="$ARCH_INPUT" - fi + - name: Resolve and sanitize build version from git tags (SemVer) + id: version + shell: bash + run: | + set -euo pipefail + git fetch --tags --force + sanitize_semver() { + local v="$1" + v="${v#v}" - # Limit to amd64 for non-main/develop branches to speed up cycle time during debugging - if [ "${{ github.ref }}" != "refs/heads/newdev" ] && [ "${{ github.ref }}" != "refs/heads/main" ] && [ "${{ github.ref }}" != "refs/heads/develop" ] && [ "${{ github.event_name }}" != "workflow_dispatch" ]; then - ARCHES="amd64" - echo "Building only amd64 for feature/bugfix branch (automatic push)" - fi + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)([-+][0-9A-Za-z.-]+)?$ ]]; then + echo "$v" + return 0 + fi + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.0" + return 0 + fi + if [[ "$v" =~ ^([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.0.0" + return 0 + fi + + echo "0.1.0" + } - # Expand distributions list - if [ "$DISTRO_INPUT" = "all" ]; then - DISTROS="bookworm trixie" - echo "distribution=all" >> $GITHUB_OUTPUT + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + base_version="$(sanitize_semver "${GITHUB_REF_NAME}")" + version="${base_version}" else - DISTROS="$DISTRO_INPUT" - echo "distribution=$DISTRO_INPUT" >> $GITHUB_OUTPUT + latest_tag="$(git tag --sort=-v:refname | head -n1 || true)" + base_version="$(sanitize_semver "${latest_tag}")" + if [[ -z "${base_version}" ]]; then + base_version="0.1.0" + fi + version="${base_version}+${GITHUB_SHA::7}" fi + echo "base_version=${base_version}" >> "${GITHUB_OUTPUT}" + echo "version=${version}" >> "${GITHUB_OUTPUT}" - # Helper to map arch to platform - platform_for_arch() { - case "$1" in - amd64) echo "linux/amd64";; - arm64) echo "linux/arm64";; - armhf) echo "linux/arm/v7";; - *) echo "linux/amd64";; - esac - } + - name: Run unified quality + coverage + quick package build + run: | + chmod +x ./build.sh + BUILD_DIR=build-quality \ + BUILD_TESTS=ON \ + BUILD_PACKAGE=ON \ + BUILD_SBOM=ON \ + CODE_QUALITY=ON \ + FORMAT_CHECK=ON \ + ENABLE_COVERAGE=ON \ + VERSION="${{ steps.version.outputs.version }}" \ + ./build.sh --clean + + - name: Upload quick build artifacts + uses: actions/upload-artifact@v7 + with: + name: quick-build-amd64-artifacts + if-no-files-found: warn + path: | + build-quality/packages/*.deb + build-quality/packages/*.tgz + + - name: Upload quick build SBOM artifacts + uses: actions/upload-artifact@v7 + with: + name: quick-build-amd64-sbom + if-no-files-found: error + path: | + build-quality/sbom/*.spdx.json + + - name: Generate coverage reports + run: | + lcov --capture --ignore-errors mismatch --rc geninfo_unexecuted_blocks=1 --directory build-quality --output-file build-quality/coverage.info + lcov --ignore-errors unused,mismatch --remove build-quality/coverage.info '/usr/*' '*/unit_test/*' '*/src/*.ut.cpp' --output-file build-quality/coverage.filtered.info + lcov --summary build-quality/coverage.filtered.info > build-quality/coverage-summary.txt + genhtml build-quality/coverage.filtered.info --output-directory build-quality/coverage-html - # Build matrix JSON (ensure valid JSON without over-escaping) - MATRIX='{"include":[' - first=true - for d in $DISTROS; do - for a in $ARCHES; do - plat=$(platform_for_arch "$a") - entry=$(printf '{"arch":"%s","platform":"%s","distro":"%s"}' "$a" "$plat" "$d") - if [ "$first" = true ]; then - MATRIX+="$entry" - first=false - else - MATRIX+=",$entry" - fi - done - done - MATRIX+=']}' - echo "matrix=$MATRIX" >> $GITHUB_OUTPUT - - build: - name: Build AASDK for ${{ matrix.arch }} on ${{ matrix.distro }} - needs: prepare + - name: Publish coverage summary to workflow page + shell: bash + run: | + { + echo "## Test Coverage" + echo + echo "Source: build-quality/coverage.filtered.info" + echo + echo '```text' + cat build-quality/coverage-summary.txt + echo '```' + } >> "${GITHUB_STEP_SUMMARY}" + + - name: Upload coverage artifacts + uses: actions/upload-artifact@v7 + with: + name: coverage-report + path: | + build-quality/coverage.filtered.info + build-quality/coverage-summary.txt + build-quality/coverage-html/ + + full-multiarch-build-test: + name: Full Build + Unit Tests (${{ matrix.distro_id }}-${{ matrix.arch_id }}) + if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' + needs: [quality-coverage-quick-build] runs-on: ubuntu-latest strategy: fail-fast: false - matrix: ${{ fromJson(needs.prepare.outputs.matrix) }} - + matrix: + include: + - distro: ubuntu:24.04 + distro_id: ubuntu24 + platform: linux/amd64 + arch_id: amd64 + - distro: ubuntu:24.04 + distro_id: ubuntu24 + platform: linux/arm64 + arch_id: arm64 + - distro: ubuntu:24.04 + distro_id: ubuntu24 + platform: linux/arm/v7 + arch_id: armhf + - distro: debian:trixie-slim + distro_id: trixie + platform: linux/amd64 + arch_id: amd64 + - distro: debian:trixie-slim + distro_id: trixie + platform: linux/arm64 + arch_id: arm64 + - distro: debian:trixie-slim + distro_id: trixie + platform: linux/arm/v7 + arch_id: armhf steps: - - name: Checkout code - uses: actions/checkout@v6 + - name: Checkout + uses: actions/checkout@v5 with: fetch-depth: 0 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v4 - - - name: Set up QEMU for cross-platform builds + - name: Set up QEMU emulation uses: docker/setup-qemu-action@v4 - with: - platforms: all - - name: Generate build info - id: build_info + - name: Resolve and sanitize build version from git tags (SemVer) + id: version + shell: bash run: | - # Use manual version if provided, otherwise generate using same scheme as CMake - if [ -n "${{ github.event.inputs.version }}" ]; then - VERSION="${{ github.event.inputs.version }}" - else - BUILD_YEAR=$(date -u +"%Y") - BUILD_MONTH=$(date -u +"%m") - BUILD_DAY=$(date -u +"%d") - VERSION="${BUILD_YEAR}.${BUILD_MONTH}.${BUILD_DAY}" - COMMIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") - if [ "$COMMIT_SHA" != "unknown" ]; then - VERSION="${VERSION}+git.${COMMIT_SHA}" - if [ "${{ github.event_name }}" = "workflow_dispatch" ] && ! git diff --quiet 2>/dev/null; then - VERSION="${VERSION}.dirty" - fi + set -euo pipefail + git fetch --tags --force + + sanitize_semver() { + local v="$1" + v="${v#v}" + + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)([-+][0-9A-Za-z.-]+)?$ ]]; then + echo "$v" + return 0 fi - fi - COMMIT_SHA=$(git rev-parse --short HEAD 2>/dev/null || echo "unknown") - BUILD_DATE=$(date -u +"%Y%m%d_%H%M%S") - RELEASE_VERSION="${VERSION}" - if [ "${{ github.event.inputs.create_release }}" = "true" ] || [[ "${GITHUB_REF}" == refs/tags/* ]]; then - if [ -z "${{ github.event.inputs.version }}" ]; then - RELEASE_VERSION="${BUILD_YEAR}.${BUILD_MONTH}.${BUILD_DAY}" - if [ "$COMMIT_SHA" != "unknown" ]; then - RELEASE_VERSION="${RELEASE_VERSION}+git.${COMMIT_SHA}" - fi + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.0" + return 0 + fi + if [[ "$v" =~ ^([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.0.0" + return 0 fi - fi - echo "version=${VERSION}" >> $GITHUB_OUTPUT - echo "release_version=${RELEASE_VERSION}" >> $GITHUB_OUTPUT - echo "commit_sha=${COMMIT_SHA}" >> $GITHUB_OUTPUT - echo "build_date=${BUILD_DATE}" >> $GITHUB_OUTPUT - echo "package_name=aasdk-${{ matrix.arch }}-${VERSION}" >> $GITHUB_OUTPUT - - name: Build AASDK for ${{ matrix.arch }} on ${{ matrix.distro }} - run: | - echo "Building AASDK for ${{ matrix.arch }} architecture" - RUN_TESTS=false - if [ "${{ github.event_name }}" = "pull_request" ] || [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/develop" ]; then - RUN_TESTS=true - fi - echo "RUN_TESTS=${RUN_TESTS} for this build" - if [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/newdev" ]; then - BUILD_TYPE="release" - echo "Building release packages for main branch" + echo "0.1.0" + } + + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + base_version="$(sanitize_semver "${GITHUB_REF_NAME}")" + version="${base_version}" else - BUILD_TYPE="debug" - echo "Building debug packages for ${{ github.ref_name }} branch" + latest_tag="$(git tag --sort=-v:refname | head -n1 || true)" + base_version="$(sanitize_semver "${latest_tag}")" + if [[ -z "${base_version}" ]]; then + base_version="0.1.0" + fi + version="${base_version}+${GITHUB_SHA::7}" fi - mkdir -p ./build-output - docker buildx build \ - --platform ${{ matrix.platform }} \ - --build-arg TARGET_ARCH=${{ matrix.arch }} \ - --build-arg DEBIAN_VERSION=${{ matrix.distro }} \ - --build-arg BUILD_TYPE=${BUILD_TYPE} \ - --build-arg RUN_TESTS=${RUN_TESTS} \ - --tag aasdk-build:${{ matrix.arch }} \ - --load \ - . - container_id=$(docker create aasdk-build:${{ matrix.arch }}) - docker cp ${container_id}:/output/. ./build-output/ - docker rm ${container_id} - echo "Build completed for ${{ matrix.arch }}" - ls -la ./build-output/ - - - name: Validate packages + echo "base_version=${base_version}" >> "${GITHUB_OUTPUT}" + echo "version=${version}" >> "${GITHUB_OUTPUT}" + + - name: Build and test in multiarch Docker container + env: + DISTRO_IMAGE: ${{ matrix.distro }} + DISTRO_ID: ${{ matrix.distro_id }} + PLATFORM: ${{ matrix.platform }} + ARCH_ID: ${{ matrix.arch_id }} + BUILD_VERSION: ${{ steps.version.outputs.version }} run: | - echo "Validating packages for ${{ matrix.arch }}..." - if [ ! "$(ls -A ./build-output/*.deb 2>/dev/null)" ]; then - echo "Error: No .deb packages found for ${{ matrix.arch }}" - exit 1 + set -euo pipefail + chmod +x ./build.sh + + docker run --rm \ + --platform "${PLATFORM}" \ + -e DEBIAN_FRONTEND=noninteractive \ + -e BUILD_VERSION="${BUILD_VERSION}" \ + -e DISTRO_ID="${DISTRO_ID}" \ + -e ARCH_ID="${ARCH_ID}" \ + -v "${PWD}:/work" \ + -w /work \ + "${DISTRO_IMAGE}" \ + bash -lc ' + set -euo pipefail + ./build.sh --install-deps + + BUILD_DIR="build-${DISTRO_ID}-${ARCH_ID}" \ + BUILD_TESTS=ON \ + BUILD_PACKAGE=ON \ + VERSION="${BUILD_VERSION}" \ + ./build.sh --clean + + workspace_owner="$(stat -c "%u:%g" /work)" + chown -R "${workspace_owner}" "build-${DISTRO_ID}-${ARCH_ID}" + ' + + - name: Install syft on runner + shell: bash + run: | + set -euo pipefail + if ! command -v syft >/dev/null 2>&1; then + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin fi - for package in ./build-output/*.deb; do - if [ -f "$package" ]; then - echo "Package: $(basename $package)" - dpkg-deb --info "$package" | head -20 - echo "---" - fi - done - - name: Generate version report + - name: Generate matrix SBOMs on runner + env: + DISTRO_ID: ${{ matrix.distro_id }} + ARCH_ID: ${{ matrix.arch_id }} run: | - out="deb-versions-${{ matrix.distro }}-${{ matrix.arch }}.md" - echo "# AASDK DEB Versions for ${{ matrix.distro }} / ${{ matrix.arch }}" > "$out" - echo "" >> "$out" - for package in ./build-output/*.deb; do - [ -f "$package" ] || continue - pkg=$(dpkg-deb --field "$package" Package) - ver=$(dpkg-deb --field "$package" Version) - arch=$(dpkg-deb --field "$package" Architecture) - echo "- $(basename "$package"): $pkg $ver ($arch)" >> "$out" - done - echo "Wrote $out" - - - name: Upload version report + set -euo pipefail + chmod +x ./build.sh + BUILD_DIR="build-${DISTRO_ID}-${ARCH_ID}" \ + BUILD_SBOM=ON \ + ./build.sh --sbom-only + + - name: Upload matrix build artifacts uses: actions/upload-artifact@v7 with: - name: "aasdk-deb-versions-${{ matrix.distro }}-${{ matrix.arch }}" - path: "deb-versions-${{ matrix.distro }}-${{ matrix.arch }}.md" - retention-days: 60 + name: full-${{ matrix.distro_id }}-${{ matrix.arch_id }}-artifacts + if-no-files-found: error + path: | + build-${{ matrix.distro_id }}-${{ matrix.arch_id }}/packages/*.deb + build-${{ matrix.distro_id }}-${{ matrix.arch_id }}/packages/*.tgz - - name: Upload build artifacts + - name: Upload matrix SBOM artifacts uses: actions/upload-artifact@v7 with: - name: "aasdk-packages-${{ matrix.distro }}-${{ matrix.arch }}" + name: full-${{ matrix.distro_id }}-${{ matrix.arch_id }}-sbom + if-no-files-found: error path: | - ./build-output/*.deb - ./build-output/*.tar.* - retention-days: 30 + build-${{ matrix.distro_id }}-${{ matrix.arch_id }}/sbom/*.spdx.json - test: - needs: build + release-notes: + name: Changelog and Release Notes + if: github.event_name == 'push' + needs: [quality-coverage-quick-build, full-multiarch-build-test] runs-on: ubuntu-latest - if: success() - steps: - - name: Checkout code - uses: actions/checkout@v6 - - - name: Download build artifacts - uses: actions/download-artifact@v6 + - name: Checkout + uses: actions/checkout@v5 with: - pattern: aasdk-packages-* - merge-multiple: true - path: ./test-packages + fetch-depth: 0 - - name: Test package installation + - name: Resolve and sanitize release version from git tags (SemVer) + id: version + shell: bash run: | - echo "Testing package installation..." - for package in ./test-packages/*amd64*.deb; do - if [ -f "$package" ]; then - echo "Testing installation of $(basename $package)" - dpkg-deb --contents "$package" | head -20 - dpkg-deb --field "$package" Depends - echo "Package $(basename $package) structure looks good" + set -euo pipefail + git fetch --tags --force + + sanitize_semver() { + local v="$1" + v="${v#v}" + + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)([-+][0-9A-Za-z.-]+)?$ ]]; then + echo "$v" + return 0 + fi + if [[ "$v" =~ ^([0-9]+)\.([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.${BASH_REMATCH[2]}.0" + return 0 + fi + if [[ "$v" =~ ^([0-9]+)$ ]]; then + echo "${BASH_REMATCH[1]}.0.0" + return 0 fi - done - - name: Generate test report + echo "0.1.0" + } + + if [[ "${GITHUB_REF}" == refs/tags/* ]]; then + base_version="$(sanitize_semver "${GITHUB_REF_NAME}")" + version="${base_version}" + else + latest_tag="$(git tag --sort=-v:refname | head -n1 || true)" + base_version="$(sanitize_semver "${latest_tag}")" + version="${base_version}+${GITHUB_SHA::7}" + fi + + echo "base_version=${base_version}" >> "${GITHUB_OUTPUT}" + echo "version=${version}" >> "${GITHUB_OUTPUT}" + + - name: Generate changelog and release notes + shell: bash run: | - echo "# AASDK Build Test Report" > test-report.md - echo "" >> test-report.md - echo "## Build Summary" >> test-report.md - echo "- Build Date: $(date -u)" >> test-report.md - echo "- Commit: ${{ github.sha }}" >> test-report.md - echo "- Branch: ${{ github.ref_name }}" >> test-report.md - echo "" >> test-report.md - echo "## Package Information" >> test-report.md - for package in ./test-packages/*.deb; do - if [ -f "$package" ]; then - echo "### $(basename $package)" >> test-report.md - echo '```' >> test-report.md - dpkg-deb --field "$package" Package Architecture Version Depends >> test-report.md - echo '```' >> test-report.md - echo "" >> test-report.md + set -euo pipefail + git fetch --tags --force + + release_version="${{ steps.version.outputs.version }}" + + latest_tag="$(git tag --sort=-v:refname | head -n1 || true)" + if [[ -n "${latest_tag}" ]]; then + range="${latest_tag}..HEAD" + else + range="HEAD" + fi + + { + echo "# Changelog ${release_version}" + echo + if [[ -n "${latest_tag}" ]]; then + echo "Version: ${release_version}" + echo "Changes since ${latest_tag}." + else + echo "Version: ${release_version}" + echo "Changes for initial release baseline." fi - done + echo + git log ${range} --pretty='- %h %s (%an)' + } > changelog.md + + { + echo "# Release Notes ${release_version}" + echo + echo "Version: ${release_version}" + echo + echo "## Highlights" + echo "- Automated build/test matrix across Debian Trixie and Ubuntu 24 for amd64/arm64/armhf" + echo "- DEB and TGZ artifact export" + echo "- Coverage and SBOM generation" + echo + echo "## Commit Summary" + git log ${range} --pretty='- %s' + } > release-notes.md - - name: Upload test report + - name: Download generated SBOM artifacts + uses: actions/download-artifact@v5 + with: + pattern: '*-sbom' + path: sbom-artifacts + + - name: Upload changelog and release notes uses: actions/upload-artifact@v7 with: - name: aasdk-test-report-${{ github.run_number }} - path: test-report.md - retention-days: 90 + name: release-metadata + path: | + changelog.md + release-notes.md + sbom-artifacts/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f4757494..9523d007 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,9 @@ cmake_minimum_required(VERSION 3.16) +if(POLICY CMP0167) + cmake_policy(SET CMP0167 NEW) +endif() + project(aasdk) message(STATUS "AASDK Library") message(STATUS "Cross Compiling?") @@ -7,6 +11,8 @@ message(STATUS "Cross Compiling?") # Options to skip building dependencies option(SKIP_BUILD_PROTOBUF "Skip building protobuf, use system-installed version" OFF) option(SKIP_BUILD_ABSL "Skip building Abseil, use system-installed version" OFF) +option(AASDK_TEST "Build AASDK unit tests" ON) +option(AASDK_CODE_COVERAGE "Enable coverage build options for AASDK tests" OFF) # Cross Compiling Architecture and Package Architecture Detection if( TARGET_ARCH STREQUAL "amd64" ) @@ -71,10 +77,38 @@ else() endif() endif() -# Set Compile Versions - Date-based semantic versioning -string(TIMESTAMP LIBRARY_BUILD_YEAR "%Y" UTC) # Major version = Year (e.g., 2025) -string(TIMESTAMP LIBRARY_BUILD_MONTH "%m" UTC) # Minor version = Month (01-12) -string(TIMESTAMP LIBRARY_BUILD_DAY "%d" UTC) # Patch version = Day (01-31) +# Resolve version override first (from -DAASDK_VERSION_OVERRIDE or env VERSION/BUILD_VERSION). +set(AASDK_VERSION_OVERRIDE "${AASDK_VERSION_OVERRIDE}" CACHE STRING "Override build/package version (SemVer)") +if(NOT AASDK_VERSION_OVERRIDE AND DEFINED ENV{VERSION} AND NOT "$ENV{VERSION}" STREQUAL "") + set(AASDK_VERSION_OVERRIDE "$ENV{VERSION}") +endif() +if(NOT AASDK_VERSION_OVERRIDE AND DEFINED ENV{BUILD_VERSION} AND NOT "$ENV{BUILD_VERSION}" STREQUAL "") + set(AASDK_VERSION_OVERRIDE "$ENV{BUILD_VERSION}") +endif() + +set(AASDK_HAS_VERSION_OVERRIDE OFF) +if(AASDK_VERSION_OVERRIDE) + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-+][0-9A-Za-z.-]+)?$" AASDK_VERSION_MATCH "${AASDK_VERSION_OVERRIDE}") + if(AASDK_VERSION_MATCH) + set(AASDK_HAS_VERSION_OVERRIDE ON) + set(LIBRARY_BUILD_MAJOR_RELEASE "${CMAKE_MATCH_1}") + set(LIBRARY_BUILD_MINOR_RELEASE "${CMAKE_MATCH_2}") + set(LIBRARY_BUILD_PATCH_RELEASE "${CMAKE_MATCH_3}") + set(AASDK_VERSION_SUFFIX "${CMAKE_MATCH_4}") + else() + message(WARNING "Ignoring invalid AASDK_VERSION_OVERRIDE='${AASDK_VERSION_OVERRIDE}'; expected SemVer x.y.z[-suffix|+metadata]") + endif() +endif() + +if(NOT AASDK_HAS_VERSION_OVERRIDE) + # Date-based semantic versioning fallback. + string(TIMESTAMP LIBRARY_BUILD_YEAR "%Y" UTC) + string(TIMESTAMP LIBRARY_BUILD_MONTH "%m" UTC) + string(TIMESTAMP LIBRARY_BUILD_DAY "%d" UTC) + set(LIBRARY_BUILD_MAJOR_RELEASE ${LIBRARY_BUILD_YEAR}) + set(LIBRARY_BUILD_MINOR_RELEASE ${LIBRARY_BUILD_MONTH}) + set(LIBRARY_BUILD_PATCH_RELEASE ${LIBRARY_BUILD_DAY}) +endif() # Set CMAKE_MODULE_PATH early so we can include gitversion.cmake set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake_modules/") @@ -97,10 +131,7 @@ if(NOT GIT_DESCRIBE OR GIT_DESCRIBE STREQUAL "") set(GIT_DESCRIBE "unknown") endif() -# Set version components -set(LIBRARY_BUILD_MAJOR_RELEASE ${LIBRARY_BUILD_YEAR}) -set(LIBRARY_BUILD_MINOR_RELEASE ${LIBRARY_BUILD_MONTH}) -set(LIBRARY_BUILD_PATCH_RELEASE ${LIBRARY_BUILD_DAY}) +set(AASDK_BASE_VERSION "${LIBRARY_BUILD_MAJOR_RELEASE}.${LIBRARY_BUILD_MINOR_RELEASE}.${LIBRARY_BUILD_PATCH_RELEASE}") # Cache find_program(CCACHE_PROGRAM ccache) @@ -119,7 +150,7 @@ message(STATUS "Configuring CMAKE") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_INIT} -fPIC -Wall -pedantic") +string(APPEND CMAKE_CXX_FLAGS " -fPIC -Wall -pedantic") set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") set(CMAKE_CXX_FLAGS_RELEASE "-g -O3 -DNDEBUG") @@ -291,19 +322,23 @@ if(ENABLE_JSON_LOGGING AND nlohmann_json_FOUND) endif() -set(LIBRARY_VERSION_STRING "${LIBRARY_BUILD_MAJOR_RELEASE}.${LIBRARY_BUILD_MINOR_RELEASE}.${LIBRARY_BUILD_PATCH_RELEASE}") +if(AASDK_HAS_VERSION_OVERRIDE) + set(LIBRARY_VERSION_STRING "${AASDK_VERSION_OVERRIDE}") +else() + set(LIBRARY_VERSION_STRING "${AASDK_BASE_VERSION}") -# Add git commit info to version if available -if(GIT_COMMIT_ID AND NOT GIT_COMMIT_ID STREQUAL "unknown") - set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}+git.${GIT_COMMIT_ID}") - if(GIT_DIRTY GREATER 0) - set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}.dirty") + # Add git commit info to version if available + if(GIT_COMMIT_ID AND NOT GIT_COMMIT_ID STREQUAL "unknown") + set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}+git.${GIT_COMMIT_ID}") + if(GIT_DIRTY GREATER 0) + set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}.dirty") + endif() endif() -endif() -# Add build type suffix for debug builds -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}.debug") + # Add build type suffix for debug builds + if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBRARY_VERSION_STRING "${LIBRARY_VERSION_STRING}.debug") + endif() endif() message(STATUS "Project Version: ${LIBRARY_VERSION_STRING}") @@ -454,7 +489,7 @@ endif() set(CPACK_PACKAGE_VENDOR "AASDK") set(CPACK_PACKAGE_CONTACT "OpenCarDev Team ") -set(CPACK_PACKAGE_VERSION ${LIBRARY_BUILD_MAJOR_RELEASE}.${LIBRARY_BUILD_MINOR_RELEASE}.${LIBRARY_BUILD_PATCH_RELEASE}) +set(CPACK_PACKAGE_VERSION ${AASDK_BASE_VERSION}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Android Auto SDK Library") set(CPACK_PACKAGE_DESCRIPTION "Android Auto SDK (AASDK) is a library for implementing Android Auto functionality in C++ applications.") set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/opencardev/aasdk") @@ -508,11 +543,11 @@ set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_SECTION "libdevel") set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_PRIORITY "optional") # Construct the full Debian package version including any CPACK release suffix if(DEFINED CPACK_DEBIAN_PACKAGE_RELEASE AND NOT "${CPACK_DEBIAN_PACKAGE_RELEASE}" STREQUAL "") - # Full version: - - set(_full_package_version "${LIBRARY_BUILD_MAJOR_RELEASE}.${LIBRARY_BUILD_MINOR_RELEASE}.${LIBRARY_BUILD_PATCH_RELEASE}-${CPACK_DEBIAN_PACKAGE_RELEASE}") + # Full version: - + set(_full_package_version "${AASDK_BASE_VERSION}-${CPACK_DEBIAN_PACKAGE_RELEASE}") else() - # Fallback to the simple date based version - set(_full_package_version "${LIBRARY_BUILD_MAJOR_RELEASE}.${LIBRARY_BUILD_MINOR_RELEASE}.${LIBRARY_BUILD_PATCH_RELEASE}") + # Fallback to the base semantic version + set(_full_package_version "${AASDK_BASE_VERSION}") endif() set(CPACK_DEBIAN_DEVELOPMENT_PACKAGE_DEPENDS "${CPACK_PACKAGE_NAME} (= ${_full_package_version})") diff --git a/build.sh b/build.sh old mode 100755 new mode 100644 index 2462a463..84540992 --- a/build.sh +++ b/build.sh @@ -1,594 +1,362 @@ -#!/bin/bash - -# AASDK Build Script -# Provides convenient building for different configurations and architectures -# -# Usage: -# ./build.sh [BUILD_TYPE] [OPTIONS] -# -# BUILD_TYPE: -# debug - Debug build with optimizations disabled -# release - Release build with optimizations enabled -# -# OPTIONS: -# clean - Clean build directory before building -# test - Run tests after building -# install - Install after building -# package - Create packages after building -# -# Environment Variables: -# TARGET_ARCH - Target architecture (amd64, arm64, armhf, i386) -# JOBS - Number of parallel build jobs (default: nproc-1) -# CMAKE_ARGS - Additional CMake arguments -# CROSS_COMPILE - Enable cross-compilation (true/false, default: true) -# DRY_RUN - If set to true/1, skip any system installation steps - -set -e # Exit on any error - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -NC='\033[0m' # No Color - -# Default values -# Auto-detect build type based on git branch if not specified -if [ -z "$1" ]; then - CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") - if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then - BUILD_TYPE="release" - else - BUILD_TYPE="debug" - fi -else - BUILD_TYPE="$1" -fi -TARGET_ARCH=${TARGET_ARCH:-amd64} -# Use one fewer core by default to reduce memory pressure on small devices -NPROC=$(nproc 2>/dev/null || echo 1) -if [ "$NPROC" -gt 1 ]; then - JOBS_DEFAULT=$((NPROC-1)) -else - JOBS_DEFAULT=1 -fi -JOBS=${JOBS:-$JOBS_DEFAULT} -CMAKE_ARGS=${CMAKE_ARGS:-} -CROSS_COMPILE=${CROSS_COMPILE:-true} -# Dry run mode (skip system install) -DRY_RUN=${DRY_RUN:-false} - -# Parse command line arguments -CLEAN=false -RUN_TESTS=false -INSTALL=false -CREATE_PACKAGES=false -SKIP_PROTOBUF=false -SKIP_ABSL=false +#!/usr/bin/env bash +set -euo pipefail + +BUILD_TYPE="${BUILD_TYPE:-Release}" +BUILD_TESTS="${BUILD_TESTS:-ON}" +BUILD_PACKAGE="${BUILD_PACKAGE:-OFF}" +BUILD_DIR="${BUILD_DIR:-}" +SOURCE_DIR="${SOURCE_DIR:-.}" +JOBS="${JOBS:-$(nproc)}" +CLEAN="${CLEAN:-OFF}" +INSTALL_DEPS="${INSTALL_DEPS:-OFF}" +CODE_QUALITY="${CODE_QUALITY:-OFF}" +FORMAT_CHECK="${FORMAT_CHECK:-OFF}" +ENABLE_COVERAGE="${ENABLE_COVERAGE:-OFF}" +BUILD_SBOM="${BUILD_SBOM:-OFF}" +SBOM_ONLY="${SBOM_ONLY:-OFF}" +SBOM_OUTPUT_DIR="${SBOM_OUTPUT_DIR:-}" +CMAKE_EXTRA_ARGS="${CMAKE_EXTRA_ARGS:-}" +VERSION="${VERSION:-${BUILD_VERSION:-}}" +SKIP_BUILD_PROTOBUF="${SKIP_BUILD_PROTOBUF:-OFF}" +SKIP_BUILD_ABSL="${SKIP_BUILD_ABSL:-OFF}" +INSTALL_AFTER_BUILD="${INSTALL_AFTER_BUILD:-OFF}" for arg in "$@"; do - case $arg in - debug|release) - BUILD_TYPE=$arg - ;; - clean) - CLEAN=true - ;; - test) - RUN_TESTS=true - ;; - install) - INSTALL=true - ;; - package) - CREATE_PACKAGES=true - ;; - dryrun) - DRY_RUN=true - ;; - --skip-protobuf) - SKIP_PROTOBUF=true - ;; - --skip-absl) - SKIP_ABSL=true - ;; - *) - # Unknown option - ;; - esac + case "$arg" in + debug) + BUILD_TYPE="Debug" + ;; + release) + BUILD_TYPE="Release" + ;; + --clean|clean) + CLEAN="ON" + ;; + --install-deps) + INSTALL_DEPS="ON" + ;; + --code-quality) + CODE_QUALITY="ON" + ;; + --format-check) + FORMAT_CHECK="ON" + ;; + --sbom) + BUILD_SBOM="ON" + ;; + --sbom-only) + BUILD_SBOM="ON" + SBOM_ONLY="ON" + ;; + --skip-protobuf) + SKIP_BUILD_PROTOBUF="ON" + ;; + --skip-absl) + SKIP_BUILD_ABSL="ON" + ;; + test) + BUILD_TESTS="ON" + ;; + package) + BUILD_PACKAGE="ON" + ;; + install) + INSTALL_AFTER_BUILD="ON" + ;; + esac done -# Add skip options to CMake args after parsing arguments -if [ "$SKIP_PROTOBUF" = true ]; then - CMAKE_ARGS="$CMAKE_ARGS -DSKIP_BUILD_PROTOBUF=ON" -fi -if [ "$SKIP_ABSL" = true ]; then - CMAKE_ARGS="$CMAKE_ARGS -DSKIP_BUILD_ABSL=ON" +# Keep derived defaults coherent after parsing args. +if [[ -z "${BUILD_DIR}" ]]; then + BUILD_DIR="build-${BUILD_TYPE,,}" fi -# Functions -print_header() { - echo -e "${BLUE}================================================${NC}" - echo -e "${BLUE} AASDK Build Script${NC}" - echo -e "${BLUE}================================================${NC}" - echo -e "Build Type: ${GREEN}${BUILD_TYPE}${NC}" - echo -e "Architecture: ${GREEN}${TARGET_ARCH}${NC}" - echo -e "Parallel Jobs: ${GREEN}${JOBS}${NC}" - echo -e "Clean Build: ${GREEN}${CLEAN}${NC}" - echo -e "Run Tests: ${GREEN}${RUN_TESTS}${NC}" - echo -e "Install: ${GREEN}${INSTALL}${NC}" - echo -e "Create Packages: ${GREEN}${CREATE_PACKAGES}${NC}" - echo -e "Dry Run: ${GREEN}${DRY_RUN}${NC}" - echo -e "Skip Protobuf: ${GREEN}${SKIP_PROTOBUF}${NC}" - echo -e "Skip Abseil: ${GREEN}${SKIP_ABSL}${NC}" - echo -e "${YELLOW}Git details:${NC}" - echo " GIT_COMMIT_ID: $GIT_COMMIT_ID" - echo " GIT_BRANCH: $GIT_BRANCH" - echo " GIT_DESCRIBE: $GIT_DESCRIBE" - echo " GIT_TIMESTAMP: $GIT_COMMIT_TIMESTAMP" - echo " GIT_DIRTY: $GIT_DIRTY" - echo -e "${BLUE}================================================${NC}" - echo +log() { + printf '[build.sh] %s\n' "$*" } -print_step() { - echo -e "${YELLOW}🔄 $1${NC}" -} +install_deps() { + local script_dir + script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + local deps_dir="${script_dir}/deps" -print_success() { - echo -e "${GREEN}✅ $1${NC}" -} + local distro="unknown" + if [[ -f /etc/os-release ]]; then + local os_id="" os_codename="" os_version_id="" + os_id="$(. /etc/os-release && echo "${ID:-}")" + os_codename="$(. /etc/os-release && echo "${VERSION_CODENAME:-}")" + os_version_id="$(. /etc/os-release && echo "${VERSION_ID:-}")" -print_error() { - echo -e "${RED}❌ $1${NC}" -} + case "${os_id}:${os_codename}" in + ubuntu:noble) distro="ubuntu24" ;; + debian:trixie) distro="trixie" ;; + *) + case "${os_id}:${os_version_id}" in + ubuntu:24.04) distro="ubuntu24" ;; + debian:13) distro="trixie" ;; + esac + ;; + esac + fi -check_dependencies() { - print_step "Checking dependencies..." - - # Check for required tools - local missing_deps=() - - if ! command -v cmake &> /dev/null; then - missing_deps+=("cmake") - fi - - if ! command -v make &> /dev/null; then - missing_deps+=("build-essential") - fi - - if ! command -v pkg-config &> /dev/null; then - missing_deps+=("pkg-config") - fi - - # Check for required libraries - if ! pkg-config --exists protobuf; then - missing_deps+=("libprotobuf-dev protobuf-compiler") - fi - - if ! ldconfig -p | grep -q libboost_system; then - missing_deps+=("libboost-all-dev") - fi - - if ! ldconfig -p | grep -q libusb-1.0; then - missing_deps+=("libusb-1.0-0-dev") - fi - - if ! ldconfig -p | grep -q libssl; then - missing_deps+=("libssl-dev") - fi - - # Check for absl only if not skipping protobuf (system protobuf v3.21.12 doesn't require absl) - if [ "$SKIP_PROTOBUF" != true ] && ! pkg-config --exists absl_base; then - missing_deps+=("libabsl-dev") - fi - - if [ ${#missing_deps[@]} -ne 0 ]; then - print_error "Missing dependencies detected:" - printf '%s\n' "${missing_deps[@]}" - echo - echo -e "${YELLOW}To install missing dependencies on Ubuntu/Debian:${NC}" - echo "sudo apt update && sudo apt install -y ${missing_deps[*]}" - echo - echo -e "${YELLOW}Or use the DevContainer for automatic dependency management.${NC}" - exit 1 - fi - - print_success "All dependencies found" -} + if [[ "${distro}" == "unknown" ]]; then + log "WARNING: Unrecognised OS/distro - skipping dependency install" + return 0 + fi -setup_native_compilation() { - print_step "Setting up native compilation for ${TARGET_ARCH}..." - - # Force native compilers - export CC=/usr/bin/cc - export CXX=/usr/bin/c++ - export CMAKE_C_COMPILER=/usr/bin/cc - export CMAKE_CXX_COMPILER=/usr/bin/c++ - - # Add compiler settings to CMAKE_ARGS - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_C_COMPILER=/usr/bin/cc" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_CXX_COMPILER=/usr/bin/c++" - - # Architecture-specific library paths for dependency detection - local multiarch_path - case $TARGET_ARCH in - amd64) - multiarch_path="x86_64-linux-gnu" - ;; - arm64) - multiarch_path="aarch64-linux-gnu" - ;; - armhf) - multiarch_path="arm-linux-gnueabihf" - ;; - i386) - multiarch_path="i386-linux-gnu" - ;; - *) - print_error "Unsupported architecture: $TARGET_ARCH" - echo "Supported architectures: amd64, arm64, armhf, i386" - exit 1 - ;; - esac - - # Add dependency paths to CMAKE_ARGS for common libraries - CMAKE_ARGS="$CMAKE_ARGS -DProtobuf_INCLUDE_DIR=/usr/include" - CMAKE_ARGS="$CMAKE_ARGS -DProtobuf_LIBRARIES=/usr/lib/${multiarch_path}/libprotobuf.so" - CMAKE_ARGS="$CMAKE_ARGS -DProtobuf_LIBRARY=/usr/lib/${multiarch_path}/libprotobuf.so" - CMAKE_ARGS="$CMAKE_ARGS -DProtobuf_LITE_LIBRARY=/usr/lib/${multiarch_path}/libprotobuf-lite.so" - CMAKE_ARGS="$CMAKE_ARGS -DProtobuf_PROTOC_EXECUTABLE=/usr/bin/protoc" - CMAKE_ARGS="$CMAKE_ARGS -DLIBUSB_1_INCLUDE_DIRS=/usr/include/libusb-1.0" - CMAKE_ARGS="$CMAKE_ARGS -DLIBUSB_1_LIBRARIES=/usr/lib/${multiarch_path}/libusb-1.0.so" - CMAKE_ARGS="$CMAKE_ARGS -DOPENSSL_INCLUDE_DIR=/usr/include/openssl" - CMAKE_ARGS="$CMAKE_ARGS -DOPENSSL_CRYPTO_LIBRARY=/usr/lib/${multiarch_path}/libcrypto.so" - CMAKE_ARGS="$CMAKE_ARGS -DOPENSSL_SSL_LIBRARY=/usr/lib/${multiarch_path}/libssl.so" - - print_success "Native compilation configured for ${TARGET_ARCH}" -} + local pkg_file="${deps_dir}/packages-${distro}.txt" + if [[ ! -f "${pkg_file}" ]]; then + log "ERROR: Package list not found: ${pkg_file}" + exit 1 + fi -setup_cross_compilation() { - if [ "$TARGET_ARCH" != "amd64" ] && [ "$CROSS_COMPILE" = "true" ]; then - print_step "Setting up cross-compilation for ${TARGET_ARCH}..." - - case $TARGET_ARCH in - arm64) - export CMAKE_C_COMPILER=aarch64-linux-gnu-gcc - export CMAKE_CXX_COMPILER=aarch64-linux-gnu-g++ - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH=/usr/aarch64-linux-gnu" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY" - - if ! command -v aarch64-linux-gnu-gcc &> /dev/null; then - print_error "ARM64 cross-compiler not found" - echo "Install with: sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu" - exit 1 - fi - ;; - armhf) - export CMAKE_C_COMPILER=arm-linux-gnueabihf-gcc - export CMAKE_CXX_COMPILER=arm-linux-gnueabihf-g++ - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH=/usr/arm-linux-gnueabihf" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_PROGRAM=NEVER" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY=ONLY" - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE=ONLY" - - if ! command -v arm-linux-gnueabihf-gcc &> /dev/null; then - print_error "ARMHF cross-compiler not found" - echo "Install with: sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf" - exit 1 - fi - ;; - i386) - CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_C_FLAGS=-m32 -DCMAKE_CXX_FLAGS=-m32" - ;; - *) - print_error "Unsupported architecture: $TARGET_ARCH" - echo "Supported architectures: amd64, arm64, armhf, i386" - exit 1 - ;; - esac - - print_success "Cross-compilation configured for ${TARGET_ARCH}" - elif [ "$CROSS_COMPILE" = "false" ]; then - setup_native_compilation - fi -} + read_pkgs() { + local file="$1" + while IFS= read -r line || [[ -n "${line}" ]]; do + line="${line%%#*}" + line="${line#"${line%%[![:space:]]*}"}" + line="${line%"${line##*[![:space:]]}"}" + [[ -n "${line}" ]] && printf '%s\n' "${line}" + done < "${file}" + } -build_protobuf() { - if [ ! -d "protobuf/build" ] || [ "$CLEAN" = true ]; then - print_step "Building AAP Protobuf dependency..." - - if [ "$CLEAN" = true ] && [ -d "protobuf/build" ]; then - rm -rf protobuf/build - fi - - mkdir -p protobuf/build - cd protobuf/build - # Stage installs under the project to avoid requiring root - STAGING_DIR="$(pwd)/_staging" - mkdir -p "$STAGING_DIR" - - cmake -DCMAKE_BUILD_TYPE=Release \ - -DTARGET_ARCH=$TARGET_ARCH \ - -DCMAKE_INSTALL_PREFIX="/usr/local" \ - $CMAKE_ARGS \ - .. - - make -j$JOBS - # Install to a local staging dir so no sudo is required - make install DESTDIR="$STAGING_DIR" - - # Ensure main build can discover the staged install if it uses find_package - export CMAKE_PREFIX_PATH="$STAGING_DIR/usr/local:${CMAKE_PREFIX_PATH}" - cd ../.. - - print_success "AAP Protobuf built successfully" - else - print_step "AAP Protobuf already built, skipping..." - fi -} + local packages=() + while IFS= read -r pkg; do + packages+=("${pkg}") + done < <(read_pkgs "${pkg_file}") -configure_cmake() { - print_step "Configuring CMake..." - - local build_dir="build-${BUILD_TYPE}" - if [ "$TARGET_ARCH" != "amd64" ]; then - build_dir="build-${BUILD_TYPE}-${TARGET_ARCH}" - fi - - if [ "$CLEAN" = true ] && [ -d "$build_dir" ]; then - print_step "Cleaning build directory..." - rm -rf "$build_dir" - fi - - mkdir -p "$build_dir" - cd "$build_dir" - - # Convert build type to proper case - local cmake_build_type - case $BUILD_TYPE in - debug) - cmake_build_type="Debug" - ;; - release) - cmake_build_type="Release" - ;; - *) - cmake_build_type="Release" - ;; - esac - - cmake -DCMAKE_BUILD_TYPE=$cmake_build_type \ - -DTARGET_ARCH=$TARGET_ARCH \ - -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ - -DBUILD_TESTING=ON \ - $CMAKE_ARGS \ - .. - - cd .. - export BUILD_DIR="$build_dir" - - print_success "CMake configured successfully" -} + if [[ "${CODE_QUALITY}" == "ON" ]] && [[ -f "${deps_dir}/packages-quality.txt" ]]; then + while IFS= read -r pkg; do + packages+=("${pkg}") + done < <(read_pkgs "${deps_dir}/packages-quality.txt") + fi -build_project() { - print_step "Building AASDK..." - - cd "$BUILD_DIR" - - # Build with progress indicator - if [ -t 1 ]; then - # Terminal output - show progress - make -j$JOBS - else - # Non-terminal output - suppress progress for cleaner logs - make -j$JOBS --no-print-directory - fi - - cd .. - - print_success "AASDK built successfully" -} + if [[ "${ENABLE_COVERAGE}" == "ON" ]] && [[ -f "${deps_dir}/packages-coverage.txt" ]]; then + while IFS= read -r pkg; do + packages+=("${pkg}") + done < <(read_pkgs "${deps_dir}/packages-coverage.txt") + fi -run_tests() { - if [ "$RUN_TESTS" = true ]; then - print_step "Running tests..." - - cd "$BUILD_DIR" - - if ! ctest --output-on-failure --parallel $JOBS; then - print_error "Some tests failed" - cd .. - exit 1 - fi - - cd .. - - print_success "All tests passed" - fi -} + if [[ "${BUILD_SBOM}" == "ON" ]] && [[ -f "${deps_dir}/packages-sbom.txt" ]]; then + while IFS= read -r pkg; do + packages+=("${pkg}") + done < <(read_pkgs "${deps_dir}/packages-sbom.txt") + fi -install_project() { - if [ "$INSTALL" = true ]; then - if [ "$DRY_RUN" = true ] || [ "$DRY_RUN" = 1 ]; then - print_step "Dry run enabled: skipping system installation" - return 0 - fi - print_step "Installing AASDK..." - - cd "$BUILD_DIR" - - if [ "$EUID" -eq 0 ]; then - make install + log "Installing ${#packages[@]} packages for ${distro}" + + local apt_get="apt-get" + [[ "$(id -u)" -ne 0 ]] && apt_get="sudo apt-get" + + ${apt_get} update -qq + DEBIAN_FRONTEND=noninteractive ${apt_get} install -y --no-install-recommends "${packages[@]}" + + if [[ "${BUILD_SBOM}" == "ON" ]] && ! command -v syft >/dev/null 2>&1; then + local machine + machine="$(uname -m)" + case "${machine}" in + x86_64|amd64|aarch64|arm64) + log "syft not found after package install; installing via official installer" + local install_cmd='curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin' + if [[ "$(id -u)" -eq 0 ]]; then + bash -lc "${install_cmd}" + elif command -v sudo >/dev/null 2>&1; then + sudo bash -lc "${install_cmd}" else - sudo make install - sudo ldconfig + log "ERROR: syft installation requires root or sudo" + exit 1 fi - - cd .. - - print_success "AASDK installed successfully" - fi + ;; + *) + log "syft auto-install unsupported on architecture ${machine}; generate SBOMs on a host runner instead" + ;; + esac + fi } -create_packages() { - if [ "$CREATE_PACKAGES" = true ]; then - print_step "Creating packages..." - - cd "$BUILD_DIR" - - # Create DEB packages - cpack --config CPackConfig.cmake - - # Move packages to top-level packages directory - mkdir -p ../packages - mv *.deb ../packages/ 2>/dev/null || true - mv *.tar.* ../packages/ 2>/dev/null || true - - cd .. - - print_success "Packages created in packages/ directory" - - # List created packages - if [ -d "packages" ]; then - echo -e "${BLUE}Created packages:${NC}" - ls -la packages/ - fi - fi -} +generate_sboms() { + if ! command -v syft >/dev/null 2>&1; then + log "ERROR: BUILD_SBOM=ON but syft is not installed" + exit 1 + fi -validate_build() { - print_step "Validating build..." - - local lib_file="$BUILD_DIR/lib/libaasdk.so" - - if [ ! -f "$lib_file" ]; then - print_error "Library file not found: $lib_file" - exit 1 - fi - - # Check if library has expected symbols - if ! nm "$lib_file" | grep -q "aasdk"; then - print_error "Library does not contain expected AASDK symbols" - exit 1 - fi - - # Check library dependencies (only for native builds) - if [ "$TARGET_ARCH" = "amd64" ]; then - if ! ldd "$lib_file" > /dev/null 2>&1; then - print_error "Library has unresolved dependencies" - exit 1 - fi - fi - - print_success "Build validation passed" -} + local sbom_dir + if [[ -n "${SBOM_OUTPUT_DIR}" ]]; then + sbom_dir="${SBOM_OUTPUT_DIR}" + else + sbom_dir="${BUILD_DIR}/sbom" + fi + mkdir -p "${sbom_dir}" -show_build_summary() { - echo - echo -e "${BLUE}================================================${NC}" - echo -e "${GREEN}🎉 AASDK Build Completed Successfully!${NC}" - echo -e "${BLUE}================================================${NC}" - echo -e "Build Type: ${GREEN}${BUILD_TYPE}${NC}" - echo -e "Architecture: ${GREEN}${TARGET_ARCH}${NC}" - echo -e "Build Directory: ${GREEN}${BUILD_DIR}${NC}" - echo - echo -e "${BLUE}Build artifacts:${NC}" - echo -e " Library: ${BUILD_DIR}/lib/libaasdk.so" - echo -e " Headers: ${BUILD_DIR}/include/" - echo -e " CMake Config: ${BUILD_DIR}/aasdkConfig.cmake" - echo - if [ "$RUN_TESTS" = true ]; then - echo -e "${GREEN}✅ Tests: PASSED${NC}" - fi - if [ "$INSTALL" = true ]; then - echo -e "${GREEN}✅ Installation: COMPLETED${NC}" - fi - if [ "$CREATE_PACKAGES" = true ]; then - echo -e "${GREEN}✅ Packages: CREATED${NC}" - fi - echo - echo -e "${YELLOW}Next steps:${NC}" - echo -e " • To run tests: cd ${BUILD_DIR} && ctest" - echo -e " • To install: cd ${BUILD_DIR} && sudo make install" - echo -e " • To create packages: cd ${BUILD_DIR} && cpack" - echo -e " • For troubleshooting: see TROUBLESHOOTING.md" - echo -e "${BLUE}================================================${NC}" -} + log "Generating source SBOM" + syft "dir:${SOURCE_DIR}" -o "spdx-json=${sbom_dir}/source.spdx.json" + + log "Generating package SBOM(s)" + shopt -s nullglob + local pkg + local has_pkg="false" + for pkg in "${BUILD_DIR}/packages"/*.deb "${BUILD_DIR}/packages"/*.tgz; do + has_pkg="true" + local base + base="$(basename "${pkg}")" + syft "file:${pkg}" -o "spdx-json=${sbom_dir}/package-${base}.spdx.json" + done + shopt -u nullglob -show_usage() { - echo "AASDK Build Script" - echo - echo "Usage: $0 [BUILD_TYPE] [OPTIONS]" - echo - echo "BUILD_TYPE:" - echo " debug Debug build with optimizations disabled (default)" - echo " release Release build with optimizations enabled" - echo - echo "OPTIONS:" - echo " clean Clean build directory before building" - echo " test Run tests after building" - echo " install Install after building" - echo " package Create packages after building" - echo " --skip-protobuf Skip building protobuf, use system-installed version" - echo " --skip-absl Skip building Abseil, use system-installed version" - echo - echo "Environment Variables:" - echo " TARGET_ARCH Target architecture (amd64, arm64, armhf, i386)" - echo " JOBS Number of parallel build jobs (default: nproc-1)" - echo " CMAKE_ARGS Additional CMake arguments" - echo " CROSS_COMPILE Enable cross-compilation (true/false, default: true)" - echo - echo "Examples:" - echo " $0 debug # Debug build" - echo " $0 release clean # Clean release build" - echo " $0 debug test # Debug build with tests" - echo " $0 debug --skip-protobuf # Debug build using system protobuf" - echo " $0 release --skip-absl # Release build using system Abseil" - echo " TARGET_ARCH=arm64 $0 release # Cross-compile for ARM64" - echo " JOBS=4 $0 debug clean # Build with 4 parallel jobs" - echo - echo "Backward Compatibility:" - echo " This version includes API changes from AASDK v4.x. For migration help," - echo " see include/aasdk/BackwardCompatibility.hpp and the migration guide." - echo - echo "For complete documentation, see BUILD.md" + if [[ "${has_pkg}" != "true" ]]; then + log "ERROR: BUILD_SBOM=ON but no package artifacts were found in ${BUILD_DIR}/packages" + exit 1 + fi + + log "SBOM output written to ${sbom_dir}" } -# Main execution -main() { - # Check for help - if [ "$1" = "-h" ] || [ "$1" = "--help" ] || [ "$1" = "help" ]; then - show_usage - exit 0 +if [[ "${INSTALL_DEPS}" == "ON" ]]; then + install_deps + log "Dependency installation complete (--install-deps); exiting without build" + exit 0 +fi + +if [[ "${SBOM_ONLY}" == "ON" ]]; then + generate_sboms + log "SBOM generation complete (--sbom-only); exiting without build" + exit 0 +fi + +if [[ "${CLEAN}" == "ON" ]]; then + log "Cleaning build directory ${BUILD_DIR}" + rm -rf "${BUILD_DIR}" +fi + +if [[ "${FORMAT_CHECK}" == "ON" ]]; then + CODE_QUALITY="ON" +fi + +cmake_args=( + -DCMAKE_BUILD_TYPE="${BUILD_TYPE}" + -DAASDK_TEST="${BUILD_TESTS}" +) + +# Pass architecture from CI env (ARCH_ID) or TARGET_ARCH to CMake +_target_arch="${TARGET_ARCH:-${ARCH_ID:-}}" +if [[ -n "${_target_arch}" ]]; then + cmake_args+=("-DTARGET_ARCH=${_target_arch}") +fi + +# Pass distro info from CI env so DebPackageFilename works inside Docker +# (lsb_release is often absent in slim images) +if [[ -n "${DISTRO_ID:-}" ]]; then + case "${DISTRO_ID}" in + ubuntu24) + export DISTRO_DEB_SUITE="noble" + export DISTRO_DEB_VERSION="ubuntu24.04" + export DISTRO_DEB_RELEASE="ubuntu24.04" + ;; + trixie) + export DISTRO_DEB_SUITE="trixie" + export DISTRO_DEB_VERSION="deb13" + export DISTRO_DEB_RELEASE="deb13" + ;; + esac +fi + +if [[ "${SKIP_BUILD_PROTOBUF}" == "ON" ]]; then + cmake_args+=("-DSKIP_BUILD_PROTOBUF=ON") +fi + +if [[ "${SKIP_BUILD_ABSL}" == "ON" ]]; then + cmake_args+=("-DSKIP_BUILD_ABSL=ON") +fi + +if [[ "${ENABLE_COVERAGE}" == "ON" ]]; then + cmake_args+=("-DCMAKE_CXX_FLAGS=--coverage" "-DCMAKE_C_FLAGS=--coverage") +fi + +if [[ -n "${VERSION}" ]]; then + cmake_args+=("-DAASDK_VERSION_OVERRIDE=${VERSION}") +fi + +if [[ -n "${CMAKE_EXTRA_ARGS}" ]]; then + # shellcheck disable=SC2206 + extra_args=( ${CMAKE_EXTRA_ARGS} ) + cmake_args+=("${extra_args[@]}") +fi + +log "Configuring (${BUILD_TYPE}) from ${SOURCE_DIR} into ${BUILD_DIR}" +cmake -S "${SOURCE_DIR}" -B "${BUILD_DIR}" -G Ninja "${cmake_args[@]}" + +if [[ "${CODE_QUALITY}" == "ON" ]]; then + if command -v cppcheck >/dev/null 2>&1; then + log "Running cppcheck" + mapfile -t cppcheck_files < <(find src include protobuf \ + -type f \( -name '*.cpp' -o -name '*.cc' -o -name '*.c' -o -name '*.hpp' -o -name '*.h' \) \ + ! -name '*.ut.cpp' \ + ! -path '*/unit_test/*') + + if [[ "${#cppcheck_files[@]}" -eq 0 ]]; then + log "No source files found for cppcheck; skipping static analysis" + else + cppcheck \ + --enable=warning,performance,portability,style \ + --error-exitcode=1 \ + --suppress=unusedStructMember \ + --suppress=noExplicitConstructor \ + --inline-suppr \ + --language=c++ \ + --std=c++17 \ + --quiet \ + "${cppcheck_files[@]}" fi - - # Validate build type - if [ "$BUILD_TYPE" != "debug" ] && [ "$BUILD_TYPE" != "release" ]; then - print_error "Invalid build type: $BUILD_TYPE" - echo "Valid build types: debug, release" - exit 1 + else + log "cppcheck not installed, skipping static analysis" + fi + + if cmake --build "${BUILD_DIR}" --target help | grep -q "clang-format"; then + log "Running clang-format target" + cmake --build "${BUILD_DIR}" --target clang-format + else + log "clang-format target unavailable, skipping format step" + fi + + if [[ "${FORMAT_CHECK}" == "ON" ]]; then + log "Checking formatting diff" + if ! git diff --exit-code -- '*.cpp' '*.cc' '*.c' '*.h' '*.hpp'; then + log "Formatting check failed; run clang-format and commit changes" + exit 1 fi - - print_header - - # Build process - check_dependencies - setup_cross_compilation - # NOTE: aap_protobuf is built via add_subdirectory(protobuf) inside the main CMake build. - # Prebuilding and installing it separately is unnecessary and can require elevated privileges. - # The previous step has been disabled to keep dry runs Pi-safe and rootless. - configure_cmake - build_project - validate_build - run_tests - install_project - create_packages - - show_build_summary -} + fi +fi + +log "Building" +cmake --build "${BUILD_DIR}" --parallel "${JOBS}" + +if [[ "${BUILD_TESTS}" == "ON" ]]; then + log "Running tests" + ctest --test-dir "${BUILD_DIR}" --output-on-failure +fi + +if [[ "${BUILD_PACKAGE}" == "ON" ]]; then + log "Packaging" + cpack --config "${BUILD_DIR}/CPackConfig.cmake" -B "${BUILD_DIR}/packages" +fi + +if [[ "${INSTALL_AFTER_BUILD}" == "ON" ]]; then + log "Installing" + if [[ "$(id -u)" -eq 0 ]]; then + cmake --install "${BUILD_DIR}" + ldconfig || true + else + sudo cmake --install "${BUILD_DIR}" + sudo ldconfig || true + fi +fi + +if [[ "${BUILD_SBOM}" == "ON" ]]; then + if [[ "${BUILD_PACKAGE}" != "ON" ]]; then + log "ERROR: BUILD_SBOM=ON requires BUILD_PACKAGE=ON" + exit 1 + fi + generate_sboms +fi -# Execute main function -main "$@" +log "Done" \ No newline at end of file diff --git a/cmake_modules/DebPackageFilename.cmake b/cmake_modules/DebPackageFilename.cmake index 5325c5e2..72f59041 100644 --- a/cmake_modules/DebPackageFilename.cmake +++ b/cmake_modules/DebPackageFilename.cmake @@ -52,37 +52,55 @@ function(detect_deb_suite OUT_SUITE) message(STATUS "detect_deb_suite") set(DETECTED_SUITE "unknown") + # 1. Check environment variable override if(DEFINED ENV{DISTRO_DEB_SUITE} AND NOT "$ENV{DISTRO_DEB_SUITE}" STREQUAL "") - message(STATUS "DISTRO_DEB_SUITE: ${DISTRO_DEB_SUITE}") + message(STATUS "Using DISTRO_DEB_SUITE: $ENV{DISTRO_DEB_SUITE}") set(DETECTED_SUITE "$ENV{DISTRO_DEB_SUITE}") - elseif(DEFINED CPACK_DEBIAN_PACKAGE_RELEASE AND NOT "${CPACK_DEBIAN_PACKAGE_RELEASE}" STREQUAL "") - if(CMAKE_SYSTEM_NAME MATCHES "Linux") - get_linux_lsb_release_information() - message(STATUS "Linux ${LSB_RELEASE_ID_SHORT} ${LSB_RELEASE_VERSION_SHORT} ${LSB_RELEASE_CODENAME_SHORT}") - set(DETECTED_SUITE "${LSB_RELEASE_CODENAME_SHORT}") + # 2. Try to detect from lsb_release directly + elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + find_program(LSB_RELEASE_EXEC lsb_release) + if(LSB_RELEASE_EXEC) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --codename OUTPUT_VARIABLE LSB_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + if(LSB_CODENAME AND NOT LSB_CODENAME STREQUAL "") + set(DETECTED_SUITE "${LSB_CODENAME}") + message(STATUS "Detected suite from lsb_release: ${LSB_CODENAME}") + endif() endif() endif() + message(STATUS "Detected Suite: ${DETECTED_SUITE}") set(${OUT_SUITE} "${DETECTED_SUITE}" PARENT_SCOPE) endfunction() -# Detect debian version for filename (e.g. deb13, deb12) +# Detect debian version for filename (e.g. deb13, deb12, ubuntu24.04) function(detect_deb_version OUT_VERSION) message(STATUS "detect_deb_version") set(DETECTED_VERSION "unknown") - if(DEFINED CPACK_DEBIAN_PACKAGE_RELEASE AND NOT "${CPACK_DEBIAN_PACKAGE_RELEASE}" STREQUAL "") - message(STATUS "CPACK_DEBIAN_PACKAGE_RELEASE: ${CPACK_DEBIAN_PACKAGE_RELEASE}") - if(CPACK_DEBIAN_PACKAGE_RELEASE MATCHES "deb([0-9]+)") - set(DETECTED_VERSION "deb${CMAKE_MATCH_1}") - elseif(CPACK_DEBIAN_PACKAGE_RELEASE MATCHES "0ubuntu1~([0-9]+\.[0-9]+)") - set(DETECTED_VERSION "ubuntu${CMAKE_MATCH_1}") - elseif(CPACK_DEBIAN_PACKAGE_RELEASE MATCHES "rpi([0-9]+)") - set(DETECTED_VERSION "rpi${CMAKE_MATCH_1}") - else() - set(DETECTED_VERSION "unknown") + # Try environment variable first + if(DEFINED ENV{DISTRO_DEB_VERSION} AND NOT "$ENV{DISTRO_DEB_VERSION}" STREQUAL "") + set(DETECTED_VERSION "$ENV{DISTRO_DEB_VERSION}") + # Try to detect from lsb_release + elseif(CMAKE_SYSTEM_NAME MATCHES "Linux") + find_program(LSB_RELEASE_EXEC lsb_release) + if(LSB_RELEASE_EXEC) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_ID OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + + if(LSB_ID AND LSB_RELEASE) + if(LSB_ID STREQUAL "Ubuntu") + # Ubuntu format: ubuntu24.04 + set(DETECTED_VERSION "ubuntu${LSB_RELEASE}") + message(STATUS "Detected Ubuntu version: ${DETECTED_VERSION}") + elseif(LSB_RELEASE MATCHES "^([0-9]+)") + # Debian format: deb13, deb12, etc. + set(DETECTED_VERSION "deb${CMAKE_MATCH_1}") + message(STATUS "Detected Debian version: ${DETECTED_VERSION}") + endif() + endif() endif() endif() + message(STATUS "DETECTED_VERSION: ${DETECTED_VERSION}") set(${OUT_VERSION} "${DETECTED_VERSION}" PARENT_SCOPE) endfunction() @@ -92,12 +110,31 @@ function(detect_deb_release OUT_RELEASE) message(STATUS "detect_deb_release") set(DETECTED_RELEASE "unknown") - if(DEFINED CPACK_DEBIAN_PACKAGE_RELEASE AND NOT "${CPACK_DEBIAN_PACKAGE_RELEASE}" STREQUAL "") - message(STATUS "CPACK_DEBIAN_PACKAGE_RELEASE: ${CPACK_DEBIAN_PACKAGE_RELEASE}") + # Try environment variable first + if(DEFINED ENV{DISTRO_DEB_RELEASE} AND NOT "$ENV{DISTRO_DEB_RELEASE}" STREQUAL "") + set(DETECTED_RELEASE "$ENV{DISTRO_DEB_RELEASE}") + # Use CPACK_DEBIAN_PACKAGE_RELEASE if available + elseif(DEFINED CPACK_DEBIAN_PACKAGE_RELEASE AND NOT "${CPACK_DEBIAN_PACKAGE_RELEASE}" STREQUAL "") # Remove any leading version numbers (e.g. 1+deb13u1 -> deb13u1) string(REGEX REPLACE "^[0-9]+[\+~]?" "" DETECTED_RELEASE "${CPACK_DEBIAN_PACKAGE_RELEASE}") + # Fallback: use detected version as release identifier else() - set(DETECTED_RELEASE "unknown") + # Try to construct a sensible release identifier + if(CMAKE_SYSTEM_NAME MATCHES "Linux") + find_program(LSB_RELEASE_EXEC lsb_release) + if(LSB_RELEASE_EXEC) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --id OUTPUT_VARIABLE LSB_ID OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + execute_process(COMMAND "${LSB_RELEASE_EXEC}" --short --release OUTPUT_VARIABLE LSB_RELEASE OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET) + + if(LSB_ID STREQUAL "Ubuntu") + set(DETECTED_RELEASE "0ubuntu1~${LSB_RELEASE}") + message(STATUS "Generated Ubuntu release string: ${DETECTED_RELEASE}") + elseif(LSB_RELEASE MATCHES "^([0-9]+)") + set(DETECTED_RELEASE "deb${CMAKE_MATCH_1}") + message(STATUS "Generated Debian release string: ${DETECTED_RELEASE}") + endif() + endif() + endif() endif() message(STATUS "DETECTED_RELEASE: ${DETECTED_RELEASE}") diff --git a/deps/packages-coverage.txt b/deps/packages-coverage.txt new file mode 100644 index 00000000..7edd9333 --- /dev/null +++ b/deps/packages-coverage.txt @@ -0,0 +1 @@ +lcov diff --git a/deps/packages-quality.txt b/deps/packages-quality.txt new file mode 100644 index 00000000..b834cb3c --- /dev/null +++ b/deps/packages-quality.txt @@ -0,0 +1,2 @@ +cppcheck +clang-format diff --git a/deps/packages-sbom.txt b/deps/packages-sbom.txt new file mode 100644 index 00000000..36ba6659 --- /dev/null +++ b/deps/packages-sbom.txt @@ -0,0 +1,2 @@ +# Optional SBOM package dependencies. +# syft is installed via upstream installer when unavailable in apt. diff --git a/deps/packages-trixie.txt b/deps/packages-trixie.txt new file mode 100644 index 00000000..f3135fae --- /dev/null +++ b/deps/packages-trixie.txt @@ -0,0 +1,14 @@ +# Build dependencies for Debian 13 (Trixie) +ca-certificates +git +build-essential +cmake +ninja-build +pkg-config +libboost-all-dev +libprotobuf-dev +protobuf-compiler +libusb-1.0-0-dev +libssl-dev +libabsl-dev +file diff --git a/deps/packages-ubuntu24.txt b/deps/packages-ubuntu24.txt new file mode 100644 index 00000000..883dce96 --- /dev/null +++ b/deps/packages-ubuntu24.txt @@ -0,0 +1,14 @@ +# Build dependencies for Ubuntu 24.04 (Noble Numbat) +ca-certificates +git +build-essential +cmake +ninja-build +pkg-config +libboost-all-dev +libprotobuf-dev +protobuf-compiler +libusb-1.0-0-dev +libssl-dev +libabsl-dev +file diff --git a/src/Common/Data.cpp b/src/Common/Data.cpp index 745fc54b..eab6f3dd 100644 --- a/src/Common/Data.cpp +++ b/src/Common/Data.cpp @@ -35,7 +35,7 @@ namespace aasdk { if (offset > _size || _data == nullptr || _size == 0) { data = nullptr; size = 0; - } else if (offset <= _size) { + } else { data = _data + offset; size = _size - offset; } @@ -72,7 +72,7 @@ namespace aasdk { if (offset > _size || _data == nullptr || _size == 0) { cdata = nullptr; size = 0; - } else if (offset <= _size) { + } else { cdata = _data + offset; size = _size - offset; } diff --git a/src/Messenger/MessageInStream.cpp b/src/Messenger/MessageInStream.cpp index c293e30c..997643d4 100644 --- a/src/Messenger/MessageInStream.cpp +++ b/src/Messenger/MessageInStream.cpp @@ -81,13 +81,16 @@ namespace aasdk::messenger { } else { AASDK_LOG_MESSENGER(debug, "Could not find existing message."); // No Message Found in Buffers and this is a middle or last frame, this an error. - // Still need to process the frame, but we will not resolve at the end. - message_ = std::make_shared(frameHeader.getChannelId(), frameHeader.getEncryptionType(), - frameHeader.getMessageType()); if (frameHeader.getType() == FrameType::MIDDLE || frameHeader.getType() == FrameType::LAST) { - // This is an error - isValidFrame_ = false; + AASDK_LOG_MESSENGER(debug, "Rejecting intertwined channel frame."); + promise_->reject(error::Error(error::ErrorCode::MESSENGER_INTERTWINED_CHANNELS)); + promise_.reset(); + message_.reset(); + return; } + + message_ = std::make_shared(frameHeader.getChannelId(), frameHeader.getEncryptionType(), + frameHeader.getMessageType()); } thisFrameType_ = frameHeader.getType();