From 08a416ae1a7b8b2e4c1386ec858fa0110c7da057 Mon Sep 17 00:00:00 2001 From: Frantisek Hrbata Date: Tue, 12 Aug 2025 18:04:03 +0200 Subject: [PATCH] feat(cmakev2/project): move all project-related items into project.cmake The current approach involves transparently calling __init_build within idf_build_library and performing all post-project() initialization there. The issue with this method is that project_include.cmake files also need to be included during post-project() initialization, but they should be included in the global scope. This cannot be achieved within the __init_build function unless it is converted into a macro. Although using a macro is a potential solution, it risks causing global scope pollution. Another complication is the location where project() can be invoked; it must be explicitly[1] stated in the project's CMakeLists.txt. This requirement conflicts with our intention to wrap it within the idf_project_default helper. Given these challenges, it makes sense to introduce an explicit idf_project_init macro, where all post-project() initialization occurs, including the inclusion of project_include.cmake files. While we can still encapsulate this within idf_project_default, for the plumbing commands (idf_build_library, idf_build_executable, ...), it will need to be explicitly called after the project() invocation. Usage for default project: cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake) project() idf_project_default() Usage for plumbing commands: cmake_minimum_required(VERSION 3.22) include($ENV{IDF_PATH}/tools/cmakev2/idf.cmake) project() idf_project_init() idf_build_library() ... [1] https://cmake.org/cmake/help/latest/command/project.html#usage Signed-off-by: Frantisek Hrbata --- tools/cmakev2/build.cmake | 565 +---------------------------- tools/cmakev2/idf.cmake | 1 + tools/cmakev2/project.cmake | 566 ++++++++++++++++++++++++++++++ tools/cmakev2/test/CMakeLists.txt | 2 + 4 files changed, 574 insertions(+), 560 deletions(-) create mode 100644 tools/cmakev2/project.cmake diff --git a/tools/cmakev2/build.cmake b/tools/cmakev2/build.cmake index d2a92e233da..a3d6e98bd25 100644 --- a/tools/cmakev2/build.cmake +++ b/tools/cmakev2/build.cmake @@ -91,534 +91,6 @@ function(__dump_build_properties) endforeach() endfunction() -#[[ - __init_project_name() - - Initialize the PROJECT_NAME build property, using CMAKE_PROJECT_NAME as a - fallback. -#]] -function(__init_project_name) - __get_default_value(VARIABLE PROJECT_NAME - DEFAULT "${CMAKE_PROJECT_NAME}" - OUTPUT project_name) - idf_build_set_property(PROJECT_NAME "${project_name}") -endfunction() - -#[[ - __init_project_version() - - Initialize the PROJECT_VER build property based on the following precedence. - - 1. The PROJECT_VER environment or CMake variable. - 2. The version.txt file located in the top-level project directory. - 3. The VERSION argument, if provided, in the project() macro. - 4. The output of git describe if the project is within a Git repository. - 5. Defaults to 1 if none of the above conditions are met. - - The value of PROJECT_VER will be overridden later if - CONFIG_APP_PROJECT_VER_FROM_CONFIG is defined. For more details, refer to - components/esp_app_format/CMakeLists.txt. -#]] -function(__init_project_version) - idf_build_get_property(project_dir PROJECT_DIR) - - # 1. The PROJECT_VER environment or CMake variable. - __get_default_value(VARIABLE PROJECT_VER - DEFAULT NOTFOUND - OUTPUT project_ver) - if(project_ver) - idf_build_set_property(PROJECT_VER "${project_ver}") - return() - endif() - - # 2. The version.txt file located in the top-level project directory. - if(EXISTS "${project_dir}/version.txt") - file(STRINGS "${project_dir}/version.txt" project_ver) - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${project_dir}/version.txt") - idf_build_set_property(PROJECT_VER "${project_ver}") - return() - endif() - - # 3. The VERSION argument, if provided, in the project() macro. - if(PROJECT_VERSION) - idf_build_set_property(PROJECT_VER "${PROJECT_VERSION}") - return() - endif() - - # 4. The output of git describe if the project is within a Git repository. - git_describe(project_ver "${project_dir}") - if(project_ver) - idf_build_set_property(PROJECT_VER "${project_ver}") - return() - endif() - - # 5. Defaults to 1 if none of the above conditions are met. - idf_build_set_property(PROJECT_VER 1) -endfunction() - -#[[ - __init_build_configuration() - - Configure the build settings in one location, incorporating preset - compilation flags, definitions, and settings based on sdkconfig. -#]] -function(__init_build_configuration) - set(compile_definitions) - set(compile_options) - set(c_compile_options) - set(cxx_compile_options) - set(asm_compile_options) - set(link_options) - - idf_build_get_property(idf_ver IDF_VER) - idf_build_get_property(idf_target IDF_TARGET) - idf_build_get_property(components_discovered COMPONENTS_DISCOVERED) - idf_build_get_property(build_dir BUILD_DIR) - idf_build_get_property(project_dir PROJECT_DIR) - idf_build_get_property(project_name PROJECT_NAME) - - list(APPEND compile_definitions "_GLIBCXX_USE_POSIX_SEMAPHORE" # These two lines enable libstd++ to use - "_GLIBCXX_HAVE_POSIX_SEMAPHORE" # posix-semaphores from components/pthread - "_GNU_SOURCE") - - list(APPEND compile_definitions "IDF_VER=\"${idf_ver}\"") - - list(APPEND compile_options "-ffunction-sections" - "-fdata-sections" - # warning-related flags - "-Wall" - "-Wno-error=unused-function" - "-Wno-error=unused-variable" - "-Wno-error=unused-but-set-variable" - "-Wno-error=deprecated-declarations" - "-Wextra" - "-Wno-error=extra" - "-Wno-unused-parameter" - "-Wno-sign-compare" - # ignore multiple enum conversion warnings since gcc 11 - # TODO: IDF-5163 - "-Wno-enum-conversion" - # Default is dwarf-5 since GCC 11, fallback to dwarf-4 because of binary size - # TODO: IDF-5160 - "-gdwarf-4" - # always generate debug symbols (even in release mode, these don't - # go into the final binary so have no impact on size - "-ggdb") - - if(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS AND NOT CMAKE_C_COMPILER_ID MATCHES "Clang") - list(APPEND compile_options "-Werror=all") - else() - list(APPEND compile_options "-Werror") - endif() - - if(IDF_TARGET STREQUAL "linux") - # Building for Linux target, fall back to an older version of the standard - # if the preferred one is not supported by the compiler. - set(preferred_c_versions gnu17 gnu11 gnu99) - set(ver_found FALSE) - foreach(c_version ${preferred_c_versions}) - check_c_compiler_flag("-std=${c_version}" ver_${c_version}_supported) - if(ver_${c_version}_supported) - set(c_std ${c_version}) - set(ver_found TRUE) - break() - endif() - endforeach() - if(NOT ver_found) - idf_die("Failed to set C language standard to one of the supported versions: " - "${preferred_c_versions}. Please upgrade the host compiler.") - endif() - - set(preferred_cxx_versions gnu++2b gnu++20 gnu++2a gnu++17 gnu++14) - set(ver_found FALSE) - foreach(cxx_version ${preferred_cxx_versions}) - check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported) - if(ver_${cxx_version}_supported) - set(cxx_std ${cxx_version}) - set(ver_found TRUE) - break() - endif() - endforeach() - if(NOT ver_found) - idf_die("Failed to set C++ language standard to one of the supported versions: " - "${preferred_cxx_versions}. Please upgrade the host compiler.") - endif() - - list(APPEND c_compile_options "-std=${c_std}") - list(APPEND cxx_compile_options "-std=${cxx_std}") - else() - # Building for chip targets: we use a known version of the toolchain. - # Use latest supported versions. - # For Linux target -std settings, refer to the __linux_build_set_lang_version - # function, which must be called after project(). - # Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and - # tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this. - list(APPEND c_compile_options "-std=gnu17") - list(APPEND cxx_compile_options "-std=gnu++2b") - endif() - - if(CONFIG_COMPILER_OPTIMIZATION_SIZE) - if(CMAKE_C_COMPILER_ID MATCHES "Clang") - list(APPEND compile_options "-Oz") - else() - list(APPEND compile_options "-Os") - endif() - if(CMAKE_C_COMPILER_ID MATCHES "GNU") - list(APPEND compile_options "-freorder-blocks") - endif() - elseif(CONFIG_COMPILER_OPTIMIZATION_DEBUG) - list(APPEND compile_options "-Og") - if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CONFIG_IDF_TARGET_LINUX) - list(APPEND compile_options "-fno-shrink-wrap") # Disable shrink-wrapping to reduce binary size - endif() - elseif(CONFIG_COMPILER_OPTIMIZATION_NONE) - list(APPEND compile_options "-O0") - elseif(CONFIG_COMPILER_OPTIMIZATION_PERF) - list(APPEND compile_options "-O2") - endif() - - if(CONFIG_COMPILER_CXX_EXCEPTIONS) - list(APPEND cxx_compile_options "-fexceptions") - else() - list(APPEND cxx_compile_options "-fno-exceptions") - endif() - - if(CONFIG_COMPILER_CXX_RTTI) - list(APPEND cxx_compile_options "-frtti") - else() - list(APPEND cxx_compile_options "-fno-rtti") - list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking - endif() - - if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS) - list(APPEND compile_options "-msave-restore") - 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") - # 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 implicit conversions 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") - # Disable Clang warnings for atomic operations with access size - # more then 4 bytes - list(APPEND compile_options "-Wno-atomic-alignment") - # several warnings in wpa_supplicant component - list(APPEND compile_options "-Wno-unused-but-set-variable") - # Clang also produces many -Wunused-function warnings which GCC doesn't. - list(APPEND compile_options "-Wno-unused-function") - # many warnings in bluedroid code - # warning: field 'hdr' with variable sized type 'BT_HDR' not at the end of a struct or class is a GNU extension - list(APPEND compile_options "-Wno-gnu-variable-sized-type-not-at-end") - # several warnings in bluedroid code - list(APPEND compile_options "-Wno-constant-logical-operand") - # warning: '_Static_assert' with no message is a C2x extension - list(APPEND compile_options "-Wno-c2x-extensions") - # warning on xMPU_SETTINGS for esp32s2 has size 0 for C and 1 for C++ - list(APPEND compile_options "-Wno-extern-c-compat") - if(NOT (CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")) - # warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 - list(APPEND compile_options "-Wno-single-bit-bitfield-constant-conversion") - endif() - endif() - # More warnings may exist in unit tests and example projects. - - if(CONFIG_COMPILER_WARN_WRITE_STRINGS) - list(APPEND compile_options "-Wwrite-strings") - endif() - - if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE) - list(APPEND compile_definitions "-DNDEBUG") - endif() - - if(CONFIG_COMPILER_NO_MERGE_CONSTANTS) - list(APPEND compile_options "-fno-merge-constants") - endif() - - if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM) - list(APPEND compile_options "-fstack-protector") - elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG) - list(APPEND compile_options "-fstack-protector-strong") - elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL) - list(APPEND compile_options "-fstack-protector-all") - endif() - - if(CONFIG_COMPILER_DUMP_RTL_FILES) - list(APPEND compile_options "-fdump-rtl-expand") - endif() - - if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0) - list(APPEND c_compile_options "-fzero-init-padding-bits=all" "-fno-malloc-dce") - endif() - - if(CONFIG_COMPILER_DISABLE_GCC12_WARNINGS) - list(APPEND compile_options "-Wno-address" - "-Wno-use-after-free") - endif() - - if(CONFIG_COMPILER_DISABLE_GCC13_WARNINGS) - list(APPEND compile_options "-Wno-xor-used-as-pow") - list(APPEND c_compile_options "-Wno-enum-int-mismatch") - list(APPEND cxx_compile_options "-Wno-self-move" - "-Wno-dangling-reference") - endif() - - if(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS) - list(APPEND compile_options "-Wno-calloc-transposed-args") - endif() - - if(CONFIG_COMPILER_DISABLE_GCC15_WARNINGS) - list(APPEND c_compile_options "-Wno-unterminated-string-initialization") - list(APPEND c_compile_options "-Wno-header-guard") - list(APPEND cxx_compile_options "-Wno-self-move") - list(APPEND cxx_compile_options "-Wno-template-body") - list(APPEND cxx_compile_options "-Wno-dangling-reference") - list(APPEND cxx_compile_options "-Wno-defaulted-function-deleted") - endif() - - # GCC-specific options - if(CMAKE_C_COMPILER_ID STREQUAL "GNU") - list(APPEND compile_options "-fstrict-volatile-bitfields") - if(CONFIG_COMPILER_STATIC_ANALYZER) - list(APPEND compile_options "-fanalyzer") - endif() - endif() - - if(CONFIG_ESP_SYSTEM_USE_EH_FRAME) - list(APPEND compile_options "-fasynchronous-unwind-tables") - list(APPEND link_options "-Wl,--eh-frame-hdr") - endif() - - if(CONFIG_ESP_SYSTEM_USE_FRAME_POINTER) - list(APPEND compile_options "-fno-omit-frame-pointer") - if(CMAKE_C_COMPILER_ID MATCHES "GNU") - list(APPEND compile_options "-mno-omit-leaf-frame-pointer") - endif() - endif() - - list(APPEND link_options "-fno-lto") - - if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - # Not all versions of the MacOS linker support the -warn_commons flag. - # ld version 1053.12 (and above) have been tested to support it. - # Hence, we extract the version string from the linker output - # before including the flag. - - # Get the ld version, capturing both stdout and stderr - execute_process( - COMMAND ${CMAKE_LINKER} -v - OUTPUT_VARIABLE LD_VERSION_OUTPUT - ERROR_VARIABLE LD_VERSION_ERROR - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE - ) - - # Combine stdout and stderr - set(LD_VERSION_OUTPUT "${LD_VERSION_OUTPUT}\n${LD_VERSION_ERROR}") - - # Extract the version string - string(REGEX MATCH "PROJECT:(ld|dyld)-([0-9]+)\\.([0-9]+)" LD_VERSION_MATCH "${LD_VERSION_OUTPUT}") - set(LD_VERSION_MAJOR_MINOR "${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") - - idf_msg("Linker Version: ${LD_VERSION_MAJOR_MINOR}") - - # Compare the version with 1053.12 - if(LD_VERSION_MAJOR_MINOR VERSION_GREATER_EQUAL "1053.12") - list(APPEND link_options "-Wl,-warn_commons") - endif() - - list(APPEND link_options "-Wl,-dead_strip") - else() - list(APPEND link_options "-Wl,--gc-sections") - list(APPEND link_options "-Wl,--warn-common") - endif() - - # SMP FreeRTOS user provided minimal idle hook. This allows the user to provide - # their own copy of vApplicationPassiveIdleHook() - if(CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK) - list(APPEND link_options "-Wl,--wrap=vApplicationPassiveIdleHook") - endif() - - # Placing jump tables in flash would cause issues with code that required - # to be placed in IRAM - list(APPEND compile_options "-fno-jump-tables") - 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 "Clang") - list(APPEND compile_options "-fno-use-cxa-atexit") # TODO IDF-10934 - else() - list(APPEND cxx_compile_options "-fuse-cxa-atexit") - endif() - - if(COMPILER_RT_LIB_NAME) - list(APPEND link_options "-rtlib=${CONFIG_COMPILER_RT_LIB_NAME}") - endif() - - if(CONFIG_LIBC_PICOLIBC) - list(APPEND c_compile_options "-specs=picolibc.specs") - list(APPEND cxx_compile_options "-specs=picolibcpp.specs") - list(APPEND link_options "-specs=picolibc.specs") - endif() - - if(CMAKE_C_COMPILER_ID MATCHES "GNU") - set(mapfile "${build_dir}/${project_name}.map") - set(target_upper "${idf_target}") - string(TOUPPER ${target_upper} target_upper) - # Add cross-reference table to the map file - list(APPEND link_options "-Wl,--cref") - # Add this symbol as a hint for esp_idf_size to guess the target name - list(APPEND link_options "-Wl,--defsym=IDF_TARGET_${target_upper}=0") - # Enable map file output - list(APPEND link_options "-Wl,--Map=${mapfile}") - # Check if linker supports --no-warn-rwx-segments - execute_process(COMMAND ${CMAKE_LINKER} "--no-warn-rwx-segments" "--version" - RESULT_VARIABLE result - OUTPUT_QUIET - ERROR_QUIET) - if(${result} EQUAL 0) - # Do not print RWX segment warnings - list(APPEND link_options "-Wl,--no-warn-rwx-segments") - endif() - if(CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING) - # Print warnings if orphan sections are found - list(APPEND link_options "-Wl,--orphan-handling=warn") - endif() - endif() - - # Prepares the list of compiler flags for remapping various paths to fixed - # names. This is used when reproducible builds are required. This function - # also creates a gdbinit file for the debugger to remap the substituted - # paths back to the real paths in the filesystem. - set(gdbinit_dir ${build_dir}/gdbinit) - set(gdbinit_path "${gdbinit_dir}/prefix_map") - - if(CONFIG_COMPILER_HIDE_PATHS_MACROS) - list(APPEND compile_options "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.") - list(APPEND compile_options "-fmacro-prefix-map=${idf_path}=/IDF") - endif() - - if(CONFIG_APP_REPRODUCIBLE_BUILD) - list(APPEND compile_options "-fdebug-prefix-map=${idf_path}=/IDF") - list(APPEND compile_options "-fdebug-prefix-map=${project_dir}=/IDF_PROJECT") - list(APPEND compile_options "-fdebug-prefix-map=${build_dir}=/IDF_BUILD") - - # Generate mapping for component paths - set(gdbinit_file_lines) - foreach(component_name ${components_discovered}) - idf_component_get_property(component_dir ${component_name} COMPONENT_DIR) - - string(TOUPPER ${component_name} component_name_uppercase) - set(substituted_path "/COMPONENT_${component_name_uppercase}_DIR") - list(APPEND compile_options "-fdebug-prefix-map=${component_dir}=${substituted_path}") - string(APPEND gdbinit_file_lines "set substitute-path ${substituted_path} ${component_dir}\n") - endforeach() - - # Mapping for toolchain path - execute_process( - COMMAND ${CMAKE_C_COMPILER} -print-sysroot - OUTPUT_VARIABLE compiler_sysroot - ) - if(compiler_sysroot STREQUAL "") - idf_die("Failed to determine toolchain sysroot") - endif() - string(STRIP "${compiler_sysroot}" compiler_sysroot) - get_filename_component(compiler_sysroot "${compiler_sysroot}/.." REALPATH) - list(APPEND compile_options "-fdebug-prefix-map=${compiler_sysroot}=/TOOLCHAIN") - string(APPEND gdbinit_file_lines "set substitute-path /TOOLCHAIN ${compiler_sysroot}\n") - - file(WRITE "${build_dir}/prefix_map_gdbinit" "${gdbinit_file_lines}") # TODO IDF-11667 - idf_build_set_property(DEBUG_PREFIX_MAP_GDBINIT "${gdbinit_path}") - else() - set(gdbinit_file_lines "# There is no prefix map defined for the project.\n") - endif() - # Write prefix_map_gdbinit file even it is empty. - file(MAKE_DIRECTORY ${gdbinit_dir}) - file(WRITE "${gdbinit_path}" "${gdbinit_file_lines}") - - idf_build_set_property(GDBINIT_FILES_PREFIX_MAP "${gdbinit_path}") - idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) - idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND) - idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND) - idf_build_set_property(ASM_COMPILE_OPTIONS "${asm_compile_options}" APPEND) - idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND) - idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND) - - # Set the LINKER_TYPE build property. Different linkers may have varying - # options, so it's important to identify the linker type to configure the - # options correctly. Currently, LINKER_TYPE is used to set the appropriate - # linker options for linking the entire archive, which differs between the - # GNU and Apple linkers when building on the host. - if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") - # Compiling for the host, and the host is macOS, so the linker is Darwin LD. - # Note, when adding support for Clang and LLD based toolchain this check will - # need to be modified. - set(linker_type "Darwin") - else() - set(linker_type "GNU") - endif() - idf_build_set_property(LINKER_TYPE "${linker_type}") -endfunction() - -#[[ - __init_build() - - Initialize settings that need to be configured after the project() function - is called. This primarily involves setting compilation options, define - settings, and configuring linker options. -#]] -function(__init_build) - idf_build_get_property(build_initialized __BUILD_INITIALIZED) - if(build_initialized) - # Ensure this function is executed only once throughout the entire - # project. - return() - endif() - - # Set PROJECT_NAME build property - __init_project_name() - - # Set PROJECT_VER build property - __init_project_version() - - # Initialize all compilation options and defines. - __init_build_configuration() - - idf_build_set_property(__BUILD_INITIALIZED YES) -endfunction() - #[[ __get_library_interface_or_die(LIBRARY OUTPUT ) @@ -763,6 +235,11 @@ function(idf_build_library) set(multi_value COMPONENTS) cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN}) + idf_build_get_property(project_initialized __PROJECT_INITIALIZED) + if(NOT project_initialized) + idf_die("The IDF project is not initialized. The 'idf_project_init()' must be called first.") + endif() + if(NOT DEFINED ARG_INTERFACE) idf_die("INTERFACE option is required") endif() @@ -773,10 +250,6 @@ function(idf_build_library) set(ARG_COMPONENTS "${component_names}") endif() - # Initialize settings that must be configured after the project() function - # is called. The __init_build function is evaluated only once per project. - __init_build() - # Create library interface. add_library("${ARG_INTERFACE}" INTERFACE) idf_build_set_property(LIBRARY_INTERFACES "${ARG_INTERFACE}" APPEND) @@ -799,31 +272,3 @@ function(idf_build_library) target_link_libraries("${ARG_INTERFACE}" INTERFACE "${component_interface}") endforeach() endfunction() - -#[[ - __generate_project_info() - - Generate a dummy project_description.json file to enable the use of idf.py - commands that require ensure_build_directory, such as reconfigure. - - FIXME: This needs to generate a complete project_description.json for the - specified executable. -#]] -function(__generate_project_info) - idf_build_get_property(IDF_PATH IDF_PATH) - idf_build_get_property(PROJECT_NAME PROJECT_NAME) - idf_build_get_property(PROJECT_VER PROJECT_VER) - idf_build_get_property(PROJECT_PATH PROJECT_DIR) - idf_build_get_property(BUILD_DIR BUILD_DIR) - idf_build_get_property(SDKCONFIG SDKCONFIG) - idf_build_get_property(SDKCONFIG_DEFAULTS SDKCONFIG_DEFAULTS) - - set(common_component_reqs_json "\"\"") - set(build_components_json "\"\"") - set(build_component_paths_json "\"\"") - set(build_component_info_json "\"\"") - set(all_component_info_json "\"\"") - - configure_file("${IDF_PATH}/tools/cmake/project_description.json.in" - "${BUILD_DIR}/project_description.json") -endfunction() diff --git a/tools/cmakev2/idf.cmake b/tools/cmakev2/idf.cmake index 77886909998..0378e5e95ea 100644 --- a/tools/cmakev2/idf.cmake +++ b/tools/cmakev2/idf.cmake @@ -20,6 +20,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/../cmake/version.cmake) include(component) include(build) include(kconfig) +include(project) include(GetGitRevisionDescription) #[[ diff --git a/tools/cmakev2/project.cmake b/tools/cmakev2/project.cmake new file mode 100644 index 00000000000..48194b0cfcc --- /dev/null +++ b/tools/cmakev2/project.cmake @@ -0,0 +1,566 @@ +# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +include_guard(GLOBAL) + +#[[ + __init_project_name() + + Initialize the PROJECT_NAME build property, using CMAKE_PROJECT_NAME as a + fallback. +#]] +function(__init_project_name) + __get_default_value(VARIABLE PROJECT_NAME + DEFAULT "${CMAKE_PROJECT_NAME}" + OUTPUT project_name) + idf_build_set_property(PROJECT_NAME "${project_name}") +endfunction() + +#[[ + __init_project_version() + + Initialize the PROJECT_VER build property based on the following precedence. + + 1. The PROJECT_VER environment or CMake variable. + 2. The version.txt file located in the top-level project directory. + 3. The VERSION argument, if provided, in the project() macro. + 4. The output of git describe if the project is within a Git repository. + 5. Defaults to 1 if none of the above conditions are met. + + The value of PROJECT_VER will be overridden later if + CONFIG_APP_PROJECT_VER_FROM_CONFIG is defined. For more details, refer to + components/esp_app_format/CMakeLists.txt. +#]] +function(__init_project_version) + idf_build_get_property(project_dir PROJECT_DIR) + + # 1. The PROJECT_VER environment or CMake variable. + __get_default_value(VARIABLE PROJECT_VER + DEFAULT NOTFOUND + OUTPUT project_ver) + if(project_ver) + idf_build_set_property(PROJECT_VER "${project_ver}") + return() + endif() + + # 2. The version.txt file located in the top-level project directory. + if(EXISTS "${project_dir}/version.txt") + file(STRINGS "${project_dir}/version.txt" project_ver) + set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${project_dir}/version.txt") + idf_build_set_property(PROJECT_VER "${project_ver}") + return() + endif() + + # 3. The VERSION argument, if provided, in the project() macro. + if(PROJECT_VERSION) + idf_build_set_property(PROJECT_VER "${PROJECT_VERSION}") + return() + endif() + + # 4. The output of git describe if the project is within a Git repository. + git_describe(project_ver "${project_dir}") + if(project_ver) + idf_build_set_property(PROJECT_VER "${project_ver}") + return() + endif() + + # 5. Defaults to 1 if none of the above conditions are met. + idf_build_set_property(PROJECT_VER 1) +endfunction() + +#[[ + __init_project_configuration() + + Configure the build settings in one location, incorporating preset + compilation flags, definitions, and settings based on sdkconfig. +#]] +function(__init_project_configuration) + set(compile_definitions) + set(compile_options) + set(c_compile_options) + set(cxx_compile_options) + set(asm_compile_options) + set(link_options) + + idf_build_get_property(idf_ver IDF_VER) + idf_build_get_property(idf_target IDF_TARGET) + idf_build_get_property(components_discovered COMPONENTS_DISCOVERED) + idf_build_get_property(build_dir BUILD_DIR) + idf_build_get_property(project_dir PROJECT_DIR) + idf_build_get_property(project_name PROJECT_NAME) + + list(APPEND compile_definitions "_GLIBCXX_USE_POSIX_SEMAPHORE" # These two lines enable libstd++ to use + "_GLIBCXX_HAVE_POSIX_SEMAPHORE" # posix-semaphores from components/pthread + "_GNU_SOURCE") + + list(APPEND compile_definitions "IDF_VER=\"${idf_ver}\"") + + list(APPEND compile_options "-ffunction-sections" + "-fdata-sections" + # warning-related flags + "-Wall" + "-Wno-error=unused-function" + "-Wno-error=unused-variable" + "-Wno-error=unused-but-set-variable" + "-Wno-error=deprecated-declarations" + "-Wextra" + "-Wno-error=extra" + "-Wno-unused-parameter" + "-Wno-sign-compare" + # ignore multiple enum conversion warnings since gcc 11 + # TODO: IDF-5163 + "-Wno-enum-conversion" + # Default is dwarf-5 since GCC 11, fallback to dwarf-4 because of binary size + # TODO: IDF-5160 + "-gdwarf-4" + # always generate debug symbols (even in release mode, these don't + # go into the final binary so have no impact on size + "-ggdb") + + if(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS AND NOT CMAKE_C_COMPILER_ID MATCHES "Clang") + list(APPEND compile_options "-Werror=all") + else() + list(APPEND compile_options "-Werror") + endif() + + if(IDF_TARGET STREQUAL "linux") + # Building for Linux target, fall back to an older version of the standard + # if the preferred one is not supported by the compiler. + set(preferred_c_versions gnu17 gnu11 gnu99) + set(ver_found FALSE) + foreach(c_version ${preferred_c_versions}) + check_c_compiler_flag("-std=${c_version}" ver_${c_version}_supported) + if(ver_${c_version}_supported) + set(c_std ${c_version}) + set(ver_found TRUE) + break() + endif() + endforeach() + if(NOT ver_found) + idf_die("Failed to set C language standard to one of the supported versions: " + "${preferred_c_versions}. Please upgrade the host compiler.") + endif() + + set(preferred_cxx_versions gnu++2b gnu++20 gnu++2a gnu++17 gnu++14) + set(ver_found FALSE) + foreach(cxx_version ${preferred_cxx_versions}) + check_cxx_compiler_flag("-std=${cxx_version}" ver_${cxx_version}_supported) + if(ver_${cxx_version}_supported) + set(cxx_std ${cxx_version}) + set(ver_found TRUE) + break() + endif() + endforeach() + if(NOT ver_found) + idf_die("Failed to set C++ language standard to one of the supported versions: " + "${preferred_cxx_versions}. Please upgrade the host compiler.") + endif() + + list(APPEND c_compile_options "-std=${c_std}") + list(APPEND cxx_compile_options "-std=${cxx_std}") + else() + # Building for chip targets: we use a known version of the toolchain. + # Use latest supported versions. + # For Linux target -std settings, refer to the __linux_build_set_lang_version + # function, which must be called after project(). + # Please update docs/en/api-guides/c.rst, docs/en/api-guides/cplusplus.rst and + # tools/test_apps/system/cxx_build_test/main/test_cxx_standard.cpp when changing this. + list(APPEND c_compile_options "-std=gnu17") + list(APPEND cxx_compile_options "-std=gnu++2b") + endif() + + if(CONFIG_COMPILER_OPTIMIZATION_SIZE) + if(CMAKE_C_COMPILER_ID MATCHES "Clang") + list(APPEND compile_options "-Oz") + else() + list(APPEND compile_options "-Os") + endif() + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND compile_options "-freorder-blocks") + endif() + elseif(CONFIG_COMPILER_OPTIMIZATION_DEBUG) + list(APPEND compile_options "-Og") + if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CONFIG_IDF_TARGET_LINUX) + list(APPEND compile_options "-fno-shrink-wrap") # Disable shrink-wrapping to reduce binary size + endif() + elseif(CONFIG_COMPILER_OPTIMIZATION_NONE) + list(APPEND compile_options "-O0") + elseif(CONFIG_COMPILER_OPTIMIZATION_PERF) + list(APPEND compile_options "-O2") + endif() + + if(CONFIG_COMPILER_CXX_EXCEPTIONS) + list(APPEND cxx_compile_options "-fexceptions") + else() + list(APPEND cxx_compile_options "-fno-exceptions") + endif() + + if(CONFIG_COMPILER_CXX_RTTI) + list(APPEND cxx_compile_options "-frtti") + else() + list(APPEND cxx_compile_options "-fno-rtti") + list(APPEND link_options "-fno-rtti") # used to invoke correct multilib variant (no-rtti) during linking + endif() + + if(CONFIG_COMPILER_SAVE_RESTORE_LIBCALLS) + list(APPEND compile_options "-msave-restore") + 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") + # 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 implicit conversions 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") + # Disable Clang warnings for atomic operations with access size + # more then 4 bytes + list(APPEND compile_options "-Wno-atomic-alignment") + # several warnings in wpa_supplicant component + list(APPEND compile_options "-Wno-unused-but-set-variable") + # Clang also produces many -Wunused-function warnings which GCC doesn't. + list(APPEND compile_options "-Wno-unused-function") + # many warnings in bluedroid code + # warning: field 'hdr' with variable sized type 'BT_HDR' not at the end of a struct or class is a GNU extension + list(APPEND compile_options "-Wno-gnu-variable-sized-type-not-at-end") + # several warnings in bluedroid code + list(APPEND compile_options "-Wno-constant-logical-operand") + # warning: '_Static_assert' with no message is a C2x extension + list(APPEND compile_options "-Wno-c2x-extensions") + # warning on xMPU_SETTINGS for esp32s2 has size 0 for C and 1 for C++ + list(APPEND compile_options "-Wno-extern-c-compat") + if(NOT (CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")) + # warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 + list(APPEND compile_options "-Wno-single-bit-bitfield-constant-conversion") + endif() + endif() + # More warnings may exist in unit tests and example projects. + + if(CONFIG_COMPILER_WARN_WRITE_STRINGS) + list(APPEND compile_options "-Wwrite-strings") + endif() + + if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE) + list(APPEND compile_definitions "-DNDEBUG") + endif() + + if(CONFIG_COMPILER_NO_MERGE_CONSTANTS) + list(APPEND compile_options "-fno-merge-constants") + endif() + + if(CONFIG_COMPILER_STACK_CHECK_MODE_NORM) + list(APPEND compile_options "-fstack-protector") + elseif(CONFIG_COMPILER_STACK_CHECK_MODE_STRONG) + list(APPEND compile_options "-fstack-protector-strong") + elseif(CONFIG_COMPILER_STACK_CHECK_MODE_ALL) + list(APPEND compile_options "-fstack-protector-all") + endif() + + if(CONFIG_COMPILER_DUMP_RTL_FILES) + list(APPEND compile_options "-fdump-rtl-expand") + endif() + + if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0) + list(APPEND c_compile_options "-fzero-init-padding-bits=all" "-fno-malloc-dce") + endif() + + if(CONFIG_COMPILER_DISABLE_GCC12_WARNINGS) + list(APPEND compile_options "-Wno-address" + "-Wno-use-after-free") + endif() + + if(CONFIG_COMPILER_DISABLE_GCC13_WARNINGS) + list(APPEND compile_options "-Wno-xor-used-as-pow") + list(APPEND c_compile_options "-Wno-enum-int-mismatch") + list(APPEND cxx_compile_options "-Wno-self-move" + "-Wno-dangling-reference") + endif() + + if(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS) + list(APPEND compile_options "-Wno-calloc-transposed-args") + endif() + + if(CONFIG_COMPILER_DISABLE_GCC15_WARNINGS) + list(APPEND c_compile_options "-Wno-unterminated-string-initialization") + list(APPEND c_compile_options "-Wno-header-guard") + list(APPEND cxx_compile_options "-Wno-self-move") + list(APPEND cxx_compile_options "-Wno-template-body") + list(APPEND cxx_compile_options "-Wno-dangling-reference") + list(APPEND cxx_compile_options "-Wno-defaulted-function-deleted") + endif() + + # GCC-specific options + if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + list(APPEND compile_options "-fstrict-volatile-bitfields") + if(CONFIG_COMPILER_STATIC_ANALYZER) + list(APPEND compile_options "-fanalyzer") + endif() + endif() + + if(CONFIG_ESP_SYSTEM_USE_EH_FRAME) + list(APPEND compile_options "-fasynchronous-unwind-tables") + list(APPEND link_options "-Wl,--eh-frame-hdr") + endif() + + if(CONFIG_ESP_SYSTEM_USE_FRAME_POINTER) + list(APPEND compile_options "-fno-omit-frame-pointer") + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + list(APPEND compile_options "-mno-omit-leaf-frame-pointer") + endif() + endif() + + list(APPEND link_options "-fno-lto") + + if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + # Not all versions of the MacOS linker support the -warn_commons flag. + # ld version 1053.12 (and above) have been tested to support it. + # Hence, we extract the version string from the linker output + # before including the flag. + + # Get the ld version, capturing both stdout and stderr + execute_process( + COMMAND ${CMAKE_LINKER} -v + OUTPUT_VARIABLE LD_VERSION_OUTPUT + ERROR_VARIABLE LD_VERSION_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_STRIP_TRAILING_WHITESPACE + ) + + # Combine stdout and stderr + set(LD_VERSION_OUTPUT "${LD_VERSION_OUTPUT}\n${LD_VERSION_ERROR}") + + # Extract the version string + string(REGEX MATCH "PROJECT:(ld|dyld)-([0-9]+)\\.([0-9]+)" LD_VERSION_MATCH "${LD_VERSION_OUTPUT}") + set(LD_VERSION_MAJOR_MINOR "${CMAKE_MATCH_2}.${CMAKE_MATCH_3}") + + idf_msg("Linker Version: ${LD_VERSION_MAJOR_MINOR}") + + # Compare the version with 1053.12 + if(LD_VERSION_MAJOR_MINOR VERSION_GREATER_EQUAL "1053.12") + list(APPEND link_options "-Wl,-warn_commons") + endif() + + list(APPEND link_options "-Wl,-dead_strip") + else() + list(APPEND link_options "-Wl,--gc-sections") + list(APPEND link_options "-Wl,--warn-common") + endif() + + # SMP FreeRTOS user provided minimal idle hook. This allows the user to provide + # their own copy of vApplicationPassiveIdleHook() + if(CONFIG_FREERTOS_USE_PASSIVE_IDLE_HOOK) + list(APPEND link_options "-Wl,--wrap=vApplicationPassiveIdleHook") + endif() + + # Placing jump tables in flash would cause issues with code that required + # to be placed in IRAM + list(APPEND compile_options "-fno-jump-tables") + 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 "Clang") + list(APPEND compile_options "-fno-use-cxa-atexit") # TODO IDF-10934 + else() + list(APPEND cxx_compile_options "-fuse-cxa-atexit") + endif() + + if(COMPILER_RT_LIB_NAME) + list(APPEND link_options "-rtlib=${CONFIG_COMPILER_RT_LIB_NAME}") + endif() + + if(CONFIG_LIBC_PICOLIBC) + list(APPEND c_compile_options "-specs=picolibc.specs") + list(APPEND cxx_compile_options "-specs=picolibcpp.specs") + list(APPEND link_options "-specs=picolibc.specs") + endif() + + if(CMAKE_C_COMPILER_ID MATCHES "GNU") + set(mapfile "${build_dir}/${project_name}.map") + set(target_upper "${idf_target}") + string(TOUPPER ${target_upper} target_upper) + # Add cross-reference table to the map file + list(APPEND link_options "-Wl,--cref") + # Add this symbol as a hint for esp_idf_size to guess the target name + list(APPEND link_options "-Wl,--defsym=IDF_TARGET_${target_upper}=0") + # Enable map file output + list(APPEND link_options "-Wl,--Map=${mapfile}") + # Check if linker supports --no-warn-rwx-segments + execute_process(COMMAND ${CMAKE_LINKER} "--no-warn-rwx-segments" "--version" + RESULT_VARIABLE result + OUTPUT_QUIET + ERROR_QUIET) + if(${result} EQUAL 0) + # Do not print RWX segment warnings + list(APPEND link_options "-Wl,--no-warn-rwx-segments") + endif() + if(CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING) + # Print warnings if orphan sections are found + list(APPEND link_options "-Wl,--orphan-handling=warn") + endif() + endif() + + # Prepares the list of compiler flags for remapping various paths to fixed + # names. This is used when reproducible builds are required. This function + # also creates a gdbinit file for the debugger to remap the substituted + # paths back to the real paths in the filesystem. + set(gdbinit_dir ${build_dir}/gdbinit) + set(gdbinit_path "${gdbinit_dir}/prefix_map") + + if(CONFIG_COMPILER_HIDE_PATHS_MACROS) + list(APPEND compile_options "-fmacro-prefix-map=${CMAKE_SOURCE_DIR}=.") + list(APPEND compile_options "-fmacro-prefix-map=${idf_path}=/IDF") + endif() + + if(CONFIG_APP_REPRODUCIBLE_BUILD) + list(APPEND compile_options "-fdebug-prefix-map=${idf_path}=/IDF") + list(APPEND compile_options "-fdebug-prefix-map=${project_dir}=/IDF_PROJECT") + list(APPEND compile_options "-fdebug-prefix-map=${build_dir}=/IDF_BUILD") + + # Generate mapping for component paths + set(gdbinit_file_lines) + foreach(component_name ${components_discovered}) + idf_component_get_property(component_dir ${component_name} COMPONENT_DIR) + + string(TOUPPER ${component_name} component_name_uppercase) + set(substituted_path "/COMPONENT_${component_name_uppercase}_DIR") + list(APPEND compile_options "-fdebug-prefix-map=${component_dir}=${substituted_path}") + string(APPEND gdbinit_file_lines "set substitute-path ${substituted_path} ${component_dir}\n") + endforeach() + + # Mapping for toolchain path + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-sysroot + OUTPUT_VARIABLE compiler_sysroot + ) + if(compiler_sysroot STREQUAL "") + idf_die("Failed to determine toolchain sysroot") + endif() + string(STRIP "${compiler_sysroot}" compiler_sysroot) + get_filename_component(compiler_sysroot "${compiler_sysroot}/.." REALPATH) + list(APPEND compile_options "-fdebug-prefix-map=${compiler_sysroot}=/TOOLCHAIN") + string(APPEND gdbinit_file_lines "set substitute-path /TOOLCHAIN ${compiler_sysroot}\n") + + file(WRITE "${build_dir}/prefix_map_gdbinit" "${gdbinit_file_lines}") # TODO IDF-11667 + idf_build_set_property(DEBUG_PREFIX_MAP_GDBINIT "${gdbinit_path}") + else() + set(gdbinit_file_lines "# There is no prefix map defined for the project.\n") + endif() + # Write prefix_map_gdbinit file even it is empty. + file(MAKE_DIRECTORY ${gdbinit_dir}) + file(WRITE "${gdbinit_path}" "${gdbinit_file_lines}") + + idf_build_set_property(GDBINIT_FILES_PREFIX_MAP "${gdbinit_path}") + idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) + idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND) + idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND) + idf_build_set_property(ASM_COMPILE_OPTIONS "${asm_compile_options}" APPEND) + idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND) + idf_build_set_property(LINK_OPTIONS "${link_options}" APPEND) + + # Set the LINKER_TYPE build property. Different linkers may have varying + # options, so it's important to identify the linker type to configure the + # options correctly. Currently, LINKER_TYPE is used to set the appropriate + # linker options for linking the entire archive, which differs between the + # GNU and Apple linkers when building on the host. + if(CONFIG_IDF_TARGET_LINUX AND CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin") + # Compiling for the host, and the host is macOS, so the linker is Darwin LD. + # Note, when adding support for Clang and LLD based toolchain this check will + # need to be modified. + set(linker_type "Darwin") + else() + set(linker_type "GNU") + endif() + idf_build_set_property(LINKER_TYPE "${linker_type}") +endfunction() + +#[[api +.. cmakev2:macro:: idf_project_init + + .. code-block:: cmake + + idf_project_init() + + Initialize settings that need to be configured after the project() function + is called. This must occur after the project() function and before any other + build system functions. It initializes the PROJECT_NAME and PROJECT_VER + build properties, as well as all default C, CXX, and ASM compile options, + link options, and compile definitions. +#]] +macro(idf_project_init) + idf_build_get_property(project_initialized __PROJECT_INITIALIZED) + if(NOT project_initialized) + # Ensure this function is executed only once throughout the entire + # project. + + # Set PROJECT_NAME build property + __init_project_name() + + # Set PROJECT_VER build property + __init_project_version() + + # Initialize all compilation options and defines. + __init_project_configuration() + + idf_build_set_property(__PROJECT_INITIALIZED YES) + endif() + unset(project_initialized) +endmacro() + +#[[ + __generate_project_info() + + Generate a dummy project_description.json file to enable the use of idf.py + commands that require ensure_build_directory, such as reconfigure. + + FIXME: This needs to generate a complete project_description.json for the + specified executable. +#]] +function(__generate_project_info) + idf_build_get_property(IDF_PATH IDF_PATH) + idf_build_get_property(PROJECT_NAME PROJECT_NAME) + idf_build_get_property(PROJECT_VER PROJECT_VER) + idf_build_get_property(PROJECT_PATH PROJECT_DIR) + idf_build_get_property(BUILD_DIR BUILD_DIR) + idf_build_get_property(SDKCONFIG SDKCONFIG) + idf_build_get_property(SDKCONFIG_DEFAULTS SDKCONFIG_DEFAULTS) + + set(common_component_reqs_json "\"\"") + set(build_components_json "\"\"") + set(build_component_paths_json "\"\"") + set(build_component_info_json "\"\"") + set(all_component_info_json "\"\"") + + configure_file("${IDF_PATH}/tools/cmake/project_description.json.in" + "${BUILD_DIR}/project_description.json") +endfunction() diff --git a/tools/cmakev2/test/CMakeLists.txt b/tools/cmakev2/test/CMakeLists.txt index 134c0beb85d..c8a62ab3e44 100644 --- a/tools/cmakev2/test/CMakeLists.txt +++ b/tools/cmakev2/test/CMakeLists.txt @@ -11,6 +11,8 @@ project(cmakev2 VERSION 1.2.3 LANGUAGES C CXX ASM) +idf_project_init() + # Test component priority function(test_component_priority) # Set the idf component to be replaced with a testing component of higher