Merge branch 'feature/clang_toolchain_compat' into 'master'

Build system: minimal changes for clang compatibility

See merge request espressif/esp-idf!15168
This commit is contained in:
Ivan Grokhotkov 2021-09-23 08:19:09 +00:00
commit 8f0ee18931
16 changed files with 149 additions and 33 deletions

View File

@ -20,7 +20,9 @@ if(NOT BOOTLOADER_BUILD)
if(CONFIG_COMPILER_OPTIMIZATION_SIZE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND compile_options "-freorder-blocks")
endif()
elseif(CONFIG_COMPILER_OPTIMIZATION_DEFAULT)
list(APPEND compile_options "-Og")
elseif(CONFIG_COMPILER_OPTIMIZATION_NONE)
@ -33,7 +35,9 @@ else() # BOOTLOADER_BUILD
if(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE)
list(APPEND compile_options "-Os")
list(APPEND compile_options "-freorder-blocks")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND compile_options "-freorder-blocks")
endif()
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
list(APPEND compile_options "-Og")
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
@ -74,6 +78,48 @@ if(CONFIG_COMPILER_DISABLE_GCC8_WARNINGS)
"-Wno-int-in-bool-context")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND c_compile_options "-Wno-old-style-declaration")
endif()
# Clang finds some warnings in IDF code which GCC doesn't.
# All these warnings should be fixed before Clang is presented
# as a toolchain choice for users.
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
# Clang checks Doxygen comments for being in sync with function prototype.
# There are some inconsistencies, especially in ROM headers.
list(APPEND compile_options "-Wno-documentation")
# GCC allows repeated typedefs when the source and target types are the same.
# Clang doesn't allow this. This occurs in many components due to forward
# declarations.
list(APPEND compile_options "-Wno-typedef-redefinition")
# This issue is seemingly related to newlib's char type functions.
# Fix is not clear yet.
list(APPEND compile_options "-Wno-char-subscripts")
# Clang seems to notice format string issues which GCC doesn't.
list(APPEND compile_options "-Wno-format-security")
# Logic bug in essl component
list(APPEND compile_options "-Wno-tautological-overlap-compare")
# Some pointer checks in mDNS component check addresses which can't be NULL
list(APPEND compile_options "-Wno-tautological-pointer-compare")
# Similar to the above, in tcp_transport
list(APPEND compile_options "-Wno-pointer-bool-conversion")
# mbedTLS md5.c triggers this warning in md5_test_buf (false positive)
list(APPEND compile_options "-Wno-string-concatenation")
# multiple cases of implict convertions between unrelated enum types
list(APPEND compile_options "-Wno-enum-conversion")
# When IRAM_ATTR is specified both in function declaration and definition,
# it produces different section names, since section names include __COUNTER__.
# Occurs in multiple places.
list(APPEND compile_options "-Wno-section")
# Multiple cases of attributes unknown to clang, for example
# __attribute__((optimize("-O3")))
list(APPEND compile_options "-Wno-unknown-attributes")
# Clang also produces many -Wunused-function warnings which GCC doesn't.
# However these aren't treated as errors.
endif()
# More warnings may exist in unit tests and example projects.
if(CONFIG_COMPILER_WARN_WRITE_STRINGS)
list(APPEND compile_options "-Wwrite-strings")
endif()
@ -118,7 +164,15 @@ list(APPEND link_options "-fno-lto")
# Placing jump tables in flash would cause issues with code that required
# to be placed in IRAM
list(APPEND compile_options "-fno-jump-tables")
list(APPEND compile_options "-fno-tree-switch-conversion")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
# This flag is GCC-specific.
# Not clear yet if some other flag should be used for Clang.
list(APPEND compile_options "-fno-tree-switch-conversion")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
list(APPEND compile_options "-fno-use-cxa-atexit")
endif()
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)

View File

@ -13,3 +13,8 @@ idf_component_register(SRCS "tinycbor/src/cborencoder_close_container_checked.c"
# for open_memstream.c
set_source_files_properties(tinycbor/src/open_memstream.c PROPERTIES COMPILE_DEFINITIONS "__linux__")
# workaround for the fact that we are passing -ffreestanding to Clang
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
target_compile_options(${COMPONENT_LIB} PRIVATE "-U __STDC_HOSTED__")
endif()

View File

@ -6,3 +6,7 @@ idf_component_register(SRCS "commands.c"
INCLUDE_DIRS "."
REQUIRES vfs
PRIV_REQUIRES driver)
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
set_source_files_properties(argtable3/argtable3.c PROPERTIES COMPILE_FLAGS -Wno-clobbered)
endif()

View File

@ -30,8 +30,6 @@
#include "argtable3.h"
#pragma GCC diagnostic ignored "-Wclobbered"
/*******************************************************************************
* This file is part of the argtable3 library.
*

View File

@ -1,2 +1,4 @@
COMPONENT_ADD_INCLUDEDIRS := .
COMPONENT_SRCDIRS := linenoise argtable3 .
argtable3/argtable3.o: CFLAGS += -Wno-clobbered

View File

@ -1,8 +1,12 @@
#
# Warn if the toolchain version doesn't match
#
if(NOT ${target} STREQUAL "linux")
if(NOT (${target} STREQUAL "linux" OR CMAKE_C_COMPILER_ID MATCHES "Clang"))
get_expected_ctng_version(expected_toolchain expected_gcc)
gcc_version_check("${expected_gcc}")
crosstool_version_check("${expected_toolchain}")
endif()
if(NOT ${target} STREQUAL "linux" AND CMAKE_C_COMPILER_ID MATCHES "Clang")
message(WARNING "Building ESP-IDF with clang is an experimental feature and is not yet officially supported.")
endif()

View File

@ -399,7 +399,7 @@ void IRAM_ATTR __attribute__((noreturn, no_sanitize_undefined)) panic_abort(cons
#endif
#endif
*((int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets
*((volatile int *) 0) = 0; // NOLINT(clang-analyzer-core.NullDereference) should be an invalid operation on targets
while (1);
}

View File

@ -94,8 +94,10 @@ int _fstat_r (struct _reent *r, int fd, struct stat *st)
* doesn't have the same signature as the original function.
* Disable type mismatch warnings for this reason.
*/
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wattribute-alias"
#endif
int _open_r(struct _reent *r, const char * path, int flags, int mode)
__attribute__((weak,alias("syscall_not_implemented")));
@ -133,7 +135,9 @@ int _kill_r(struct _reent *r, int pid, int sig)
void _exit(int __status)
__attribute__((alias("syscall_not_implemented_aborts")));
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic pop
#endif
/* Similar to syscall_not_implemented, but not taking struct _reent argument */
int system(const char* str)

View File

@ -55,5 +55,9 @@ idf_component_register(SRCS "${srcs}"
LDFRAGMENTS linker.lf)
# Avoid cache miss by unexpected inlineing when built by -Os
set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS
"-fno-inline-functions -fno-inline-small-functions -fno-inline-functions-called-once")
set_source_files_properties(${cache_srcs} PROPERTIES COMPILE_FLAGS "-fno-inline-functions")
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
# These flags are GCC specific
set_property(SOURCE ${cache_srcs} APPEND_STRING PROPERTY COMPILE_FLAGS
" -fno-inline-small-functions -fno-inline-functions-called-once")
endif()

View File

@ -408,4 +408,4 @@ esp_err_t spi_flash_chip_generic_suspend_cmd_conf(esp_flash_t *chip);
esp_err_t spi_flash_chip_generic_read_unique_id_none(esp_flash_t *chip, uint64_t* flash_unique_id);
/// Default timeout configuration used by most chips
const flash_chip_op_timeout_t spi_flash_chip_generic_timeout;
extern const flash_chip_op_timeout_t spi_flash_chip_generic_timeout;

View File

@ -10,4 +10,6 @@ idf_component_register(SRCS "esp_spiffs.c"
REQUIRES spi_flash
PRIV_REQUIRES bootloader_support esptool_py)
set_source_files_properties(spiffs/src/spiffs_nucleus.c PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation)
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
set_source_files_properties(spiffs/src/spiffs_nucleus.c PROPERTIES COMPILE_FLAGS -Wno-stringop-truncation)
endif()

View File

@ -446,12 +446,6 @@ function run_tests()
mv CMakeLists.bak CMakeLists.txt
assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN}
print_status "Can find toolchain file in component directory"
clean_build_dir
mv ${IDF_PATH}/tools/cmake/toolchain-esp32.cmake ${IDF_PATH}/components/esp32/
(idf.py reconfigure > /dev/null && grep "${IDF_PATH}/components/esp32/toolchain-esp32.cmake" build/CMakeCache.txt) || failure "Failed to find toolchain file in component directory"
mv ${IDF_PATH}/components/esp32/toolchain-esp32.cmake ${IDF_PATH}/tools/cmake/
print_status "Setting EXTRA_COMPONENT_DIRS works"
clean_build_dir
(idf.py reconfigure | grep "$PWD/main") || failure "Failed to verify original `main` directory"

View File

@ -107,8 +107,7 @@ function(__build_set_default_build_specifications)
# go into the final binary so have no impact on size
"-ggdb")
list(APPEND c_compile_options "-std=gnu99"
"-Wno-old-style-declaration")
list(APPEND c_compile_options "-std=gnu99")
list(APPEND cxx_compile_options "-std=gnu++11")

View File

@ -47,23 +47,37 @@ endfunction()
#
macro(__target_set_toolchain)
idf_build_get_property(idf_path IDF_PATH)
# See if Clang toolchain should be used
set(env_idf_toolchain $ENV{IDF_TOOLCHAIN})
if(NOT env_idf_toolchain)
# IDF_TOOLCHAIN not set in environment, see if it is set in cache
if(IDF_TOOLCHAIN)
set(env_idf_toolchain ${IDF_TOOLCHAIN})
else()
set(env_idf_toolchain gcc)
endif()
else()
# IDF_TOOLCHAIN set both in environment and in cache, must be the same
if(NOT ${IDF_TOOLCHAIN} STREQUAL ${env_idf_toolchain})
message(FATAL_ERROR "IDF_TOOLCHAIN in CMake cache does not match "
"IDF_TOOLCHAIN environment variable. To change the toolchain, clear "
"the build directory and sdkconfig file, and build the project again")
endif()
endif()
# Finally, set IDF_TOOLCHAIN in cache
set(IDF_TOOLCHAIN ${env_idf_toolchain} CACHE STRING "IDF Build Toolchain Type")
if(${env_idf_toolchain} STREQUAL "clang")
set(toolchain_type "clang-")
endif()
# First try to load the toolchain file from the tools/cmake/directory of IDF
set(toolchain_file_global ${idf_path}/tools/cmake/toolchain-${IDF_TARGET}.cmake)
set(toolchain_file_global ${idf_path}/tools/cmake/toolchain-${toolchain_type}${IDF_TARGET}.cmake)
if(EXISTS ${toolchain_file_global})
set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_global})
else()
__component_get_target(component_target ${IDF_TARGET})
if(NOT component_target)
message(FATAL_ERROR "Unable to resolve '${IDF_TARGET}' for setting toolchain file.")
endif()
get_property(component_dir TARGET ${component_target} PROPERTY COMPONENT_DIR)
# Try to load the toolchain file from the directory of IDF_TARGET component
set(toolchain_file_component ${component_dir}/toolchain-${IDF_TARGET}.cmake)
if(EXISTS ${toolchain_file_component})
set(CMAKE_TOOLCHAIN_FILE ${toolchain_file_component})
else()
message(FATAL_ERROR "Toolchain file toolchain-${IDF_TARGET}.cmake not found,"
"checked ${toolchain_file_global} and ${toolchain_file_component}")
endif()
message(FATAL_ERROR "Toolchain file ${toolchain_file_global} not found")
endif()
endmacro()

View File

@ -0,0 +1,16 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_AR xtensa-esp32-elf-ar)
set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib)
set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
# -freestanding is a hack to force Clang to use its own stdatomic.h,
# without falling back to the (incompatible) GCC stdatomic.h
# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18
set(CMAKE_C_FLAGS "--target=xtensa -mcpu=esp32 -ffreestanding" CACHE STRING "C Compiler Base Flags")
set(CMAKE_CXX_FLAGS "--target=xtensa -mcpu=esp32 -ffreestanding" CACHE STRING "C++ Compiler Base Flags")
set(CMAKE_ASM_FLAGS "--target=xtensa -mcpu=esp32" CACHE STRING "Assembler Base Flags")

View File

@ -0,0 +1,16 @@
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER clang)
set(CMAKE_AR xtensa-esp32-elf-ar)
set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib)
set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
# -freestanding is a hack to force Clang to use its own stdatomic.h,
# without falling back to the (incompatible) GCC stdatomic.h
# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18
set(CMAKE_C_FLAGS "--target=xtensa -mcpu=esp32s2 -ffreestanding" CACHE STRING "C Compiler Base Flags")
set(CMAKE_CXX_FLAGS "--target=xtensa -mcpu=esp32s2 -ffreestanding" CACHE STRING "C++ Compiler Base Flags")
set(CMAKE_ASM_FLAGS "--target=xtensa -mcpu=esp32s2" CACHE STRING "Assembler Base Flags")