Przeglądaj źródła

cmake: Corrected setting of C++ language standard

* reverted old faulty mechanism to set different
  standard according to the toolchain
* Using -std=gnu++2b now for both gcc and clang
* Added a build test app to check the C++ standard in IDF
* Updated english docs to reflect the change to C++23
Jakob Hasse 2 lat temu
rodzic
commit
0244c24c8d

+ 2 - 1
docs/en/api-guides/cplusplus.rst

@@ -132,13 +132,14 @@ ESP-IDF expects the application entry point, ``app_main``, to be defined with C
     {
     }
 
+.. _cplusplus_designated_initializers:
 
 Designated initializers
 ^^^^^^^^^^^^^^^^^^^^^^^
 
 Many of the ESP-IDF components use :ref:`configuration structures <api_reference_config_structures>` as arguments to the initialization functions. ESP-IDF examples written in C routinely use `designated initializers <https://en.cppreference.com/w/c/language/struct_initialization>`_ to fill these structures in a readable and a maintainable way.
 
-C and C++ languages have different rules with regards to the designated initializers. For example, C++ language version C++20, currently the default in ESP-IDF, does not support out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays. Therefore, when porting ESP-IDF C examples to C++, some changes to the structure initializers may be necessary. See the `C++ aggregate initialization reference <https://en.cppreference.com/w/cpp/language/aggregate_initialization>`_ for more details.
+C and C++ languages have different rules with regards to the designated initializers. For example, C++ language version C++23, currently the default in ESP-IDF, does not support out-of-order designated initialization, nested designated initialization, mixing of designated initializers and regular initializers, and designated initialization of arrays. Therefore, when porting ESP-IDF C examples to C++, some changes to the structure initializers may be necessary. See the `C++ aggregate initialization reference <https://en.cppreference.com/w/cpp/language/aggregate_initialization>`_ for more details.
 
 
 iostream

+ 15 - 1
docs/en/api-reference/api-conventions.rst

@@ -55,7 +55,21 @@ Most ESP-IDF examples use C99 `designated initializers`_ for structure initializ
         /* Correct, fields .arg and .name are zero-initialized */
     };
 
-C++ language doesn't support the designated initializers syntax until C++20. However, the GCC compiler partially supports it as an extension. When using ESP-IDF APIs in C++ code, you may consider using the following pattern::
+The C++ language supports designated initializers syntax, too, but the initializers must be in the order of declaration. When using ESP-IDF APIs in C++ code, you may consider using the following pattern::
+
+    /* Correct, fields .dispatch_method, .name and .skip_unhandled_events are zero-initialized */
+    const esp_timer_create_args_t my_timer_args = {
+        .callback = &my_timer_callback,
+        .arg = &my_arg,
+    };
+
+    ///* Incorrect, .arg is declared after .callback in esp_timer_create_args_t */
+    //const esp_timer_create_args_t my_timer_args = {
+    //    .arg = &my_arg,
+    //    .callback = &my_timer_callback,
+    //};
+
+For more information on designated initializers, see :ref:`Designated initializers <cplusplus_designated_initializers>`. Note that C++ language versions older than C++20 (not the default in the current version of ESP-IDF) do not support designated initializers. If you have to compile code with an older C++ standard than C++20, you may use GCC extensions to produce the following pattern::
 
     esp_timer_create_args_t my_timer_args = {};
     /* All the fields are zero-initialized */

+ 4 - 8
tools/cmake/build.cmake

@@ -127,14 +127,10 @@ function(__build_set_lang_version)
     if(NOT IDF_TARGET STREQUAL "linux")
         # Building for chip targets: we use a known version of the toolchain.
         # Use latest supported versions.
-        # Please update docs/en/api-guides/cplusplus.rst when changing this.
+        # Please update docs/en/api-guides/cplusplus.rst and
+        # tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this.
         set(c_std gnu17)
-        if(NOT ${env_idf_toolchain} STREQUAL "clang")
-            set(cxx_std gnu++23)
-        else()
-            # TODO: IDF-7241 - remove the exception for clang
-            set(cxx_std gnu++20)
-        endif()
+        set(cxx_std gnu++2b)
     else()
         enable_language(C CXX)
         # Building for Linux target, fall back to an older version of the standard
@@ -154,7 +150,7 @@ function(__build_set_lang_version)
                                 "${preferred_c_versions}. Please upgrade the host compiler.")
         endif()
 
-        set(preferred_cxx_versions gnu++23 gnu++20 gnu++2a gnu++17 gnu++14)
+        set(preferred_cxx_versions gnu++2b gnu++20 gnu++2a gnu++17 gnu++14)
         set(ver_found FALSE)
         foreach(cxx_version ${preferred_cxx_versions})
             check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported)

+ 8 - 3
tools/test_apps/system/cxx_build_test/README.md

@@ -3,8 +3,13 @@
 
 # C++ build test
 
-This build-only app can be used to check if certain headers, macros or features can be successfully compiled in a C++ source file.
+This build-only app can be used to check if certain headers, macros or features can be successfully compiled in a C++ source file. It furthermore checks the current C++ language standard set in IDF is the expected one.
 
-To add a new test, create a new file `main/test_<name>.cpp` and add it to main/CMakeLists.txt.
+## This App Broke My Build :(
 
-If you need to check specific compiler flags, use `set_source_files_properties` CMake function to adjust the compilation flags for the given source file.
+It is likely that one of the following situations occurred:
+1. The language standard for IDF has been changed without changing the test in this application.
+2. Code incompatible to C++ has been added to one of the public header files in IDF. Check the C++ documentation section [Combining C and C++ code](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/cplusplus.html#combining-c-and-c-code) for more details.
+
+## Adding New Test
+Create a new file `main/test_<name>.cpp` and add it to main/CMakeLists.txt. If you need to check specific compiler flags, use `set_source_files_properties` CMake function to adjust the compilation flags for the given source file.

+ 1 - 0
tools/test_apps/system/cxx_build_test/main/CMakeLists.txt

@@ -1,6 +1,7 @@
 idf_component_register(SRCS cxx_build_test_main.cpp
                             test_soc_reg_macros.cpp
                             test_esp_hw_support.cpp
+                            test_cxx_standard.cpp
                        INCLUDE_DIRS "."
                        PRIV_REQUIRES driver
                        REQUIRES soc)

+ 10 - 0
tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp

@@ -0,0 +1,10 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+/*
+ * Current (2023-05-04) value for -std=gnu++23 and -std=gnu++2b.
+ * If you change the C++ standard for IDF, you also need to change this.
+ */
+static_assert(__cplusplus == 202100L);