diff --git a/.github/workflows/ci_linux.yml b/.github/workflows/ci_linux.yml new file mode 100644 index 000000000..93ef8cb04 --- /dev/null +++ b/.github/workflows/ci_linux.yml @@ -0,0 +1,113 @@ +name: CI Linux + +on: + pull_request: + branches: + - '**' + workflow_dispatch: + inputs: + name: + description: "Manual trigger" + schedule: + - cron: '25 18 * * 6' + +permissions: + pull-requests: write + +jobs: + build-test-style-cover: + name: Build, Tests, and Coverage + runs-on: ubuntu-22.04 + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: Install CMake and prerequisites + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y build-essential curl python3-pip valgrind + python3 -m pip install --upgrade pip + python3 -m pip install gcovr + + # CMake 3.31.8 + CMAKE_VER=3.31.8 + curl -L "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-linux-x86_64.tar.gz" -o cmake-${CMAKE_VER}.tgz + sudo tar -C /opt -xzf cmake-${CMAKE_VER}.tgz + echo "/opt/cmake-${CMAKE_VER}-linux-x86_64/bin" >> "$GITHUB_PATH" + + - name: Show cmake version + run: | + cmake --version + ctest --version + + - name: Configure + run: | + mkdir -p build + cd build + cmake ../ci/linux -DCMAKE_BUILD_TYPE=Release + + - name: Build + run: | + cd build + make -j"$(nproc)" + + # --- Run tests with newer CTest to produce JUnit --- + - name: Run tests and export JUnit + shell: bash + run: | + ctest --test-dir build/microxrcedds_client-build \ + --output-on-failure \ + --no-tests=error \ + --output-junit "$GITHUB_WORKSPACE/build/CTestResults.xml" + + - name: Generate coverage (gcovr Cobertura XML + HTML) + shell: bash + run: | + EXCLUDES=( + '--exclude-unreachable-branches' + '--exclude' 'build/' + '--exclude' 'ci/' + '--exclude' 'test/' + '--exclude' 'examples/' + '--exclude' 'thirdparty/' + '--exclude' 'src/c/core/log' + '--exclude' 'src/c/core/serialization/xrce_types.c' + '--exclude' 'src/c/profile/transport/ip' + '--exclude' 'src/c/profile/discovery' + '--exclude' 'src/c/util/ping.c' + ) + gcovr -x -r . "${EXCLUDES[@]}" -o build/coverage.xml + gcovr --html-details -r . "${EXCLUDES[@]}" -o build/coverage.html + gcovr -r . "${EXCLUDES[@]}" # human-readable summary + + - name: Upload artifacts (CTest & Coverage) + uses: actions/upload-artifact@v4 + with: + name: test-and-coverage + path: | + build/CTestResults.xml + build/coverage.xml + build/coverage.html + if-no-files-found: warn + + - name: Publish unit test results (JUnit) + uses: EnricoMi/publish-unit-test-result-action@v2 + if: (!cancelled()) + with: + files: build/CTestResults.xml + check_run: false + comment_mode: failures + comment_title: "Linux Tests Results" + + uncrustify: + name: Uncrustify check + runs-on: ubuntu-22.04 + if: ${{ !(github.event_name == 'pull_request') || !contains(github.event.pull_request.labels.*.name, 'conflicts') }} + steps: + - name: Run Uncrustify Linter + uses: eProsima/eProsima-CI/ubuntu/uncrustify@v0 diff --git a/.github/workflows/ci_windows.yml b/.github/workflows/ci_windows.yml new file mode 100644 index 000000000..db2ec7605 --- /dev/null +++ b/.github/workflows/ci_windows.yml @@ -0,0 +1,85 @@ +name: CI Windows + +on: + pull_request: + branches: + - '**' + workflow_dispatch: + inputs: + name: + description: "Manual trigger" + schedule: + - cron: '50 18 * * 6' + +permissions: + pull-requests: write + +jobs: + build-and-tests: + name: Build and Tests + runs-on: windows-2022 + + env: + TOOLSET: v142 + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: Install CMake + uses: ssrobins/install-cmake@v1 + with: + version: '3.31.8' + + - name: Show tool versions + shell: pwsh + run: | + cmake --version + ctest --version + + - name: Configure + shell: pwsh + run: | + mkdir build + cd build + cmake ..\ci\windows ` + -G "Visual Studio 17 2022" ` + -A x64 ` + -T $env:TOOLSET ` + -DCMAKE_BUILD_TYPE=Release + + - name: Build + shell: pwsh + run: | + cd build + cmake --build . --config Release + + - name: Run tests and export JUnit + shell: pwsh + run: | + ctest --test-dir build\microxrcedds_client-build ` + -C Release ` + --output-on-failure ` + --no-tests=error ` + --output-junit "$env:GITHUB_WORKSPACE\build\CTestResults.xml" + Get-Item "$env:GITHUB_WORKSPACE\build\CTestResults.xml" | Format-List -Property * + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: test-artifact + path: | + build/CTestResults.xml + if-no-files-found: error + + - name: Publish unit test results (JUnit) + uses: EnricoMi/publish-unit-test-result-action/windows@v2 + if: (!cancelled()) + with: + files: build/CTestResults.xml + check_run: false + comment_mode: failures + comment_title: "Windows Tests Results" diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 098ed6e75..8d390e757 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -16,7 +16,7 @@ on: branches: [ master, develop ] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [ master, develop ] schedule: - cron: '24 2 * * *' @@ -39,7 +39,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v1 + uses: github/codeql-action/init@v3 # with: # languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -50,7 +50,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v1 + uses: github/codeql-action/autobuild@v3 # ℹ️ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -64,4 +64,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v1 + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/performance.yml b/.github/workflows/performance.yml new file mode 100644 index 000000000..1feaa47c2 --- /dev/null +++ b/.github/workflows/performance.yml @@ -0,0 +1,240 @@ +name: Weekly Performance + +on: + push: + branches: + - develop + workflow_dispatch: + inputs: + name: + description: "Manual trigger" + schedule: + - cron: '12 13 * * 0' + +permissions: + contents: write + +jobs: + performance: + name: Performance + runs-on: ubuntu-24.04 + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: ${{ github.ref }} + + - name: Install CMake and prerequisites + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y build-essential curl python3-pip valgrind + python3 -m pip install --upgrade pip + python3 -m pip install msparser + + # CMake 3.31.8 + CMAKE_VER=3.31.8 + curl -L "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-linux-x86_64.tar.gz" -o cmake-${CMAKE_VER}.tgz + sudo tar -C /opt -xzf cmake-${CMAKE_VER}.tgz + echo "/opt/cmake-${CMAKE_VER}-linux-x86_64/bin" >> "$GITHUB_PATH" + + - name: Run tests + shell: bash + run: | + ./test/memory/memory_test.sh + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + name: performance-results + path: | + build/complete_profile.csv + build/core_profile.csv + build/stack.csv + build/profiles_bss.csv + build/profiles_data.csv + build/profiles_text.csv + if-no-files-found: error + + save-metrics-and-plots: + name: Save Metrics and Generate Plots + runs-on: ubuntu-24.04 + needs: performance + + steps: + - name: Set branch name + run: echo "BR=memory/performance" >> $GITHUB_ENV # Use this branch to store performance results + + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: ${{ env.BR }} + + - name: Install Python and prerequisites + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y python3-pip + python3 -m pip install --upgrade pip + python3 -m pip install matplotlib + + - name: Download artifacts + uses: actions/download-artifact@v4 + with: + name: performance-results + path: results + + - name: Save results into memory + shell: bash + run: | + set -euxo pipefail + + git config user.name "github-actions" + git config user.email "github-actions@github.com" + + python3 ci/metrics/save_results.py \ + --input results/complete_profile.csv \ + --output ci/metrics/memory/complete_profile_timeseries.csv + python3 ci/metrics/save_results.py \ + --input results/core_profile.csv \ + --output ci/metrics/memory/core_profile_timeseries.csv + python3 ci/metrics/save_results.py \ + --input results/stack.csv \ + --output ci/metrics/memory/stack_timeseries.csv + python3 ci/metrics/save_results.py \ + --input results/profiles_bss.csv \ + --output ci/metrics/memory/profiles_bss_timeseries.csv + python3 ci/metrics/save_results.py \ + --input results/profiles_data.csv \ + --output ci/metrics/memory/profiles_data_timeseries.csv + python3 ci/metrics/save_results.py \ + --input results/profiles_text.csv \ + --output ci/metrics/memory/profiles_text_timeseries.csv + + git add ci/metrics/memory/*_timeseries.csv + git diff --cached --quiet || git commit -m "metrics: append run ${GITHUB_RUN_NUMBER} (${GITHUB_SHA::8})" + git push origin "${{ env.BR }}" + + - name: Generate plots + shell: bash + run: | + set -euxo pipefail + + LAST_N=52 + + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/complete_profile_timeseries.csv \ + --output ci/metrics/plots/complete_profile_plot.svg \ + --title "Complete Profile" \ + --ylabel "Bytes" \ + --last "$LAST_N" + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/core_profile_timeseries.csv \ + --output ci/metrics/plots/core_profile_plot.svg \ + --title "Core Profile" \ + --ylabel "Bytes" \ + --last "$LAST_N" + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/stack_timeseries.csv \ + --output ci/metrics/plots/stack_plot.svg \ + --title "Simple App Stack Usage" \ + --ylabel "Bytes" \ + --last "$LAST_N" + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/profiles_bss_timeseries.csv \ + --output ci/metrics/plots/profiles_bss_plot.svg \ + --title "Increase of .bss memory by enabling profiles" \ + --ylabel "Bytes" \ + --last "$LAST_N" + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/profiles_data_timeseries.csv \ + --output ci/metrics/plots/profiles_data_plot.svg \ + --title "Increase of .data memory by enabling profiles" \ + --ylabel "Bytes" \ + --last "$LAST_N" + python3 ci/metrics/generate_plot.py \ + --input ci/metrics/memory/profiles_text_timeseries.csv \ + --output ci/metrics/plots/profiles_text_plot.svg \ + --title "Increase of .text memory by enabling profiles" \ + --ylabel "Bytes" \ + --last "$LAST_N" + + git add ci/metrics/plots/*.svg + git diff --cached --quiet || git commit -m "metrics: update plots (${GITHUB_RUN_NUMBER})" + git push origin "${{ env.BR }}" + + - name: Upload plots + uses: actions/upload-artifact@v4 + with: + name: performance-plots + path: ci/metrics/plots/*.svg + if-no-files-found: warn + + - name: Add plots to summary + if: always() + shell: bash + run: | + set -euo pipefail + + BASE="https://raw.githubusercontent.com/${GITHUB_REPOSITORY}/memory/performance/ci/metrics/plots" + CB="?r=${GITHUB_RUN_NUMBER}" + + { + echo "## 📊 Performance Metrics (last 52 runs)" + echo + echo "The workflow triggering this run can be found in the default branch." + echo "The python scripts and the data used to generate these plots can be found in the [memory/performance](${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/tree/memory/performance) branch." + echo "The scripts and data can be modified without affecting develop nor master branches." + echo "The \`memory/performance\` branch is unprotected and can be pushed to in case any manual modifications are needed." + echo + echo "### Complete Profile" + echo "\"Complete" + echo + echo "### Core Profile" + echo "\"Core" + echo + echo "### Simple App Stack Usage" + echo "\"Stack\"" + echo + echo "### Increase of .bss memory by enabling profiles" + echo "\"bss\"" + echo + echo "### Increase of .data memory by enabling profiles" + echo "\"data\"" + echo + echo "### Increase of .text memory by enabling profiles" + echo "\"text\"" + } >> "$GITHUB_STEP_SUMMARY" + + analyze-metrics: + name: Analyze Metrics + runs-on: ubuntu-24.04 + needs: save-metrics-and-plots + + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + ref: memory/performance + + - name: Analyze results + shell: bash + run: | + set -euo pipefail + + { + echo "## Analyze Memory Metrics" + echo + echo "⚠️ Failure of this job should be treated as a warning. It can be safely ignored if there are intentional changes that affect memory usage." + } >> "$GITHUB_STEP_SUMMARY" + + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/complete_profile_timeseries.csv + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/core_profile_timeseries.csv + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/stack_timeseries.csv + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/profiles_bss_timeseries.csv + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/profiles_data_timeseries.csv + python3 ci/metrics/check_last_result.py --input ci/metrics/memory/profiles_text_timeseries.csv diff --git a/CMakeLists.txt b/CMakeLists.txt index d3c2e46f6..69ad7929b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,8 +81,8 @@ set(UCLIENT_C_STANDARD 99 CACHE STRING "Version of the C language used to build ############################################################################### # Dependencies ############################################################################### -set(_microcdr_version 2.0.1) -set(_microcdr_tag v2.0.1) +set(_microcdr_version 2.0.2) +set(_microcdr_tag v2.0.2) set(_deps "") list(APPEND _deps "microcdr\;${_microcdr_version}") @@ -92,7 +92,7 @@ list(APPEND _deps "microcdr\;${_microcdr_version}") ############################################################################### set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) if(NOT UCLIENT_SUPERBUILD) - project(microxrcedds_client VERSION "3.0.0" LANGUAGES C) + project(microxrcedds_client VERSION "3.0.1" LANGUAGES C) else() project(uclient_superbuild NONE) include(${PROJECT_SOURCE_DIR}/cmake/SuperBuild.cmake) diff --git a/README.md b/README.md index 1ed80d722..162e23744 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ [![Docker Build Status](https://img.shields.io/docker/cloud/build/eprosima/micro-xrce-dds-client)](https://hub.docker.com/r/eprosima/micro-xrce-dds-client/) - + *eProsima Micro XRCE-DDS* is a library implementing the [DDS-XRCE protocol](https://www.omg.org/spec/DDS-XRCE/About-DDS-XRCE/) as defined and maintained by the OMG, whose aim is to allow resource constrained devices such as microcontrollers to communicate with the [DDS](https://www.omg.org/spec/DDS/About-DDS/>) world as any other DDS actor would do. It follows a client/server paradigm and is composed by two libraries, the *Micro XRCE-DDS Client* and the *Micro XRCE-DDS Agent*. The *Micro XRCE-DDS Clients* are lightweight entities meant to be compiled on e**X**tremely **R**esource **C**onstrained **E**nvironments, while the *Micro XRCE-DDS Agent* is a broker which bridges the *Clients* with the DDS world. @@ -27,6 +27,12 @@ The communication in the DDS world is mediated by a dedicated `ProxyClient` in c The communication between a *Micro XRCE-DDS Client* and a *Micro XRCE-DDS Agent* is achieved by means of several kinds of built-in transports: **UDPv4**, **UDPv6**, **TCPv4**, **TCPv6** and **Serial** communication. In addition, there is the possibility for the user to generate its own **Custom** transport. +## Commercial support + +Looking for commercial support? Write us to info@eprosima.com + +Find more about us at [eProsima’s webpage](https://eprosima.com/). + ## Documentation You can access the *eProsima Micro XRCE-DDS* user documentation online, which is hosted on Read the Docs. @@ -39,6 +45,3 @@ You can access the *eProsima Micro XRCE-DDS* user documentation online, which is **eProsima Micro XRCE-DDS Client** claims to be in the **Quality Level 1** category based on the guidelines provided by [ROS 2](https://ros.org/reps/rep-2004.html). See the [Quality Declaration](QUALITY.md) for more details. -## Getting Help - -If you need support you can reach us by mail at `support@eProsima.com` or by phone at `+34 91 804 34 48`. diff --git a/docs/eprosima-logo.svg b/docs/eprosima-logo.svg new file mode 100644 index 000000000..447536324 --- /dev/null +++ b/docs/eprosima-logo.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/examples/ShapesDemo/main.c b/examples/ShapesDemo/main.c index 097691ba1..d94fda394 100644 --- a/examples/ShapesDemo/main.c +++ b/examples/ShapesDemo/main.c @@ -438,13 +438,13 @@ bool compute_command( (void) compute_print_command(session, stream_id, 3, "create_datareader", arg1, arg1, 0, 0, 0, ""); (void) uxr_run_session_time(session, 20); } - else if (0 == strcmp(name, "list") || 0 == strcmp(name, "l")) + else if (0 == strcmp(name, "help") || 0 == strcmp(name, "h")) { print_commands(); } else { - printf("%sUnknown command error, write 'l' or 'list' to show the command list.%s\n", RED_CONSOLE_COLOR, + printf("%sUnknown command error, write 'h' or 'help' to show the command list.%s\n", RED_CONSOLE_COLOR, RESTORE_COLOR); shapes_demo_error = 2; } diff --git a/test/memory/consumption/stack_analysis.py b/test/memory/consumption/stack_analysis.py index 0c94a764e..0f83cbfdc 100644 --- a/test/memory/consumption/stack_analysis.py +++ b/test/memory/consumption/stack_analysis.py @@ -12,4 +12,3 @@ csv_writer = csv.writer(csv_file, delimiter=',', quoting=csv.QUOTE_ALL) csv_writer.writerow(['stack']) csv_writer.writerow([max(stack)]) -