| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421 |
- #
- # Load cmake modules
- #
- get_property(__idf_environment_set GLOBAL PROPERTY __IDF_ENVIRONMENT_SET)
- if(NOT __idf_environment_set)
- # Set IDF_PATH, as nothing else will work without this.
- set(IDF_PATH "$ENV{IDF_PATH}")
- if(NOT IDF_PATH)
- # Documentation says you should set IDF_PATH in your environment, but we
- # can infer it relative to tools/cmake directory if it's not set.
- get_filename_component(IDF_PATH "${CMAKE_CURRENT_LIST_DIR}/../.." ABSOLUTE)
- endif()
- file(TO_CMAKE_PATH "${IDF_PATH}" IDF_PATH)
- set(ENV{IDF_PATH} ${IDF_PATH})
- set(CMAKE_MODULE_PATH
- "${IDF_PATH}/tools/cmake"
- "${IDF_PATH}/tools/cmake/third_party"
- ${CMAKE_MODULE_PATH})
- include(utilities)
- include(components)
- include(kconfig)
- include(targets)
- include(git_submodules)
- include(GetGitRevisionDescription)
- include(crosstool_version_check)
- include(ldgen)
- include(version)
- set_default(PYTHON "python")
- if(NOT PYTHON_DEPS_CHECKED AND NOT BOOTLOADER_BUILD)
- message(STATUS "Checking Python dependencies...")
- execute_process(COMMAND "${PYTHON}" "${IDF_PATH}/tools/check_python_dependencies.py"
- RESULT_VARIABLE result)
- if(NOT result EQUAL 0)
- message(FATAL_ERROR "Some Python dependencies must be installed. Check above message for details.")
- endif()
- endif()
- idf_set_target()
- set_property(GLOBAL APPEND PROPERTY __IDF_COMPONENTS_PREFIX "idf_component")
- set_property(GLOBAL PROPERTY __IDF_ENVIRONMENT_SET 1)
- endif()
- macro(idf_set_variables)
- set_default(IDF_BUILD_ARTIFACTS OFF)
- if(IDF_BUILD_ARTIFACTS)
- if(NOT IDF_BUILD_ARTIFACTS_DIR OR NOT IDF_PROJECT_EXECUTABLE)
- message(FATAL_ERROR "IDF_BUILD_ARTIFACTS and IDF_PROJECT_EXECUTABLE needs to be specified \
- if IDF_BUILD_ARTIFACTS is ON.")
- endif()
- endif()
- set_default(IDF_COMPONENT_DIRS "${IDF_EXTRA_COMPONENT_DIRS} ${IDF_PATH}/components")
- set_default(IDF_COMPONENTS "")
- set_default(IDF_COMPONENT_REQUIRES_COMMON "cxx ${IDF_TARGET} newlib freertos heap log soc")
- set(IDF_PROJECT_PATH "${CMAKE_SOURCE_DIR}")
- set(ESP_PLATFORM 1 CACHE BOOL INTERNAL)
- spaces2list(IDF_COMPONENT_DIRS)
- spaces2list(IDF_COMPONENTS)
- spaces2list(IDF_COMPONENT_REQUIRES_COMMON)
- 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_compile_options)
- # 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 CACHE STRING "GCC is 5.2.0 version")
- else()
- set(GCC_NOT_5_2_0 1 CACHE STRING "GCC is not 5.2.0 version")
- endif()
- list(APPEND compile_definitions "GCC_NOT_5_2_0=${GCC_NOT_5_2_0}")
- list(APPEND compile_definitions "ESP_PLATFORM" "HAVE_CONFIG_H")
- list(APPEND compile_options "${CMAKE_C_FLAGS}")
- list(APPEND c_compile_options "${CMAKE_C_FLAGS}")
- list(APPEND cxx_compile_options "${CMAKE_CXX_FLAGS}")
- if(CONFIG_OPTIMIZATION_LEVEL_RELEASE)
- list(APPEND compile_options "-Os")
- else()
- list(APPEND compile_options "-Og")
- endif()
- list(APPEND c_compile_options "-std=gnu99")
- list(APPEND cxx_compile_options "-std=gnu++11" "-fno-rtti")
- if(CONFIG_CXX_EXCEPTIONS)
- list(APPEND cxx_compile_options "-fexceptions")
- else()
- list(APPEND cxx_compile_options "-fno-exceptions")
- endif()
- # Default compiler configuration
- list(APPEND compile_options "-ffunction-sections"
- "-fdata-sections"
- "-fstrict-volatile-bitfields"
- "-nostdlib")
- list(APPEND 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")
- list(APPEND c_compile_options "-Wno-old-style-declaration")
- if(CONFIG_DISABLE_GCC8_WARNINGS)
- list(APPEND 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)
- list(APPEND 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)
- list(APPEND compile_options "-fstack-protector")
- elseif(CONFIG_STACK_CHECK_STRONG)
- list(APPEND compile_options "-fstack-protector-strong")
- elseif(CONFIG_STACK_CHECK_ALL)
- list(APPEND compile_options "-fstack-protector-all")
- endif()
- endif()
- if(CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED)
- list(APPEND compile_definitions "NDEBUG")
- endif()
- # Always generate debug symbols (even in Release mode, these don't
- # go into the final binary so have no impact on size)
- list(APPEND compile_options "-ggdb")
- # Use EXTRA_CFLAGS, EXTRA_CXXFLAGS and EXTRA_CPPFLAGS to add more priority options to the compiler
- # EXTRA_CPPFLAGS is used for both C and C++
- # Unlike environments' CFLAGS/CXXFLAGS/CPPFLAGS which work for both host and target build,
- # these works only for target build
- set(EXTRA_CFLAGS "$ENV{EXTRA_CFLAGS}")
- set(EXTRA_CXXFLAGS "$ENV{EXTRA_CXXFLAGS}")
- set(EXTRA_CPPFLAGS "$ENV{EXTRA_CPPFLAGS}")
- spaces2list(EXTRA_CFLAGS)
- spaces2list(EXTRA_CXXFLAGS)
- spaces2list(EXTRA_CPPFLAGS)
- list(APPEND c_compile_options ${EXTRA_CFLAGS})
- list(APPEND cxx_compile_options ${EXTRA_CXXFLAGS})
- list(APPEND compile_options ${EXTRA_CPPFLAGS})
- set_default(IDF_COMPILE_DEFINITIONS "${compile_definitions}")
- set_default(IDF_COMPILE_OPTIONS "${compile_options}")
- set_default(IDF_C_COMPILE_OPTIONS "${c_compile_options}")
- set_default(IDF_CXX_COMPILE_OPTIONS "${cxx_compile_options}")
- set_default(IDF_INCLUDE_DIRECTORIES "${CONFIG_DIR}")
- set(IDF_COMPILE_DEFINITIONS ${IDF_COMPILE_DEFINITIONS} PARENT_SCOPE)
- set(IDF_COMPILE_OPTIONS ${IDF_COMPILE_OPTIONS} PARENT_SCOPE)
- set(IDF_C_COMPILE_OPTIONS ${IDF_C_COMPILE_OPTIONS} PARENT_SCOPE)
- set(IDF_CXX_COMPILE_OPTIONS ${IDF_CXX_COMPILE_OPTIONS} PARENT_SCOPE)
- set(IDF_INCLUDE_DIRECTORIES ${CONFIG_DIR} PARENT_SCOPE)
- 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_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)
- git_describe(IDF_VER_GIT "${IDF_PATH}")
- if(EXISTS "${IDF_PATH}/version.txt")
- file(STRINGS "${IDF_PATH}/version.txt" IDF_VER_T)
- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${IDF_PATH}/version.txt")
- else()
- set(IDF_VER_T ${IDF_VER_GIT})
- endif()
- # cut IDF_VER to required 32 characters.
- string(SUBSTRING "${IDF_VER_T}" 0 31 IDF_VER)
- message(STATUS "IDF_VER: ${IDF_VER}")
- add_definitions(-DIDF_VER=\"${IDF_VER}\")
- git_submodule_check("${IDF_PATH}")
- set(IDF_VER ${IDF_VER} PARENT_SCOPE)
- endfunction()
- # app_get_revision
- #
- # Set global PROJECT_VER
- #
- # If PROJECT_VER variable set in project CMakeLists.txt file, its value will be used.
- # Else, if the _project_path/version.txt exists, its contents will be used as PROJECT_VER.
- # Else, if the project is located inside a Git repository, the output of git describe will be used.
- # Otherwise, PROJECT_VER will be "1".
- function(app_get_revision _project_path)
- if(NOT DEFINED PROJECT_VER)
- if(EXISTS "${_project_path}/version.txt")
- file(STRINGS "${_project_path}/version.txt" PROJECT_VER)
- set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${_project_path}/version.txt")
- else()
- git_describe(PROJECT_VER_GIT "${_project_path}")
- if(PROJECT_VER_GIT)
- set(PROJECT_VER ${PROJECT_VER_GIT})
- else()
- message(STATUS "Project is not inside a git repository, \
- will not use 'git describe' to determine PROJECT_VER.")
- set(PROJECT_VER "1")
- endif()
- endif()
- endif()
- message(STATUS "Project version: ${PROJECT_VER}")
- set(PROJECT_VER ${PROJECT_VER} PARENT_SCOPE)
- endfunction()
- # idf_link_components
- #
- # Link library components to the target
- function(idf_link_components target components)
- foreach(component ${components})
- component_get_target(component_target ${component})
- # Add each component library's link-time dependencies (which are otherwise ignored) to the executable
- # LINK_DEPENDS in order to trigger a re-link when needed (on Ninja/Makefile generators at least).
- # (maybe this should probably be something CMake does, but it doesn't do it...)
- if(TARGET ${component_target})
- get_target_property(type ${component_target} TYPE)
- get_target_property(imported ${component_target} IMPORTED)
- if(NOT imported)
- if(${type} STREQUAL STATIC_LIBRARY OR ${type} STREQUAL EXECUTABLE)
- get_target_property(link_depends "${component_target}" LINK_DEPENDS)
- if(link_depends)
- set_property(TARGET ${target} APPEND PROPERTY LINK_DEPENDS "${link_depends}")
- endif()
- endif()
- endif()
- if(${type} MATCHES .+_LIBRARY)
- list(APPEND libraries ${component_target})
- endif()
- endif()
- endforeach()
- if(libraries)
- # gc-sections is necessary for linking some IDF binary libraries
- # (and without it, IDF apps are much larger than they should be)
- target_link_libraries(${target} "-Wl,--gc-sections")
- target_link_libraries(${target} "-Wl,--start-group")
- target_link_libraries(${target} ${libraries})
- message(STATUS "Component libraries: ${IDF_COMPONENT_LIBRARIES}")
- endif()
- endfunction()
- # idf_import_components
- #
- # Adds ESP-IDF as a subdirectory to the current project and imports the components
- macro(idf_import_components var idf_path build_path)
- #
- # Set variables that control the build configuration and the build itself
- #
- idf_set_variables()
- kconfig_set_variables()
- #
- # Generate a component dependencies file, enumerating components to be included in the build
- # as well as their dependencies.
- #
- execute_process(COMMAND "${CMAKE_COMMAND}"
- -D "COMPONENTS=${IDF_COMPONENTS}"
- -D "COMPONENT_REQUIRES_COMMON=${IDF_COMPONENT_REQUIRES_COMMON}"
- -D "EXCLUDE_COMPONENTS=${IDF_EXCLUDE_COMPONENTS}"
- -D "TEST_COMPONENTS=${IDF_TEST_COMPONENTS}"
- -D "TEST_EXCLUDE_COMPONENTS=${IDF_TEST_EXCLUDE_COMPONENTS}"
- -D "BUILD_TESTS=${IDF_BUILD_TESTS}"
- -D "DEPENDENCIES_FILE=${CMAKE_BINARY_DIR}/component_depends.cmake"
- -D "COMPONENT_DIRS=${IDF_COMPONENT_DIRS}"
- -D "BOOTLOADER_BUILD=${BOOTLOADER_BUILD}"
- -D "IDF_TARGET=${IDF_TARGET}"
- -D "IDF_PATH=${IDF_PATH}"
- -D "DEBUG=${DEBUG}"
- -P "${IDF_PATH}/tools/cmake/scripts/expand_requirements.cmake"
- WORKING_DIRECTORY "${PROJECT_PATH}"
- RESULT_VARIABLE expand_requirements_result)
- if(expand_requirements_result)
- message(FATAL_ERROR "Failed to expand component requirements")
- endif()
- include("${CMAKE_BINARY_DIR}/component_depends.cmake")
- #
- # We now have the following component-related variables:
- #
- # IDF_COMPONENTS is the list of initial components set by the user
- # (or empty to include all components in the build).
- # BUILD_COMPONENTS is the list of components to include in the build.
- # BUILD_COMPONENT_PATHS is the paths to all of these components, obtained from the component dependencies file.
- #
- # Print the list of found components and test components
- #
- string(REPLACE ";" " " BUILD_COMPONENTS_SPACES "${BUILD_COMPONENTS}")
- message(STATUS "Component names: ${BUILD_COMPONENTS_SPACES}")
- unset(BUILD_COMPONENTS_SPACES)
- message(STATUS "Component paths: ${BUILD_COMPONENT_PATHS}")
- # Print list of test components
- if(TESTS_ALL EQUAL 1 OR TEST_COMPONENTS)
- string(REPLACE ";" " " BUILD_TEST_COMPONENTS_SPACES "${BUILD_TEST_COMPONENTS}")
- message(STATUS "Test component names: ${BUILD_TEST_COMPONENTS_SPACES}")
- unset(BUILD_TEST_COMPONENTS_SPACES)
- message(STATUS "Test component paths: ${BUILD_TEST_COMPONENT_PATHS}")
- endif()
- # Generate project configuration
- kconfig_process_config()
- # Include sdkconfig.cmake so rest of the build knows the configuration
- include(${SDKCONFIG_CMAKE})
- # Verify the environment is configured correctly
- idf_verify_environment()
- # Check git revision (may trigger reruns of cmake)
- ## sets IDF_VER to IDF git revision
- idf_get_git_revision()
- # Check that the targets set in cache, sdkconfig, and in environment all match
- idf_check_config_target()
- ## get PROJECT_VER
- if(NOT BOOTLOADER_BUILD)
- app_get_revision("${CMAKE_SOURCE_DIR}")
- endif()
- # Add some idf-wide definitions
- idf_set_global_compile_options()
- # generate compile_commands.json (needs to come after project)
- set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
- #
- # Setup variables for linker script generation
- #
- ldgen_set_variables()
- # Include any top-level project_include.cmake files from components
- foreach(component ${BUILD_COMPONENT_PATHS})
- set(COMPONENT_PATH "${component}")
- include_if_exists("${component}/project_include.cmake")
- unset(COMPONENT_PATH)
- endforeach()
- add_subdirectory(${idf_path} ${build_path})
- if(IDF_BUILD_ARTIFACTS)
- # Write project description JSON file
- make_json_list("${BUILD_COMPONENTS}" build_components_json)
- make_json_list("${BUILD_COMPONENT_PATHS}" build_component_paths_json)
- configure_file("${IDF_PATH}/tools/cmake/project_description.json.in"
- "${IDF_BUILD_ARTIFACTS_DIR}/project_description.json")
- unset(build_components_json)
- unset(build_component_paths_json)
- endif()
- ldgen_add_dependencies()
- set(${var} ${BUILD_COMPONENTS})
- endmacro()
|