diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index b504469b6..741f4db41 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -31,4 +31,4 @@ register_component() # disable --coverage for this component, as it is used as transport # for gcov target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage") -target_link_libraries(${COMPONENT_LIB} gcov ${LIBC} ${LIBM}) +target_link_libraries(${COMPONENT_LIB} gcov ${LIBC} ${LIBM} gcc) diff --git a/components/bootloader/subproject/main/bootloader_start.c b/components/bootloader/subproject/main/bootloader_start.c index 780c1326e..7a7e76aa6 100644 --- a/components/bootloader/subproject/main/bootloader_start.c +++ b/components/bootloader/subproject/main/bootloader_start.c @@ -111,3 +111,9 @@ static int selected_boot_partition(const bootloader_state_t *bs) } return boot_index; } + +// Return global reent struct if any newlib functions are linked to bootloader +struct _reent* __getreent() { + return _GLOBAL_REENT; +} + diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 526ad92a1..d1373be30 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -9,8 +9,8 @@ set(COMPONENT_SRCS "src/bootloader_clock.c" if(BOOTLOADER_BUILD) set(COMPONENT_ADD_INCLUDEDIRS "include include_bootloader") - set(COMPONENT_REQUIRES soc) #unfortunately the header directly uses SOC registers - set(COMPONENT_PRIV_REQUIRES spi_flash micro-ecc efuse) + set(COMPONENT_REQUIRES spi_flash soc) #unfortunately the header directly uses SOC registers + set(COMPONENT_PRIV_REQUIRES micro-ecc efuse) list(APPEND COMPONENT_SRCS "src/bootloader_init.c" "src/${IDF_TARGET}/bootloader_sha.c" "src/${IDF_TARGET}/flash_encrypt.c" diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index cb5609d2a..f1f9b35c2 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -2,7 +2,7 @@ set(COMPONENT_SRCS "cxx_exception_stubs.cpp" "cxx_guards.cpp") register_component() -target_link_libraries(${COMPONENT_LIB} stdc++) +target_link_libraries(${COMPONENT_LIB} stdc++ gcc) target_link_libraries(${COMPONENT_LIB} "-u __cxa_guard_dummy") if(NOT CONFIG_COMPILER_CXX_EXCEPTIONS) diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index c8816fc38..371023789 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -88,4 +88,13 @@ else() cpu_start.c PROPERTIES COMPILE_FLAGS -fno-stack-protector) + + if(CONFIG_SPIRAM_CACHE_WORKAROUND) + # Note: Adding as a PUBLIC compile option here causes this option to propagate to all components that depend on esp32. + # + # To handle some corner cases, the same flag is set in project_include.cmake + target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue) + # also, make sure we link with this option so correct toolchain libs are pulled in + target_link_libraries(${COMPONENT_LIB} -mfix-esp32-psram-cache-issue) + endif() endif() diff --git a/components/esp32/ld/esp32.project.ld.in b/components/esp32/ld/esp32.project.ld.in index 6b10c8694..a38abce64 100644 --- a/components/esp32/ld/esp32.project.ld.in +++ b/components/esp32/ld/esp32.project.ld.in @@ -267,12 +267,12 @@ SECTIONS __eh_frame = ABSOLUTE(.); KEEP(*(.eh_frame)) . = (. + 7) & ~ 3; - /* C++ constructor and destructor tables, properly ordered: */ + /* C++ constructor and destructor tables + + Make a point of not including anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt + */ __init_array_start = ABSOLUTE(.); - KEEP (*crtbegin.*(.ctors)) - KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .ctors .ctors.*)) __init_array_end = ABSOLUTE(.); KEEP (*crtbegin.*(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors)) diff --git a/components/esp_rom/CMakeLists.txt b/components/esp_rom/CMakeLists.txt index 468819a22..88a230c6a 100644 --- a/components/esp_rom/CMakeLists.txt +++ b/components/esp_rom/CMakeLists.txt @@ -25,12 +25,7 @@ else() ) target_linker_script(${COMPONENT_LIB} "${scripts}") - if(CONFIG_SPIRAM_CACHE_WORKAROUND) - # Note: Adding as a PUBLIC compile option here causes this option to propagate to all components that depend on esp32. - # - # To handle some corner cases, the same flag is set in project_include.cmake - target_compile_options(${COMPONENT_LIB} PUBLIC -mfix-esp32-psram-cache-issue) - else() + if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND) target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.newlib-funcs.ld") endif() diff --git a/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld b/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld index 811d879dd..9819556fc 100644 --- a/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld +++ b/components/esp_rom/esp32/ld/esp32.rom.syscalls.ld @@ -1,26 +1,3 @@ -/* These ROM functions call respective entries in syscall table. - IDF implementations of these function carry different names - (usually esp_vfs_*) so we still export these functions, - in case some newlib function needs to call them. - - I.e.: - - open (in ROM) -> _open_r (in ROM) -> syscall table entry _open_r -> esp_vfs_open (in IDF) - - */ - -PROVIDE ( _close_r = 0x4000bd3c ); -PROVIDE ( _exit_r = 0x4000bd28 ); -PROVIDE ( _fstat_r = 0x4000bccc ); -PROVIDE ( _link_r = 0x4000bc9c ); -PROVIDE ( _lseek_r = 0x4000bd8c ); -PROVIDE ( _open_r = 0x4000bd54 ); -PROVIDE ( _read_r = 0x4000bda8 ); -PROVIDE ( _rename_r = 0x4000bc28 ); -PROVIDE ( _unlink_r = 0x4000bc84 ); -PROVIDE ( _write_r = 0x4000bd70 ); - - /* These ROM functions call respective entries in the syscall table. They are called by other ROM functions (mostly from newlib). We don't link to them directly, since in IDF there are actual @@ -61,6 +38,16 @@ PROVIDE ( _realloc_r = 0x4000bbe0 ); PROVIDE ( _sbrk_r = 0x4000bce4 ); PROVIDE ( _system_r = 0x4000bc10 ); PROVIDE ( _times_r = 0x4000bc40 ); +PROVIDE ( _close_r = 0x4000bd3c ); +PROVIDE ( _exit_r = 0x4000bd28 ); +PROVIDE ( _fstat_r = 0x4000bccc ); +PROVIDE ( _link_r = 0x4000bc9c ); +PROVIDE ( _lseek_r = 0x4000bd8c ); +PROVIDE ( _open_r = 0x4000bd54 ); +PROVIDE ( _read_r = 0x4000bda8 ); +PROVIDE ( _rename_r = 0x4000bc28 ); +PROVIDE ( _unlink_r = 0x4000bc84 ); +PROVIDE ( _write_r = 0x4000bd70 ); ---> end commented out block */ diff --git a/components/esp_wifi/CMakeLists.txt b/components/esp_wifi/CMakeLists.txt index 218b4b644..be99e00d8 100644 --- a/components/esp_wifi/CMakeLists.txt +++ b/components/esp_wifi/CMakeLists.txt @@ -8,8 +8,8 @@ set(COMPONENT_SRCS "src/wifi_init.c") set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_PRIV_INCLUDEDIRS) -set(COMPONENT_REQUIRES) -set(COMPONENT_PRIV_REQUIRES "wpa_supplicant" "nvs_flash") +set(COMPONENT_REQUIRES wpa_supplicant smartconfig_ack) +set(COMPONENT_PRIV_REQUIRES "nvs_flash") if(NOT CONFIG_ESP32_NO_BLOBS) set(COMPONENT_ADD_LDFRAGMENTS "linker.lf") @@ -19,8 +19,20 @@ register_component() target_link_libraries(${COMPONENT_LIB} "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib_${IDF_TARGET}") if(NOT CONFIG_ESP32_NO_BLOBS) - target_link_libraries(${COMPONENT_LIB} "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib_${IDF_TARGET}") - target_link_libraries(${COMPONENT_LIB} coexist core espnow mesh net80211 phy pp rtc smartconfig wpa2 wpa wps) + set(blobs coexist core espnow mesh net80211 phy pp rtc smartconfig wpa2 wpa wps) + foreach(blob ${blobs}) + add_library(${blob} STATIC IMPORTED) + set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib_${IDF_TARGET}/lib${blob}.a) + target_link_libraries(${COMPONENT_LIB} ${blob}) + + foreach(_blob ${blobs}) + if(NOT _blob STREQUAL ${blob}) + set_property(TARGET ${blob} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${_blob}) + endif() + endforeach() + + set_property(TARGET ${blob} APPEND PROPERTY INTERFACE_LINK_LIBRARIES ${COMPONENT_LIB}) + endforeach() endif() if(CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION) diff --git a/components/newlib/CMakeLists.txt b/components/newlib/CMakeLists.txt index 627f092e8..8d5724cc4 100644 --- a/components/newlib/CMakeLists.txt +++ b/components/newlib/CMakeLists.txt @@ -12,16 +12,7 @@ set(COMPONENT_SRCS "heap.c" "utime.c") set(COMPONENT_ADD_INCLUDEDIRS platform_include) - if(GCC_NOT_5_2_0) - if(CONFIG_NEWLIB_NANO_FORMAT) - set(LIBC c_nano) - else() - set(LIBC c) - endif() - - set(LIBM m) - if(CONFIG_SPIRAM_CACHE_WORKAROUND) set(COMPONENT_ADD_LDFRAGMENTS esp32-spiram-rom-functions-c.lf) endif() @@ -31,7 +22,7 @@ if(GCC_NOT_5_2_0) set(EXTRA_LINK_FLAGS "-u newlib_include_locks_impl") list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_heap_impl") list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_syscalls_impl") - + list(APPEND EXTRA_LINK_FLAGS "-u newlib_include_pthread_impl") else() # Remove this section when GCC 5.2.0 is no longer supported # 'include' and 'lib' directories should also be removed. @@ -40,21 +31,10 @@ else() set(LIB_PATH ${CMAKE_CURRENT_SOURCE_DIR}/lib) if(CONFIG_SPIRAM_CACHE_WORKAROUND) - set(LIBC c-psram-workaround) - set(LIBM m-psram-workaround) - set(COMPONENT_ADD_LDFRAGMENTS esp32-spiram-rom-functions-psram-workaround.lf) - else() - - if(CONFIG_NEWLIB_NANO_FORMAT) - set(LIBC c_nano) - else() - set(LIBC c) - endif() - - set(LIBM m) endif() endif() + set(COMPONENT_REQUIRES vfs) # for sys/ioctl.h set(COMPONENT_PRIV_REQUIRES soc) @@ -70,10 +50,10 @@ if(GCC_NOT_5_2_0) # Toolchain libraries require code defined in this component add_library(extra INTERFACE) idf_component_get_property(newlib newlib COMPONENT_LIB) - target_link_libraries(extra INTERFACE ${LIBC} ${LIBM} "$") + target_link_libraries(extra INTERFACE ${LIBC} ${LIBM} gcc "$") target_link_libraries(${COMPONENT_LIB} extra) else() - target_link_libraries(${COMPONENT_LIB} ${LIBC} ${LIBM}) + target_link_libraries(${COMPONENT_LIB} ${LIBC} ${LIBM} gcc) endif() set_source_files_properties(heap.c PROPERTIES COMPILE_FLAGS -fno-builtin) diff --git a/components/newlib/project_include.cmake b/components/newlib/project_include.cmake new file mode 100644 index 000000000..367794a1d --- /dev/null +++ b/components/newlib/project_include.cmake @@ -0,0 +1,22 @@ +if(GCC_NOT_5_2_0) + if(CONFIG_NEWLIB_NANO_FORMAT) + set(LIBC c_nano) + else() + set(LIBC c) + endif() + + set(LIBM m) +else() + if(CONFIG_SPIRAM_CACHE_WORKAROUND) + set(LIBC c-psram-workaround) + set(LIBM m-psram-workaround) + else() + if(CONFIG_NEWLIB_NANO_FORMAT) + set(LIBC c_nano) + else() + set(LIBC c) + endif() + + set(LIBM m) + endif() +endif() \ No newline at end of file diff --git a/components/newlib/pthread.c b/components/newlib/pthread.c index c917a22ab..3c982f483 100644 --- a/components/newlib/pthread.c +++ b/components/newlib/pthread.c @@ -13,3 +13,8 @@ int pthread_setcancelstate(int state, int *oldstate) { return 0; } + +void newlib_include_pthread_impl() +{ + // Linker hook, exists for no other purpose +} diff --git a/components/protocomm/CMakeLists.txt b/components/protocomm/CMakeLists.txt index 9f9343815..79e824ceb 100644 --- a/components/protocomm/CMakeLists.txt +++ b/components/protocomm/CMakeLists.txt @@ -12,7 +12,8 @@ set(COMPONENT_SRCS "src/common/protocomm.c" "src/transports/protocomm_console.c" "src/transports/protocomm_httpd.c") -set(COMPONENT_PRIV_REQUIRES protobuf-c mbedtls console esp_http_server bt) +set(COMPONENT_REQUIRES protobuf-c bt) +set(COMPONENT_PRIV_REQUIRES mbedtls console esp_http_server) if(CONFIG_BT_ENABLED) if(CONFIG_BT_BLUEDROID_ENABLED) diff --git a/components/vfs/CMakeLists.txt b/components/vfs/CMakeLists.txt index 816e7a6d8..1d8fb06ec 100644 --- a/components/vfs/CMakeLists.txt +++ b/components/vfs/CMakeLists.txt @@ -3,3 +3,7 @@ set(COMPONENT_SRCS "vfs.c" "vfs_semihost.c") set(COMPONENT_ADD_INCLUDEDIRS "include") register_component() + +# Some newlib syscalls are implemented in vfs.c, make sure these are always +# seen by the linker +target_link_libraries(${COMPONENT_LIB} "-u vfs_include_syscalls_impl") diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index c64d831f7..19f081c5a 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -544,6 +544,34 @@ int esp_vfs_rename(struct _reent *r, const char *src, const char *dst) return ret; } +/* Create aliases for newlib syscalls + + These functions are also available in ROM as stubs which use the syscall table, but linking them + directly here saves an additional function call when a software function is linked to one, and + makes linking with -stdlib easier. + */ +int _open_r(struct _reent *r, const char * path, int flags, int mode) + __attribute__((alias("esp_vfs_open"))); +ssize_t _write_r(struct _reent *r, int fd, const void * data, size_t size) + __attribute__((alias("esp_vfs_write"))); +off_t _lseek_r(struct _reent *r, int fd, off_t size, int mode) + __attribute__((alias("esp_vfs_lseek"))); +ssize_t _read_r(struct _reent *r, int fd, void * dst, size_t size) + __attribute__((alias("esp_vfs_read"))); +int _close_r(struct _reent *r, int fd) + __attribute__((alias("esp_vfs_close"))); +int _fstat_r(struct _reent *r, int fd, struct stat * st) + __attribute__((alias("esp_vfs_fstat"))); +int _stat_r(struct _reent *r, const char * path, struct stat * st) + __attribute__((alias("esp_vfs_stat"))); +int _link_r(struct _reent *r, const char* n1, const char* n2) + __attribute__((alias("esp_vfs_link"))); +int _unlink_r(struct _reent *r, const char *path) + __attribute__((alias("esp_vfs_unlink"))); +int _rename_r(struct _reent *r, const char *src, const char *dst) + __attribute__((alias("esp_vfs_rename"))); + + DIR* opendir(const char* name) { const vfs_entry_t* vfs = get_vfs_for_path(name); @@ -1193,3 +1221,8 @@ int esp_vfs_poll(struct pollfd *fds, nfds_t nfds, int timeout) return ret; } + +void vfs_include_syscalls_impl() +{ + // Linker hook function, exists to make the linker examine this fine +} diff --git a/docs/en/api-guides/build-system-cmake.rst b/docs/en/api-guides/build-system-cmake.rst index a3c068bf9..36c90e686 100644 --- a/docs/en/api-guides/build-system-cmake.rst +++ b/docs/en/api-guides/build-system-cmake.rst @@ -454,8 +454,6 @@ The order of components in the ``BUILD_COMPONENTS`` variable determines other or - Order that :ref:`project_include.cmake` files are included into the project. - Order that the list of header paths is generated for compilation (via ``-I`` argument). (Note that for a given component's source files, only that component's dependency's header paths are passed to the compiler.) -- Order that component object archives are passed to the linker (note that the build system also passes ``--start-group`` and ``--end-group`` to the linker to allow cycles in linker dependencies, however the basic order is determined by ``BUILD_COMPONENTS``. - Build Process Internals ======================= diff --git a/docs/zh_CN/api-guides/build-system-cmake.rst b/docs/zh_CN/api-guides/build-system-cmake.rst index 96b46aa92..19d766a83 100644 --- a/docs/zh_CN/api-guides/build-system-cmake.rst +++ b/docs/zh_CN/api-guides/build-system-cmake.rst @@ -451,7 +451,6 @@ ESP-IDF 构建系统会在命令行中添加以下 C 预处理器定义: - 项目导入 :ref:`project_include.cmake` 文件的顺序。 - 生成用于编译(通过 ``-I`` 参数)的头文件路径列表的顺序。请注意,对于给定组件的源文件,仅需将该组件的依赖组件的头文件路径告知编译器。 -- 组件目标归档文件传递给链接器的顺序。请注意,构建系统还会将 ``--start-group`` 和 ``--end-group`` 传递给链接器,以允许链接依赖存在闭环,但其基本顺序还是由 ``BUILD_COMPONENTS`` 决定的。 构建的内部过程 ============== diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 306486c16..585d26e19 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -454,10 +454,10 @@ macro(idf_build_process target) set(ESP_PLATFORM 1) idf_build_set_property(COMPILE_DEFINITIONS "-DESP_PLATFORM" APPEND) - __build_process_project_includes() - # Perform component processing (inclusion of project_include.cmake, adding component # subdirectories, creating library targets, linking libraries, etc.) + __build_process_project_includes() + idf_build_get_property(idf_path IDF_PATH) add_subdirectory(${idf_path} ${build_dir}/esp-idf) diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 3726fa0fb..754e4a2fd 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -356,8 +356,6 @@ macro(project project_name) add_executable(${project_elf} "${project_elf_src}") add_dependencies(${project_elf} _project_elf_src) - target_link_libraries(${project_elf} "-Wl,--start-group") - if(test_components) target_link_libraries(${project_elf} "-Wl,--whole-archive") foreach(test_component ${test_components}) diff --git a/tools/cmake/toolchain-esp32.cmake b/tools/cmake/toolchain-esp32.cmake index b311d7ab6..b63ae5a86 100644 --- a/tools/cmake/toolchain-esp32.cmake +++ b/tools/cmake/toolchain-esp32.cmake @@ -4,6 +4,8 @@ set(CMAKE_C_COMPILER xtensa-esp32-elf-gcc) set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++) set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc) -set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags") set(CMAKE_C_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C Compiler Base Flags") set(CMAKE_CXX_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C++ Compiler Base Flags") + +# Can be removed after gcc 5.2.0 support is removed (ref GCC_NOT_5_2_0) +set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags")