Repository: mavlink/MAVSDK
Pull request #2373 (2024-08-13 22:43:13)

Move to Ubuntu 24.04
This moves from clang-format-12 to clang-format-18 which comes with Ubuntu 24.04.

Also, let's try to add Ubuntu 24.04 to CI as well while I'm at it.


Patch:
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index f7c61b8d..588ac86d 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -77,7 +77,7 @@ jobs:
     runs-on: ${{ matrix.ubuntu_image }}
     strategy:
       matrix:
-        ubuntu_image: [ubuntu-20.04, ubuntu-22.04]
+        ubuntu_image: [ubuntu-20.04, ubuntu-22.04, ubuntu-24.04]
     steps:
       - uses: actions/checkout@v4
         with:
@@ -153,14 +153,14 @@ jobs:
       #  run: ./build/src/system_tests/system_tests_runner
 
   ubuntu22-style-and-proto-check:
-    name: ubuntu-22.04 (style and proto check)
-    runs-on: ubuntu-22.04
+    name: ubuntu-24.04 (style and proto check)
+    runs-on: ubuntu-24.04
     steps:
       - uses: actions/checkout@v4
         with:
           submodules: recursive
       - name: install dependencies
-        run: sudo apt-get update && sudo apt-get install -y clang-format-12
+        run: sudo apt-get update && sudo apt-get install -y clang-format-18
       - uses: actions/cache@v4
         id: cache
         with:
diff --git a/docker/Dockerfile-clang-format b/docker/Dockerfile-clang-format
new file mode 100644
index 00000000..2783698f
--- /dev/null
+++ b/docker/Dockerfile-clang-format
@@ -0,0 +1,21 @@
+#
+# Formatting helper for MAVSDK based on Ubuntu 24.04's clang-format-18
+#
+# Author: Julian Oes <julian@oes.ch>
+#
+
+FROM ubuntu:24.04
+MAINTAINER Julian Oes <julian@oes.ch>
+
+ENV DEBIAN_FRONTEND noninteractive
+
+RUN apt-get update \
+    && apt-get -y --quiet --no-install-recommends install \
+        git \
+        clang-format-18 \
+        colordiff \
+    && apt-get -y autoremove \
+    && apt-get clean autoclean \
+    && rm -rf /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
+
+WORKDIR "/home/user/MAVSDK"
diff --git a/docker/Dockerfile-dev b/docker/Dockerfile-dev
deleted file mode 100644
index 4840d816..00000000
--- a/docker/Dockerfile-dev
+++ /dev/null
@@ -1,59 +0,0 @@
-#
-# Development environment for MAVSDK based on Ubuntu 22.04.
-#
-# Author: Julian Oes <julian@oes.ch>
-#
-
-FROM ubuntu:22.04
-MAINTAINER Julian Oes <julian@oes.ch>
-
-ENV DEBIAN_FRONTEND noninteractive
-
-
-RUN apt-get update \
-    && apt-get -y --quiet --no-install-recommends install \
-        autoconf \
-        automake \
-        autotools-dev \
-        build-essential \
-        ca-certificates \
-        ccache \
-        clang-format-12 \
-        cmake \
-        colordiff \
-        doxygen \
-        git \
-        golang-go \
-        libcurl4-openssl-dev \
-        libltdl-dev \
-        libtinyxml2-dev \
-        libtool \
-        libz-dev \
-        ninja-build \
-        python3 \
-        python3-pip \
-        python3-future \
-        ruby-dev \
-        software-properties-common \
-        sudo \
-        wget \
-    && apt-get -y autoremove \
-    && apt-get clean autoclean \
-    && rm -rf /var/lib/apt/lists/{apt,dpkg,cache,log} /tmp/* /var/tmp/*
-
-RUN gem install --no-document fpm;
-
-RUN wget -qO- https://github.com/ncopa/su-exec/archive/dddd1567b7c76365e1e0aac561287975020a8fad.tar.gz | tar xvz && \
-    cd su-exec-* && make && mv su-exec /usr/local/bin && cd .. && rm -rf su-exec-*
-
-# Create user with id 1001 (Jenkins docker workflow default)
-RUN useradd --shell /bin/bash -u 1001 -c "" -m user
-
-ADD /sudoers.txt /etc/sudoers
-RUN chmod 440 /etc/sudoers
-
-COPY entrypoint.sh /usr/local/bin/entrypoint.sh
-
-ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
-
-WORKDIR "/home/user/MAVSDK"
diff --git a/docker/build_and_push_docker_images.sh b/docker/build_and_push_docker_images.sh
index f9aeed34..8a1f3665 100755
--- a/docker/build_and_push_docker_images.sh
+++ b/docker/build_and_push_docker_images.sh
@@ -1,23 +1,22 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
 
 set -e
 
-DOCKER_CMD=docker
+DOCKER_CMD=$(which docker podman 2>/dev/null | head -n 1)
 
-if ! command -v $DOCKER_CMD &> /dev/null
-then
-    echo "docker not found, trying podman instead"
-    DOCKER_CMD=podman
+if [ -z "$DOCKER_CMD" ]; then
+  echo "docker or podman commands not found"
+  exit 1
 fi
 
-$DOCKER_CMD build -f Dockerfile-dev -t mavsdk/mavsdk-dev .
-$DOCKER_CMD build -f Dockerfile.dockcross-linux-armv6-custom -t mavsdk/mavsdk-dockcross-linux-armv6-custom .
-$DOCKER_CMD build -f Dockerfile.dockcross-linux-armv7-custom -t mavsdk/mavsdk-dockcross-linux-armv7-custom .
-$DOCKER_CMD build -f Dockerfile.dockcross-linux-arm64-custom -t mavsdk/mavsdk-dockcross-linux-arm64-custom .
-$DOCKER_CMD build -f Dockerfile.dockcross-linux-arm64-lts-custom -t mavsdk/mavsdk-dockcross-linux-arm64-lts-custom .
+$DOCKER_CMD build -f Dockerfile-clang-format -t docker.io/mavsdk/mavsdk-clang-format .
+$DOCKER_CMD build -f Dockerfile.dockcross-linux-armv6-custom -t docker.io/mavsdk/mavsdk-dockcross-linux-armv6-custom .
+$DOCKER_CMD build -f Dockerfile.dockcross-linux-armv7-custom -t docker.io/mavsdk/mavsdk-dockcross-linux-armv7-custom .
+$DOCKER_CMD build -f Dockerfile.dockcross-linux-arm64-custom -t docker.io/mavsdk/mavsdk-dockcross-linux-arm64-custom .
+$DOCKER_CMD build -f Dockerfile.dockcross-linux-arm64-lts-custom -t docker.io/mavsdk/mavsdk-dockcross-linux-arm64-lts-custom .
 
-$DOCKER_CMD push mavsdk/mavsdk-dev:latest
-$DOCKER_CMD push mavsdk/mavsdk-dockcross-linux-armv6-custom:latest
-$DOCKER_CMD push mavsdk/mavsdk-dockcross-linux-armv7-custom:latest
-$DOCKER_CMD push mavsdk/mavsdk-dockcross-linux-arm64-custom:latest
-$DOCKER_CMD push mavsdk/mavsdk-dockcross-linux-arm64-lts-custom:latest
+$DOCKER_CMD push docker.io/mavsdk/mavsdk-clang-format:latest
+$DOCKER_CMD push docker.io/mavsdk/mavsdk-dockcross-linux-armv6-custom:latest
+$DOCKER_CMD push docker.io/mavsdk/mavsdk-dockcross-linux-armv7-custom:latest
+$DOCKER_CMD push docker.io/mavsdk/mavsdk-dockcross-linux-arm64-custom:latest
+$DOCKER_CMD push docker.io/mavsdk/mavsdk-dockcross-linux-arm64-lts-custom:latest
diff --git a/examples/ftp_client/ftp_client.cpp b/examples/ftp_client/ftp_client.cpp
index 4231a7ad..ea6a9e8b 100644
--- a/examples/ftp_client/ftp_client.cpp
+++ b/examples/ftp_client/ftp_client.cpp
@@ -155,8 +155,7 @@ upload_file(Ftp& ftp, const std::string& local_file_path, const std::string& rem
                 int percentage = progress.total_bytes > 0 ?
                                      progress.bytes_transferred * 100 / progress.total_bytes :
                                      0;
-                std::cerr << "\rUploading "
-                          << "[" << std::setw(3) << percentage << "%] "
+                std::cerr << "\rUploading " << "[" << std::setw(3) << percentage << "%] "
                           << progress.bytes_transferred << " of " << progress.total_bytes;
                 if (progress.bytes_transferred == progress.total_bytes) {
                     std::cerr << '\n';
diff --git a/src/mavsdk/core/mavlink_command_sender.cpp b/src/mavsdk/core/mavlink_command_sender.cpp
index 672a62a6..81017214 100644
--- a/src/mavsdk/core/mavlink_command_sender.cpp
+++ b/src/mavsdk/core/mavlink_command_sender.cpp
@@ -173,8 +173,8 @@ void MavlinkCommandSender::receive_command_ack(const mavlink_message_t& message)
             if (_command_debugging) {
                 LogDebug() << "Command ack for " << command_ack.command
                            << " (from: " << std::to_string(message.sysid) << "/"
-                           << std::to_string(message.compid) << ")"
-                           << " does not match command " << work->identification.command
+                           << std::to_string(message.compid) << ")" << " does not match command "
+                           << work->identification.command
                            << " (to: " << std::to_string(work->identification.target_system_id)
                            << "/" << std::to_string(work->identification.target_component_id) << ")"
                            << " after "
diff --git a/src/mavsdk/core/mavlink_parameter_client.cpp b/src/mavsdk/core/mavlink_parameter_client.cpp
index 57d72e95..0e0683b7 100644
--- a/src/mavsdk/core/mavlink_parameter_client.cpp
+++ b/src/mavsdk/core/mavlink_parameter_client.cpp
@@ -74,8 +74,7 @@ MavlinkParameterClient::set_param(const std::string& name, const ParamValue& val
 {
     auto prom = std::promise<Result>();
     auto res = prom.get_future();
-    set_param_async(
-        name, value, [&prom](Result result) { prom.set_value(result); }, this);
+    set_param_async(name, value, [&prom](Result result) { prom.set_value(result); }, this);
     return res.get();
 }
 
@@ -173,8 +172,7 @@ MavlinkParameterClient::set_param_int(const std::string& name, int32_t value)
 {
     auto prom = std::promise<Result>();
     auto res = prom.get_future();
-    set_param_int_async(
-        name, value, [&prom](Result result) { prom.set_value(result); }, this);
+    set_param_int_async(name, value, [&prom](Result result) { prom.set_value(result); }, this);
     return res.get();
 }
 
@@ -192,8 +190,7 @@ MavlinkParameterClient::set_param_float(const std::string& name, float value)
     auto prom = std::promise<Result>();
     auto res = prom.get_future();
 
-    set_param_float_async(
-        name, value, [&prom](Result result) { prom.set_value(result); }, this);
+    set_param_float_async(name, value, [&prom](Result result) { prom.set_value(result); }, this);
 
     return res.get();
 }
@@ -229,8 +226,7 @@ MavlinkParameterClient::set_param_custom(const std::string& name, const std::str
 {
     auto prom = std::promise<Result>();
     auto res = prom.get_future();
-    set_param_custom_async(
-        name, value, [&prom](Result result) { prom.set_value(result); }, this);
+    set_param_custom_async(name, value, [&prom](Result result) { prom.set_value(result); }, this);
     return res.get();
 }
 
diff --git a/src/mavsdk/plugins/gimbal/gimbal_impl.cpp b/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
index 86fa3cbe..87caf91a 100644
--- a/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
+++ b/src/mavsdk/plugins/gimbal/gimbal_impl.cpp
@@ -284,8 +284,7 @@ void GimbalImpl::process_gimbal_device_attitude_status(const mavlink_message_t&
 
     if (attitude_status.gimbal_device_id > 6) {
         LogWarn() << "Ignoring gimbal device attitude status with invalid gimbal_device_id "
-                  << attitude_status.gimbal_device_id << " from (" << message.sysid << "/"
-                  << ")";
+                  << attitude_status.gimbal_device_id << " from (" << message.sysid << "/" << ")";
         return;
     }
 
diff --git a/src/mavsdk/plugins/log_files/log_files_impl.h b/src/mavsdk/plugins/log_files/log_files_impl.h
index eea7fd34..13eef87b 100644
--- a/src/mavsdk/plugins/log_files/log_files_impl.h
+++ b/src/mavsdk/plugins/log_files/log_files_impl.h
@@ -48,8 +48,8 @@ public:
     void init() override;
     void deinit() override;
 
-    void enable() override{};
-    void disable() override{};
+    void enable() override {};
+    void disable() override {};
 
     std::pair<LogFiles::Result, std::vector<LogFiles::Entry>> get_entries();
     void get_entries_async(LogFiles::GetEntriesCallback callback);
diff --git a/src/mavsdk/plugins/param_server/param_server_impl.cpp b/src/mavsdk/plugins/param_server/param_server_impl.cpp
index e6c50b19..a26bc384 100644
--- a/src/mavsdk/plugins/param_server/param_server_impl.cpp
+++ b/src/mavsdk/plugins/param_server/param_server_impl.cpp
@@ -46,9 +46,7 @@ ParamServer::Result ParamServerImpl::provide_param_int(std::string name, int32_t
     _server_component_impl->mavlink_parameter_server().provide_server_param_int(name, value);
     _server_component_impl->mavlink_parameter_server().subscribe_param_int_changed(
         name,
-        [name, this](int32_t new_value) {
-            _changed_param_int_callbacks({name, new_value});
-        },
+        [name, this](int32_t new_value) { _changed_param_int_callbacks({name, new_value}); },
         this);
     return ParamServer::Result::Success;
 }
@@ -73,9 +71,7 @@ ParamServer::Result ParamServerImpl::provide_param_float(std::string name, float
     _server_component_impl->mavlink_parameter_server().provide_server_param_float(name, value);
     _server_component_impl->mavlink_parameter_server().subscribe_param_float_changed(
         name,
-        [name, this](float new_value) {
-            _changed_param_float_callbacks({name, new_value});
-        },
+        [name, this](float new_value) { _changed_param_float_callbacks({name, new_value}); },
         this);
     return ParamServer::Result::Success;
 }
@@ -102,9 +98,7 @@ ParamServerImpl::provide_param_custom(std::string name, const std::string& value
     _server_component_impl->mavlink_parameter_server().provide_server_param_custom(name, value);
     _server_component_impl->mavlink_parameter_server().subscribe_param_custom_changed(
         name,
-        [name, this](std::string new_value) {
-            _changed_param_custom_callbacks({name, new_value});
-        },
+        [name, this](std::string new_value) { _changed_param_custom_callbacks({name, new_value}); },
         this);
     return ParamServer::Result::Success;
 }
diff --git a/tools/fix_style.sh b/tools/fix_style.sh
index 55437e93..2d8c6099 100755
--- a/tools/fix_style.sh
+++ b/tools/fix_style.sh
@@ -3,26 +3,17 @@
 # This script runs clang-format over all files ending in .h, .c, .cpp listed
 # by git in the given directory.
 
-version_required_major="12"
+version_required_major="18"
 
 # Try to find the latest version of clang
-if command -v clang-format-12 >/dev/null; then
-    clang_format=clang-format-12
-elif command -v clang-format-11 >/dev/null; then
-    clang_format=clang-format-11
-elif command -v clang-format-10 >/dev/null; then
-    clang_format=clang-format-10
-elif command -v clang-format-9 >/dev/null; then
-    clang_format=clang-format-9
-elif command -v clang-format-8 >/dev/null; then
-    clang_format=clang-format-8
-elif command -v clang-format-7 >/dev/null; then
-    clang_format=clang-format-7
+if command -v clang-format-18 >/dev/null; then
+    clang_format=clang-format-18
 elif command -v clang-format >/dev/null; then
     clang_format=clang-format
 else
-    echo "clang-format not found"
-    echo "--> check: https://mavsdk.mavlink.io/main/en/cpp/guide/code_style.html#formatting-and-white-space"
+    echo "You can use clang-format from docker:"
+    echo ""
+    echo "    'tools/run-docker-clang-format.sh tools/fix_style.sh .'"
     exit 1
 fi
 
@@ -35,14 +26,14 @@ if [ "$version_required_major" -gt "$version_major" ]; then
     echo "Clang version $version_major too old (required: $version_required_major)"
     echo "You can use clang-format-$version_required_major from docker:"
     echo ""
-    echo "    'tools/run-docker.sh tools/fix_style.sh .'"
+    echo "    'tools/run-docker-clang-format.sh tools/fix_style.sh .'"
     exit 1
 
 elif [ "$version_required_major" -lt "$version_major" ]; then
     echo "Clang version $version_major too new (required: $version_required_major)"
     echo "You can use clang-format-$version_required_major from docker:"
     echo ""
-    echo "    'tools/run-docker.sh tools/fix_style.sh .'"
+    echo "    'tools/run-docker-clang-format.sh tools/fix_style.sh .'"
     exit 1
 fi
 
diff --git a/tools/run-docker-clang-format.sh b/tools/run-docker-clang-format.sh
new file mode 100755
index 00000000..cf8e0406
--- /dev/null
+++ b/tools/run-docker-clang-format.sh
@@ -0,0 +1,13 @@
+#!/usr/bin/env sh
+
+set -e
+
+DOCKER_CMD=$(which docker podman 2>/dev/null | head -n 1)
+
+if [ -z "$DOCKER_CMD" ]; then
+  echo "docker or podman commands not found"
+  exit 1
+fi
+
+# Use the found container runtime
+$DOCKER_CMD run -it --rm -v $(pwd):/home/user/MAVSDK:z -u `stat -c "%u:%g" $(pwd)` docker.io/mavsdk/mavsdk-clang-format "$@"
diff --git a/tools/run-docker.sh b/tools/run-docker.sh
deleted file mode 100755
index 0d3376f2..00000000
--- a/tools/run-docker.sh
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/usr/bin/env sh
-
-dockerimage=docker.io/mavsdk/mavsdk-dev
-
-if type podman > /dev/null 2> /dev/null
-then
-    podman run -it --rm -v $(pwd):/home/user/MAVSDK:z $dockerimage "$@"
-    echo "sudo needed to repair file ownership after podman ran: sudo chown -R $USER:$USER ."
-    sudo chown -R $USER:$USER .
-
-elif type docker > /dev/null 2> /dev/null
-then
-    docker run -it --rm -v $(pwd):/home/user/MAVSDK:z -e LOCAL_USER_ID=`id -u` $dockerimage "$@"
-
-else
-    echo "docker or podman commands not found"
-    exit 1
-fi


Test patch:
diff --git a/src/integration_tests/log_files.cpp b/src/integration_tests/log_files.cpp
index 4a4bc99c..453aba26 100644
--- a/src/integration_tests/log_files.cpp
+++ b/src/integration_tests/log_files.cpp
@@ -34,8 +34,7 @@ TEST(HardwareTest, LogFiles)
 
         for (auto& entry : entry_result.second) {
             float size_mib = entry.size_bytes / 1024.0f / 1024.0f;
-            LogInfo() << "Entry " << entry.id << ": "
-                      << " at " << entry.date << ", " << size_mib
+            LogInfo() << "Entry " << entry.id << ": " << " at " << entry.date << ", " << size_mib
                       << " MiB, bytes: " << entry.size_bytes;
             std::stringstream file_path_stream;
             file_path_stream << "./logfile_" << entry.id << ".ulog";
@@ -89,8 +88,7 @@ TEST(HardwareTest, LogFilesDownloadFailsIfPathIsDirectory)
 
         for (auto& entry : entry_result.second) {
             float size_mib = entry.size_bytes / 1024.0f / 1024.0f;
-            LogInfo() << "Entry " << entry.id << ": "
-                      << " at " << entry.date << ", " << size_mib
+            LogInfo() << "Entry " << entry.id << ": " << " at " << entry.date << ", " << size_mib
                       << " MiB, bytes: " << entry.size_bytes;
 
             std::stringstream file_path_stream;
@@ -145,8 +143,7 @@ TEST(HardwareTest, LogFilesDownloadFailsIfFileAlreadyExists)
 
         for (auto& entry : entry_result.second) {
             float size_mib = entry.size_bytes / 1024.0f / 1024.0f;
-            LogInfo() << "Entry " << entry.id << ": "
-                      << " at " << entry.date << ", " << size_mib
+            LogInfo() << "Entry " << entry.id << ": " << " at " << entry.date << ", " << size_mib
                       << " MiB, bytes: " << entry.size_bytes;
             std::stringstream file_path_stream;
             file_path_stream << "./logfile_" << entry.id << ".ulog";
diff --git a/src/integration_tests/telemetry_async.cpp b/src/integration_tests/telemetry_async.cpp
index e78c1881..c649da39 100644
--- a/src/integration_tests/telemetry_async.cpp
+++ b/src/integration_tests/telemetry_async.cpp
@@ -330,10 +330,10 @@ void print_position_velocity_ned(Telemetry::PositionVelocityNed position_velocit
 void print_altitude(Telemetry::Altitude altitude)
 {
     std::cout << "altitude_monotonic: " << altitude.altitude_monotonic_m << "m, "
-              << "altitude_local" << altitude.altitude_local_m << "m, "
-              << "altitude_amsl" << altitude.altitude_amsl_m << "m, "
-              << "altitude_relative" << altitude.altitude_relative_m << "m, "
-              << "altitude_terrain" << altitude.altitude_terrain_m << "m" << std::endl;
+              << "altitude_local" << altitude.altitude_local_m << "m, " << "altitude_amsl"
+              << altitude.altitude_amsl_m << "m, " << "altitude_relative"
+              << altitude.altitude_relative_m << "m, " << "altitude_terrain"
+              << altitude.altitude_terrain_m << "m" << std::endl;
 
     _received_altitude = true;
 }