mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
cxx: gnu++23 -> gnu++2b for clang compatibility, added docs and test
* Using -std=gnu++2b now for both gcc and clang as clang does not recognize gnu++23 yet * Added a build test app to check the C++ standard in IDF * Updated english docs to reflect the change to C++23
This commit is contained in:
parent
58fa57af93
commit
2379ee36ab
@ -32,7 +32,7 @@ extern "C" {
|
||||
* - MACRO_ARGS(__VA_ARGS__) if __VA_ARGS__ was not empty
|
||||
* - MACRO_NO_ARGS() if __VA_ARGS__ was empty
|
||||
*
|
||||
* @note In the future, we want to switch to C++20. We also want to become compatible with clang. Hence, we provide two
|
||||
* @note In the future, we want to become compatible with clang. Hence, we provide two
|
||||
* versions of the following macros which are using variadic arguments. One is using the GNU extension ##__VA_ARGS__.
|
||||
* The other is using the C++20 feature __VA_OPT__(,). This allows users to compile their code with standard C++20
|
||||
* enabled instead of the GNU extension. Below C++20, we haven't found any good alternative to using ##__VA_ARGS__.
|
||||
|
@ -288,7 +288,7 @@ void esp_log_writev(esp_log_level_t level, const char* tag, const char* format,
|
||||
/// Log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``,``ESP_DRAM_LOGE``
|
||||
|
||||
/**
|
||||
* In the future, we want to switch to C++20. We also want to become compatible with clang.
|
||||
* In the future, we want to become compatible with clang.
|
||||
* Hence, we provide two versions of the following macros which are using variadic arguments.
|
||||
* The first one is using the GNU extension \#\#__VA_ARGS__. The second one is using the C++20 feature __VA_OPT__(,).
|
||||
* This allows users to compile their code with standard C++20 enabled instead of the GNU extension.
|
||||
|
@ -23,14 +23,14 @@ esp-idf-cxx Component
|
||||
C++ language standard
|
||||
---------------------
|
||||
|
||||
By default, ESP-IDF compiles C++ code with C++20 language standard with GNU extensions (``-std=gnu++20``).
|
||||
By default, ESP-IDF compiles C++ code with C++23 language standard with GNU extensions (``-std=gnu++23``).
|
||||
|
||||
To compile the source code of a certain component using a different language standard, set the desired compiler flag in the component CMakeLists.txt file:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
idf_component_register( ... )
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -std=gnu++2b)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -std=gnu++11)
|
||||
|
||||
Use ``PUBLIC`` instead of ``PRIVATE`` if the public header files of the component also need to be compiled with the same language standard.
|
||||
|
||||
@ -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
|
||||
|
@ -54,7 +54,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 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 */
|
||||
|
@ -127,9 +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)
|
||||
set(cxx_std gnu++23)
|
||||
set(cxx_std gnu++2b)
|
||||
else()
|
||||
enable_language(C CXX)
|
||||
# Building for Linux target, fall back to an older version of the standard
|
||||
@ -149,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)
|
||||
|
@ -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,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)
|
||||
|
@ -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);
|
Loading…
Reference in New Issue
Block a user