cmake: Allow selecting toolchain file based on config

Refactor IDF "project" functionality under a wrapping of the default
"project" command, so we can tweak it a bit...

Will need more testing in other environments.
This commit is contained in:
Angus Gratton 2018-02-15 14:38:58 +11:00 committed by Angus Gratton
parent 04a944598f
commit abef220b13
6 changed files with 83 additions and 63 deletions

View file

@ -1,4 +1,4 @@
if(IS_BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
return() # don't keep recursing! return() # don't keep recursing!
endif() endif()

View file

@ -1,20 +1,17 @@
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/toolchain.cmake)
if(NOT SDKCONFIG) if(NOT SDKCONFIG)
message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed in by the parent build process.") message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed in by the parent build process.")
endif() endif()
project(bootloader ASM C CXX)
set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash micro-ecc soc) set(COMPONENTS bootloader esptool_py esp32 soc bootloader_support log spi_flash micro-ecc soc)
set(BOOTLOADER_BUILD 1) set(BOOTLOADER_BUILD 1)
set(IS_BOOTLOADER_BUILD 1) # deprecated, use BOOTLOADER_BUILD
add_definitions(-DBOOTLOADER_BUILD=1) add_definitions(-DBOOTLOADER_BUILD=1)
set(MAIN_SRCS main/bootloader_start.c) set(MAIN_SRCS main/bootloader_start.c)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(bootloader)
target_link_libraries(bootloader.elf "-L ${CMAKE_CURRENT_SOURCE_DIR}/main") target_link_libraries(bootloader.elf "-L ${CMAKE_CURRENT_SOURCE_DIR}/main")
target_link_libraries(bootloader.elf "-T esp32.bootloader.ld") target_link_libraries(bootloader.elf "-T esp32.bootloader.ld")

View file

@ -1,10 +1,8 @@
# The following five lines of boilerplate have to be in your project's CMakeLists # The following five lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly # in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5) cmake_minimum_required(VERSION 3.5)
set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/toolchain.cmake)
project(hello-world ASM C CXX)
set(MAIN_SRCS main/hello_world_main.c) set(MAIN_SRCS main/hello_world_main.c)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello-world)

View file

@ -2,6 +2,12 @@
include(crosstool_version_check) include(crosstool_version_check)
#
# Set some variables used by rest of the build
#
# Note at the time this macro is expanded, the config is not yet
# loaded and the toolchain and project are not yet set
#
macro(idf_set_global_variables) macro(idf_set_global_variables)
# Note that CONFIG_xxx is not available when this function is called # Note that CONFIG_xxx is not available when this function is called
@ -22,9 +28,6 @@ macro(idf_set_global_variables)
# Tell cmake to drop executables in the top-level build dir # Tell cmake to drop executables in the top-level build dir
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}") set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}")
# cmake cross-toolchain doesn't include any gcc binutils names
set(CMAKE_OBJCOPY xtensa-esp32-elf-objcopy)
# path to idf.py tool # path to idf.py tool
set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py") set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py")
@ -93,20 +96,18 @@ endfunction(idf_set_global_compiler_options)
function(idf_verify_environment) function(idf_verify_environment)
if(NOT CMAKE_PROJECT_NAME) if(NOT CMAKE_PROJECT_NAME)
message(FATAL_ERROR "Project top-level CMakeLists.txt file must call project() before including project.cmake") message(FATAL_ERROR "Internal error, IDF project.cmake should have set this variable already")
endif() endif()
# Check toolchain is configured properly in cmake # Check toolchain is configured properly in cmake
if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa)) if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa))
message(FATAL_ERROR "Project top-level CMakeLists.txt file needs to set CMAKE_TOOLCHAIN_FILE " message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project")
"before including project.cmake.\n"
"Update CMakeLists.txt to match the template project and delete CMakeCache.txt before "
"re-running cmake.")
endif() endif()
# #
# Warn if the toolchain version doesn't match # Warn if the toolchain version doesn't match
# #
# TODO: make these platform-specific for diff toolchains
gcc_version_check("5.2.0") gcc_version_check("5.2.0")
crosstool_version_check("1.22.0-80-g6c4433a") crosstool_version_check("1.22.0-80-g6c4433a")

View file

@ -24,55 +24,79 @@ include(idf_functions)
set_default(PYTHON "python") set_default(PYTHON "python")
# Verify the environment is configured correctly # project
idf_verify_environment()
# Set global variables used by rest of the build
idf_set_global_variables()
# Search COMPONENT_DIRS for COMPONENTS, make a list of full paths to each component in COMPONENT_PATHS
components_find_all("${COMPONENT_DIRS}" "${COMPONENTS}" COMPONENT_PATHS COMPONENTS)
kconfig_set_variables()
kconfig_process_config()
# Include sdkconfig.cmake so rest of the build knows the configuration
include(${SDKCONFIG_CMAKE})
# Add some idf-wide definitions
idf_set_global_compiler_options()
# Check git version (may trigger reruns of cmake)
# & set GIT_REVISION/IDF_VER variable
git_describe(GIT_REVISION)
add_definitions(-DIDF_VER=\"${GIT_REVISION}\")
git_submodule_check("${IDF_PATH}")
# Include any top-level project_include.cmake files from components
foreach(component ${COMPONENT_PATHS})
include_if_exists("${component}/project_include.cmake")
endforeach()
# #
# Add each component to the build as a library # This macro wraps the cmake 'project' command to add
# all of the IDF-specific functionality required
# #
foreach(component ${COMPONENT_PATHS}) # Implementation Note: This macro wraps 'project' on purpose, because cmake has some
get_filename_component(component_name ${component} NAME) # backwards-compatible magic where if you don't call "project" in the top-level
add_subdirectory(${component} ${component_name}) # CMakeLists file, it will call it implicitly. However, the implict project will not
endforeach() # have CMAKE_TOOLCHAIN_FILE set and therefore tries to create a native build project.
#
# Therefore, to keep all the IDF "build magic", the cleanest way is to keep the
# top-level "project" call but customize it to do what we want in the IDF build...
#
macro(project name)
# Set global variables used by rest of the build
idf_set_global_variables()
# # Search COMPONENT_DIRS for COMPONENTS, make a list of full paths to each component in COMPONENT_PATHS
# Add the app executable to the build (has name of PROJECT.elf) components_find_all("${COMPONENT_DIRS}" "${COMPONENTS}" COMPONENT_PATHS COMPONENTS)
#
idf_add_executable()
# Write project description JSON file kconfig_set_variables()
configure_file("${CMAKE_CURRENT_LIST_DIR}/project_description.json.in"
"${CMAKE_BINARY_DIR}/project_description.json")
# kconfig_process_config()
# Finish component registration (add cross-dependencies, make
# executable dependent on all components) # Include sdkconfig.cmake so rest of the build knows the configuration
# include(${SDKCONFIG_CMAKE})
components_finish_registration()
# Now the configuration is loaded, set the toolchain appropriately
#
# TODO: support more toolchains than just ESP32
set(CMAKE_TOOLCHAIN_FILE $ENV{IDF_PATH}/tools/cmake/toolchain-esp32.cmake)
# Declare the actual cmake-level project
_project(${name} ASM C CXX)
# Verify the environment is configured correctly
idf_verify_environment()
# Add some idf-wide definitions
idf_set_global_compiler_options()
# Check git version (may trigger reruns of cmake)
# & set GIT_REVISION/IDF_VER variable
git_describe(GIT_REVISION)
add_definitions(-DIDF_VER=\"${GIT_REVISION}\")
git_submodule_check("${IDF_PATH}")
# Include any top-level project_include.cmake files from components
foreach(component ${COMPONENT_PATHS})
include_if_exists("${component}/project_include.cmake")
endforeach()
#
# Add each component to the build as a library
#
foreach(component ${COMPONENT_PATHS})
get_filename_component(component_name ${component} NAME)
add_subdirectory(${component} ${component_name})
endforeach()
#
# Add the app executable to the build (has name of PROJECT.elf)
#
idf_add_executable()
# Write project description JSON file
configure_file("${IDF_PATH}/tools/cmake/project_description.json.in"
"${CMAKE_BINARY_DIR}/project_description.json")
#
# Finish component registration (add cross-dependencies, make
# executable dependent on all components)
#
components_finish_registration()
endmacro(project)