From 14e600801e4e5f62658dec8ae547b05ca4c6a049 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 10 Sep 2021 18:47:46 +0200 Subject: [PATCH] cmake: allow selection of clang based toolchain This is an experimental feature intended at the moment for ESP-IDF developers only. If IDF_TOOLCHAIN=clang environment variable or CMake variable is set, use toolchain-clang-esp32xx.cmake instead of toolchain-esp32xx.cmake. These changes aren't sufficient to actually build any IDF project with clang; subsequent commits add a few workarounds required to do this. Toolchain files are added for esp32 and esp32s2, which are the targets supported in our llvm-project fork at the moment. --- tools/cmake/targets.cmake | 28 ++++++++++++++++++++++- tools/cmake/toolchain-clang-esp32.cmake | 16 +++++++++++++ tools/cmake/toolchain-clang-esp32s2.cmake | 16 +++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 tools/cmake/toolchain-clang-esp32.cmake create mode 100644 tools/cmake/toolchain-clang-esp32s2.cmake diff --git a/tools/cmake/targets.cmake b/tools/cmake/targets.cmake index ecaaaf1818..07651f0c6e 100644 --- a/tools/cmake/targets.cmake +++ b/tools/cmake/targets.cmake @@ -47,8 +47,34 @@ 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() diff --git a/tools/cmake/toolchain-clang-esp32.cmake b/tools/cmake/toolchain-clang-esp32.cmake new file mode 100644 index 0000000000..bb25f98298 --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32.cmake @@ -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") diff --git a/tools/cmake/toolchain-clang-esp32s2.cmake b/tools/cmake/toolchain-clang-esp32s2.cmake new file mode 100644 index 0000000000..bb6e47bd0c --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32s2.cmake @@ -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")