# Some IDF-specific functions and functions 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) # Note that CONFIG_xxx is not available when this function is called set_default(EXTRA_COMPONENT_DIRS "") # Commmon components, required by every component in the build # set_default(COMPONENT_REQUIRES_COMMON "cxx ${IDF_TARGET} newlib freertos heap log soc") # PROJECT_PATH has the path to the IDF project (top-level cmake directory) # # (cmake calls this CMAKE_SOURCE_DIR, keeping old name for compatibility.) set(PROJECT_PATH "${CMAKE_SOURCE_DIR}") if(MAIN_SRCS) message(WARNING "main is now a component, use of MAIN_SRCS is deprecated") set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \ ${IDF_PATH}/components") else() set_default(COMPONENT_DIRS "${PROJECT_PATH}/components ${EXTRA_COMPONENT_DIRS} \ ${IDF_PATH}/components ${PROJECT_PATH}/main") endif() spaces2list(COMPONENT_DIRS) spaces2list(COMPONENTS) # Tell cmake to drop executables in the top-level build dir set(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}") # path to idf.py tool set(IDFTOOL ${PYTHON} "${IDF_PATH}/tools/idf.py") # Temporary trick to support both gcc5 and gcc8 builds if(CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.2.0) set(GCC_NOT_5_2_0 0) else() set(GCC_NOT_5_2_0 1) endif() endmacro() # Add all the IDF global compiler & preprocessor options # (applied to all components). Some are config-dependent # # If you only want to set options for a particular component, # don't call or edit this function. TODO DESCRIBE WHAT TO DO INSTEAD # function(idf_set_global_compiler_options) add_definitions(-DESP_PLATFORM) add_definitions(-DHAVE_CONFIG_H) if(CONFIG_OPTIMIZATION_LEVEL_RELEASE) add_compile_options(-Os) else() add_compile_options(-Og) endif() add_c_compile_options(-std=gnu99) add_cxx_compile_options(-std=gnu++11 -fno-rtti) if(CONFIG_CXX_EXCEPTIONS) add_cxx_compile_options(-fexceptions) else() add_cxx_compile_options(-fno-exceptions) endif() # Default compiler configuration add_compile_options(-ffunction-sections -fdata-sections -fstrict-volatile-bitfields -nostdlib) # Default warnings configuration add_compile_options( -Wall -Werror=all -Wno-error=unused-function -Wno-error=unused-but-set-variable -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wextra -Wno-unused-parameter -Wno-sign-compare) add_c_compile_options( -Wno-old-style-declaration ) if(CONFIG_DISABLE_GCC8_WARNINGS) add_compile_options( -Wno-parentheses -Wno-sizeof-pointer-memaccess -Wno-clobbered ) # doesn't use GCC_NOT_5_2_0 because idf_set_global_variables was not called before if(NOT CMAKE_C_COMPILER_VERSION VERSION_EQUAL 5.2.0) add_compile_options( -Wno-format-overflow -Wno-stringop-truncation -Wno-misleading-indentation -Wno-cast-function-type -Wno-implicit-fallthrough -Wno-unused-const-variable -Wno-switch-unreachable -Wno-format-truncation -Wno-memset-elt-size -Wno-int-in-bool-context ) endif() endif() # Stack protection if(NOT BOOTLOADER_BUILD) if(CONFIG_STACK_CHECK_NORM) add_compile_options(-fstack-protector) elseif(CONFIG_STACK_CHECK_STRONG) add_compile_options(-fstack-protector-strong) elseif(CONFIG_STACK_CHECK_ALL) add_compile_options(-fstack-protector-all) endif() endif() if(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED) add_definitions(-DNDEBUG) endif() # Always generate debug symbols (even in Release mode, these don't # go into the final binary so have no impact on size) add_compile_options(-ggdb) # Enable ccache if it's on the path if(NOT CCACHE_DISABLE) find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) message(STATUS "ccache will be used for faster builds") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) endif() endif() # Temporary trick to support both gcc5 and gcc8 builds add_definitions(-DGCC_NOT_5_2_0=${GCC_NOT_5_2_0}) endfunction() # Verify the IDF environment is configured correctly (environment, toolchain, etc) function(idf_verify_environment) if(NOT CMAKE_PROJECT_NAME) message(FATAL_ERROR "Internal error, IDF project.cmake should have set this variable already") endif() # Check toolchain is configured properly in cmake if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa)) message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project " "(or an invalid CMakeCache.txt file has been generated somehow)") endif() # # Warn if the toolchain version doesn't match # # TODO: make these platform-specific for diff toolchains get_expected_ctng_version(expected_toolchain expected_gcc) gcc_version_check("${expected_gcc}") crosstool_version_check("${expected_toolchain}") endfunction() # idf_add_executable # # Calls add_executable to add the final project executable # Adds .map & .bin file targets # Sets up flash-related targets function(idf_add_executable) set(exe_target ${PROJECT_NAME}.elf) if(MAIN_SRCS) spaces2list(MAIN_SRCS) add_executable(${exe_target} ${MAIN_SRCS}) else() # Create a dummy file to work around CMake requirement of having a source # file while adding an executable add_executable(${exe_target} "${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c") add_custom_command(OUTPUT dummy_main_src.c COMMAND ${CMAKE_COMMAND} -E touch dummy_main_src.c WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} VERBATIM) add_custom_target(dummy_main_src DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/dummy_main_src.c) add_dependencies(${exe_target} dummy_main_src) endif() add_map_file(${exe_target}) endfunction() # add_map_file # # Set linker args for 'exe_target' to generate a linker Map file function(add_map_file exe_target) get_filename_component(basename ${exe_target} NAME_WE) set(mapfile "${basename}.map") target_link_libraries(${exe_target} "-Wl,--gc-sections -Wl,--cref -Wl,--Map=${mapfile} -Wl,--start-group") set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${CMAKE_CURRENT_BINARY_DIR}/${mapfile}") # add size targets, depend on map file, run idf_size.py add_custom_target(size DEPENDS ${exe_target} COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py ${mapfile} ) add_custom_target(size-files DEPENDS ${exe_target} COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --files ${mapfile} ) add_custom_target(size-components DEPENDS ${exe_target} COMMAND ${PYTHON} ${IDF_PATH}/tools/idf_size.py --archives ${mapfile} ) endfunction() # component_compile_options # # Wrapper around target_compile_options that passes the component name function(component_compile_options) target_compile_options(${COMPONENT_NAME} PRIVATE ${ARGV}) endfunction() # component_compile_definitions # # Wrapper around target_compile_definitions that passes the component name function(component_compile_definitions) target_compile_definitions(${COMPONENT_NAME} PRIVATE ${ARGV}) endfunction() # idf_get_git_revision # # Set global IDF_VER to the git revision of ESP-IDF. # # Running git_describe() here automatically triggers rebuilds # if the ESP-IDF git version changes function(idf_get_git_revision) if(EXISTS "${IDF_PATH}/version.txt") file(STRINGS "${IDF_PATH}/version.txt" IDF_VER) else() git_describe(IDF_VER "${IDF_PATH}") endif() add_definitions(-DIDF_VER=\"${IDF_VER}\") git_submodule_check("${IDF_PATH}") set(IDF_VER ${IDF_VER} PARENT_SCOPE) endfunction()