diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c8b1d95017..dce9cd5d75 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -201,6 +201,51 @@ jobs: path: buildartifacts/ continue-on-error: true + # Test the out-of-tree build + OOT-Build: + needs: Linux + runs-on: ubuntu-latest + env: + DOCKER_BUILDKIT: 1 + steps: + - name: Download Source Artifact + uses: actions/download-artifact@v5 + with: + name: source-bundle + path: . + + - name: Extract sources + run: tar zxf sources.tar.gz + + - name: Docker Login + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Export NuttX Repo SHA + run: echo "nuttx_sha=`git -C sources/nuttx rev-parse HEAD`" >> $GITHUB_ENV + + - name: Run Out-of-Tree Build Test + uses: ./sources/nuttx/.github/actions/ci-container + env: + BLOBDIR: /tools/blobs + with: + run: | + echo "::add-matcher::sources/nuttx/.github/gcc.json" + git config --global --add safe.directory /github/workspace/sources/nuttx + git config --global --add safe.directory /github/workspace/sources/apps + cd sources/nuttx + ./tools/ci/cibuild-oot.sh + + - uses: actions/upload-artifact@v4 + if: ${{ always() }} + with: + name: oot-build-artifacts + path: sources/apps/testing/cxx-oot-build + continue-on-error: true + # Select the macOS Builds based on PR Arch Label macOS-Arch: uses: apache/nuttx/.github/workflows/arch.yml@master diff --git a/Documentation/applications/testing/cxx-oot-build/index.rst b/Documentation/applications/testing/cxx-oot-build/index.rst new file mode 100644 index 0000000000..9216ebbfe1 --- /dev/null +++ b/Documentation/applications/testing/cxx-oot-build/index.rst @@ -0,0 +1,75 @@ +======================================== +``cxx-oot-build`` Out-of-Tree Build Test +======================================== + +The ``cxx-oot-build`` test automates building an **Out-of-Tree (OOT)** NuttX +project using a NuttX export tarball. Its primary purpose is to validate that +NuttX can be built outside of the main source tree and to prevent regressions +in the build process for C++ projects. + +**Important:** This test uses a specialized defconfig that is **not functional** +for running actual applications. It is intended purely for CI/build +verification. Functional OOT projects should be configured according to +the instructions in :ref:`cpp_cmake`. + +The test script is located at: + +- ``tools/ci/cibuild-oot.sh`` + +### Out-of-Tree App Content + +The source content for this OOT test can be found in: + +- ``apps/testing/cxx-oot-build`` + +Its structure provides a basic skeleton for building a C++ NuttX application: + +.. code-block:: text + + testing/cxx-oot-build + ├── CMakeLists.txt + ├── include + │ └── HelloWorld.hpp + └── src + ├── HelloWorld.cpp + └── main.cpp + +This minimal structure includes: + +- `CMakeLists.txt` - Build instructions for the OOT C++ project +- `include/HelloWorld.hpp` - Example header file +- `src/HelloWorld.cpp` - Example class implementation +- `src/main.cpp` - Entry point for the test application + +### How to Run the Test + +Execute the test script from the NuttX CI tools directory: + + cd ${NUTTX_PATH}/tools/ci + ./cibuild-oot.sh + +The script performs the following steps: + +1. Configures NuttX for the ``cxx-oot-build`` board profile +2. Builds an export tarball of NuttX +3. Prepares the Out-of-Tree project by extracting the tarball +4. Builds the OOT project using CMake +5. Verifies that the output binaries ``oot`` and ``oot.bin`` exist + +### Expected Output + +On success, you should see: + + ✅ SUCCESS: OOT build completed. Output: + -rwxrwxr-x 1 94K /path/to/oot + -rwxrwxr-x 1 46K /path/to/oot.bin + +If any step fails, the script will exit immediately with an error message. + +### Notes + +- No additional configuration options are required for this test. The + ``cxx-oot-build`` defconfig is preconfigured to build correctly but is + **not suitable for running applications**. +- For functional OOT builds, please follow the procedure documented in + :doc:`here `. diff --git a/boards/arm/stm32/stm32f4discovery/configs/cxx-oot-build/defconfig b/boards/arm/stm32/stm32f4discovery/configs/cxx-oot-build/defconfig new file mode 100644 index 0000000000..4a06d4832f --- /dev/null +++ b/boards/arm/stm32/stm32f4discovery/configs/cxx-oot-build/defconfig @@ -0,0 +1,48 @@ +# +# This file is autogenerated: PLEASE DO NOT EDIT IT. +# +# You can use "make menuconfig" to make any modifications to the installed .config file. +# You can then do "make savedefconfig" to generate a new defconfig file that includes your +# modifications. +# +# CONFIG_ARCH_FPU is not set +# CONFIG_ARCH_LEDS is not set +# CONFIG_DISABLE_OS_API is not set +# CONFIG_SYSTEM_DD is not set +CONFIG_ARCH="arm" +CONFIG_ARCH_BOARD="stm32f4discovery" +CONFIG_ARCH_BOARD_COMMON=y +CONFIG_ARCH_BOARD_STM32F4_DISCOVERY=y +CONFIG_ARCH_CHIP="stm32" +CONFIG_ARCH_CHIP_STM32=y +CONFIG_ARCH_CHIP_STM32F407VG=y +CONFIG_ARCH_STACKDUMP=y +CONFIG_BOARD_LATE_INITIALIZE=y +CONFIG_BOARD_LOOPSPERMSEC=16717 +CONFIG_BUILTIN=y +CONFIG_CXX_EXCEPTION=y +CONFIG_CXX_STANDARD="c++17" +CONFIG_DRVR_MKRD=y +CONFIG_FS_PROCFS=y +CONFIG_HAVE_CXX=y +CONFIG_INIT_NONE=y +CONFIG_INTELHEX_BINARY=y +CONFIG_LIBCXXTOOLCHAIN=y +CONFIG_LINE_MAX=64 +CONFIG_MM_REGIONS=2 +CONFIG_PREALLOC_TIMERS=4 +CONFIG_RAM_SIZE=114688 +CONFIG_RAM_START=0x20000000 +CONFIG_RAW_BINARY=y +CONFIG_RR_INTERVAL=200 +CONFIG_SCHED_WAITPID=y +CONFIG_START_DAY=6 +CONFIG_START_MONTH=12 +CONFIG_START_YEAR=2011 +CONFIG_STM32_JTAG_SW_ENABLE=y +CONFIG_STM32_PWR=y +CONFIG_STM32_SPI1=y +CONFIG_STM32_USART2=y +CONFIG_USART2_RXBUFSIZE=128 +CONFIG_USART2_SERIAL_CONSOLE=y +CONFIG_USART2_TXBUFSIZE=128 diff --git a/tools/ci/cibuild-oot.sh b/tools/ci/cibuild-oot.sh new file mode 100755 index 0000000000..a0a2d88104 --- /dev/null +++ b/tools/ci/cibuild-oot.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash +############################################################################ +# tools/ci/cibuild-oot.sh +# +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +set -euo pipefail + +CID=$(cd "$(dirname "$0")" && pwd) +CIWORKSPACE=$(cd "${CID}"/../../../ && pwd -P) +NUTTX_PATH=${CIWORKSPACE}/nuttx +APP_PATH=${CIWORKSPACE}/apps + +# === CONFIGURATION === +# Allow overriding from environment for CI +EXPORT_CONFIG=${EXPORT_CONFIG:-"stm32f4discovery:cxx-oot-build"} +OOT_SRC=${OOT_SRC:-"$APP_PATH/testing/cxx-oot-build"} +BUILD_DIR=${BUILD_DIR:-"$OOT_SRC/build"} + +# Place ourselves in the nuttx dir +cd $NUTTX_PATH + +echo "=== [1/5] Configuring NuttX Export ($EXPORT_CONFIG) ===" +./tools/configure.sh -E -l "$EXPORT_CONFIG" + +echo "=== [2/5] Building Export Tarball ===" +make -j"$(nproc)" export + +EXPORT_TARBALL=$(find . -maxdepth 1 -type f -name "nuttx-export-*.tar.gz" | sort | tail -n 1) +if [[ -z "$EXPORT_TARBALL" ]]; then + echo "❌ ERROR: No export tarball found" + exit 1 +fi + +echo "=== [3/5] Preparing Out of Tree (OOT) Project ===" +rm -rf "$OOT_SRC"/nuttx-export-* +tar -xzf "$EXPORT_TARBALL" -C "$OOT_SRC" + +TOOLCHAIN_FILE=$(find "$OOT_SRC" -type f -path "*/scripts/toolchain.cmake" | head -n 1) +if [[ ! -f "$TOOLCHAIN_FILE" ]]; then + echo "❌ ERROR: toolchain.cmake not found after export" + exit 1 +fi + +echo "=== [4/5] Building OOT ===" +rm -rf "$BUILD_DIR" +mkdir -p "$BUILD_DIR" +cd "$BUILD_DIR" +cmake .. -DCMAKE_TOOLCHAIN_FILE="$TOOLCHAIN_FILE" -DBUILD_OOTCPP=ON +make -j"$(nproc)" + +echo "=== [5/5] Verifying Output ===" +if [[ ! -f "$BUILD_DIR/oot" || ! -f "$BUILD_DIR/oot.bin" ]]; then + echo "❌ ERROR: oot or oot.bin not found in $BUILD_DIR" + exit 1 +fi + +echo "✅ SUCCESS: OOT build completed. Output:" +ls -lh "$BUILD_DIR"/oot*