forked from espressif/esp-idf
fix(cmakev2/build): fix the generation of the link map file
The link flag for generating the map file is currently added globally to the link_options. If multiple executables are generated, the link map file is overwritten by the last created executable. Since cmakev2 supports building multiple executables, the link map file options need to be set for each executable individually. To address this, add a new MAPFILE_TARGET option to the idf_build_executable function. When set, the link map file will be generated by the linker, and a target specified in the MAPFILE_TARGET option will be created for the map file. This also splits the idf_project_default macro. Only the idf_project_init macro needs be called within the global scope, as it includes the project_include.cmake files and the cmake version of the configuration. The remaining functionality of the idf_project_default macro is implemented in a __project_default helper function to avoid polluting the global variable space. Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
This commit is contained in:
@@ -503,6 +503,16 @@ endfunction()
|
||||
|
||||
Optional ``executable`` suffix.
|
||||
|
||||
*MAPFILE_TARGET[in,opt]*
|
||||
|
||||
Name of the target for the map file. If provided, the link map file is
|
||||
generated for the specified executable, and the ``MAPFILE_TARGET``
|
||||
target name is created for it. The ``MAPFILE_PATH`` property with the
|
||||
link map file path is added to the ``MAPFILE_TARGET`` target. This can
|
||||
be used for other targets that depend on the link map file. The link map file
|
||||
is not generated on Darwin host, so the target ``MAPFILE_TARGET`` may not
|
||||
be created if link map file is not generated.
|
||||
|
||||
Create a new executable target using the name specified in the
|
||||
``executable`` argument, and link it to the library created with the
|
||||
component names provided in the ``COMPONENTS`` option. If the
|
||||
@@ -513,7 +523,7 @@ endfunction()
|
||||
#]]
|
||||
function(idf_build_executable executable)
|
||||
set(options)
|
||||
set(one_value NAME SUFFIX)
|
||||
set(one_value NAME SUFFIX MAPFILE_TARGET)
|
||||
set(multi_value COMPONENTS)
|
||||
cmake_parse_arguments(ARG "${options}" "${one_value}" "${multi_value}" ${ARGN})
|
||||
|
||||
@@ -536,9 +546,7 @@ function(idf_build_executable executable)
|
||||
endif()
|
||||
add_executable(${executable} "${executable_src}")
|
||||
|
||||
if(ARG_NAME)
|
||||
set_target_properties(${executable} PROPERTIES OUTPUT_NAME ${ARG_NAME})
|
||||
endif()
|
||||
set_target_properties(${executable} PROPERTIES OUTPUT_NAME ${ARG_NAME})
|
||||
|
||||
if(ARG_SUFFIX)
|
||||
set_target_properties(${executable} PROPERTIES SUFFIX ${ARG_SUFFIX})
|
||||
@@ -546,6 +554,20 @@ function(idf_build_executable executable)
|
||||
|
||||
target_link_libraries(${executable} PRIVATE ${library})
|
||||
|
||||
idf_build_get_property(linker_type LINKER_TYPE)
|
||||
if(ARG_MAPFILE_TARGET AND "${linker_type}" STREQUAL "GNU")
|
||||
set(mapfile "${CMAKE_BINARY_DIR}/${ARG_NAME}.map")
|
||||
target_link_options(${executable} PRIVATE "LINKER:--Map=${mapfile}")
|
||||
add_custom_command(
|
||||
OUTPUT "${mapfile}"
|
||||
DEPENDS ${executable}
|
||||
)
|
||||
add_custom_target(${ARG_MAPFILE_TARGET}
|
||||
DEPENDS "${mapfile}"
|
||||
)
|
||||
set_target_properties(${ARG_MAPFILE_TARGET} PROPERTIES MAPFILE_PATH ${mapfile})
|
||||
endif()
|
||||
|
||||
set_target_properties(${executable} PROPERTIES LIBRARY_INTERFACE ${library})
|
||||
endfunction()
|
||||
|
||||
|
||||
+49
-34
@@ -90,6 +90,21 @@ function(__init_project_configuration)
|
||||
idf_build_get_property(project_dir PROJECT_DIR)
|
||||
idf_build_get_property(project_name PROJECT_NAME)
|
||||
|
||||
# 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}")
|
||||
|
||||
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")
|
||||
@@ -407,16 +422,13 @@ function(__init_project_configuration)
|
||||
list(APPEND link_options "-specs=picolibc.specs")
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
|
||||
set(mapfile "${build_dir}/${project_name}.map")
|
||||
if("${linker_type}" STREQUAL "GNU")
|
||||
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
|
||||
@@ -486,21 +498,6 @@ function(__init_project_configuration)
|
||||
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()
|
||||
|
||||
#[[
|
||||
@@ -694,26 +691,22 @@ function(idf_build_generate_flasher_args)
|
||||
INPUT "${build_dir}/flasher_args.json.in")
|
||||
endfunction()
|
||||
|
||||
#[[api
|
||||
.. cmakev2:macro:: idf_project_default
|
||||
#[[
|
||||
.. cmakev2:macro:: __project_default
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
idf_project_default()
|
||||
__project_default()
|
||||
|
||||
Create a default project executable based on the main component and its
|
||||
transitive dependencies. The executable name is derived from the
|
||||
``PROJECT_NAME`` variable, which by default uses the ``CMAKE_PROJECT_NAME``
|
||||
value specified in the CMake's ``project()`` call.
|
||||
|
||||
Generate the binary image for the executable, signed or unsigned based on
|
||||
the configuration, and add flash targets for it.
|
||||
Helper function implementing the main idf_project_default macro
|
||||
functionality, preventing global variable scope pollution.
|
||||
#]]
|
||||
macro(idf_project_default)
|
||||
idf_project_init()
|
||||
function(__project_default)
|
||||
idf_build_get_property(build_dir BUILD_DIR)
|
||||
idf_build_get_property(executable PROJECT_NAME)
|
||||
idf_build_executable("${executable}" COMPONENTS main SUFFIX ".elf")
|
||||
idf_build_executable("${executable}"
|
||||
COMPONENTS main
|
||||
MAPFILE_TARGET "${executable}_mapfile")
|
||||
|
||||
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
|
||||
# Is it possible to have a configuration where
|
||||
@@ -770,7 +763,29 @@ macro(idf_project_default)
|
||||
idf_create_uf2("${executable}"
|
||||
TARGET uf2-app
|
||||
APP_ONLY)
|
||||
endfunction()
|
||||
|
||||
unset(build_dir)
|
||||
unset(executable)
|
||||
#[[api
|
||||
.. cmakev2:macro:: idf_project_default
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
idf_project_default()
|
||||
|
||||
Create a default project executable based on the main component and its
|
||||
transitive dependencies. The executable name is derived from the
|
||||
``PROJECT_NAME`` variable, which by default uses the ``CMAKE_PROJECT_NAME``
|
||||
value specified in the CMake's ``project()`` call.
|
||||
|
||||
Generate the binary image for the executable, signed or unsigned based on
|
||||
the configuration, and add flash targets for it.
|
||||
#]]
|
||||
macro(idf_project_default)
|
||||
idf_project_init()
|
||||
# Only the idf_project_init macro needs be called within the global scope,
|
||||
# as it includes the project_include.cmake files and the cmake version of
|
||||
# the configuration. The remaining functionality of the idf_project_default
|
||||
# macro is implemented in a __project_default helper function to avoid
|
||||
# polluting the global variable space.
|
||||
__project_default()
|
||||
endmacro()
|
||||
|
||||
@@ -219,7 +219,8 @@ endfunction()
|
||||
# idf.py confserver-fatfs
|
||||
function(test_executable)
|
||||
idf_build_executable(fatfs_example
|
||||
COMPONENTS fatfs_example)
|
||||
COMPONENTS fatfs_example
|
||||
MAPFILE_TARGET fatfs_example_mapfile)
|
||||
idf_build_binary(fatfs_example
|
||||
TARGET fatfs_example_bin
|
||||
OUTPUT_FILE fatfs_example.bin)
|
||||
@@ -236,7 +237,8 @@ function(test_executable)
|
||||
|
||||
|
||||
idf_build_executable(hello_world_example
|
||||
COMPONENTS hello_world_example)
|
||||
COMPONENTS hello_world_example
|
||||
MAPFILE_TARGET hello_world_example_mapfile)
|
||||
idf_build_binary(hello_world_example
|
||||
TARGET hello_world_example_bin
|
||||
OUTPUT_FILE hello_world_example.bin)
|
||||
|
||||
Reference in New Issue
Block a user