diff --git a/.github/workflows/action_tools.yml b/.github/workflows/action_tools.yml index b3e1b954d4e5..c9111de9d0fb 100644 --- a/.github/workflows/action_tools.yml +++ b/.github/workflows/action_tools.yml @@ -67,6 +67,7 @@ jobs: - name: Build Tools run: | source ~/.env/env.sh + export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin scons --pyconfig-silent -C $TEST_BSP_ROOT 2>menuconfig.log cat menuconfig.log if grep -q "warning:" menuconfig.log; then @@ -79,6 +80,8 @@ jobs: - name: Project generate Tools if: ${{ success() }} run: | + source ~/.env/env.sh + export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin echo "Test to generate eclipse project" scons --target=eclipse -s -C $TEST_BSP_ROOT echo "Test to generate cmake project" @@ -89,6 +92,8 @@ jobs: - name: Project dist Tools if: ${{ success() }} run: | + source ~/.env/env.sh + export RTT_EXEC_PATH=/opt/gcc-arm-none-eabi-10-2020-q4-major/bin echo "Test to dist project" scons --dist -C $TEST_BSP_ROOT scons --dist-ide -C $TEST_BSP_ROOT diff --git a/bsp/renesas/libraries/Kconfig b/bsp/renesas/libraries/Kconfig index 1d0aff98aa8d..acc50d0734d5 100644 --- a/bsp/renesas/libraries/Kconfig +++ b/bsp/renesas/libraries/Kconfig @@ -1,14 +1,19 @@ +# The FSP startup runtime (SystemInit()/startup) already walks .init_array, +# so RT-Thread must skip that range to keep constructors running exactly once. config SOC_FAMILY_RENESAS_RA bool + select RT_USING_CPP_CRT_INIT if RT_USING_CPLUSPLUS default n config SOC_FAMILY_RENESAS_RA_WIRELESS bool + select RT_USING_CPP_CRT_INIT if RT_USING_CPLUSPLUS default n config SOC_FAMILY_RENESAS_RZ bool + select RT_USING_CPP_CRT_INIT if RT_USING_CPLUSPLUS default n config SOC_SERIES_R7FA6M3 diff --git a/components/libc/cplusplus/Kconfig b/components/libc/cplusplus/Kconfig index 1dcc6f389ce7..749a3ab0a5c8 100644 --- a/components/libc/cplusplus/Kconfig +++ b/components/libc/cplusplus/Kconfig @@ -4,6 +4,19 @@ menuconfig RT_USING_CPLUSPLUS if RT_USING_CPLUSPLUS + config RT_USING_CPP_CRT_INIT + bool "Startup runtime already runs .init_array constructors" + default y if SOC_SIMULATOR + default n + help + Enable this for GCC ports whose startup runtime already walks the + .init_array section, so that RT-Thread skips it and does not run + the constructors twice. RT-Thread still walks the ctors range. + This option is usually set by the BSP; do not change it manually. + Leave this disabled when the startup code relies on the empty + __libc_init_array provided by RT-Thread's newlib port, which + defers constructors to RT-Thread. + config RT_USING_CPLUSPLUS11 bool "Enable C++11 standard multi-threading feature support" default n diff --git a/components/libc/cplusplus/cxx_crt_init.c b/components/libc/cplusplus/cxx_crt_init.c index c5d1e434b5e1..be8619051f32 100644 --- a/components/libc/cplusplus/cxx_crt_init.c +++ b/components/libc/cplusplus/cxx_crt_init.c @@ -40,8 +40,8 @@ rt_weak void *__dso_handle = 0; * @note If there is no SHT$$INIT_ARRAY section, calling $Super$$__cpp_initialize__aeabi_() will cause an error * in ARMCC compiler. Therefore, this function manually iterates through the base addresses of the * SHT$$INIT_ARRAY section to call the constructor functions of each object. In GCC compiler, this function - * uses the __ctors_start__ and __ctors_end__ global variables to determine the range of constructor function - * pointers and calls each constructor function of every object in that range. + * always walks the ctors range; RT_USING_CPP_CRT_INIT only indicates that the startup runtime already + * walked the init_array range. * * @return Returns 0 if the initialization of the C++ runtime environment is successful. Otherwise, it returns * an error code indicating the failure of the operation. @@ -67,12 +67,43 @@ rt_weak int cplusplus_system_init(void) } #elif defined(__GNUC__) typedef void(*pfunc)(); - extern pfunc __ctors_start__[]; - extern pfunc __ctors_end__[]; + /* Linker scripts may provide the ctors range, the init_array range, or both. */ + extern pfunc __ctors_start__[] __attribute__((weak)); + extern pfunc __ctors_end__[] __attribute__((weak)); + pfunc *ctors_start = __ctors_start__; + pfunc *ctors_end = __ctors_end__; +#ifndef RT_USING_CPP_CRT_INIT + extern pfunc __init_array_start[] __attribute__((weak)); + extern pfunc __init_array_end[] __attribute__((weak)); + pfunc *init_start = __init_array_start; + pfunc *init_end = __init_array_end; +#endif pfunc *p; - for (p = __ctors_start__; p < __ctors_end__; p++) - (*p)(); + if (ctors_start && ctors_end) + { + for (p = ctors_start; (uintptr_t)p < (uintptr_t)ctors_end; p++) + { + (*p)(); + } + } + +#ifndef RT_USING_CPP_CRT_INIT + if (init_start && init_end) + { + for (p = init_start; (uintptr_t)p < (uintptr_t)init_end; p++) + { + /* Skip entries already called through the ctors range. */ + if (ctors_start && ctors_end && + (uintptr_t)p >= (uintptr_t)ctors_start && + (uintptr_t)p < (uintptr_t)ctors_end) + { + continue; + } + (*p)(); + } + } +#endif #endif return 0;