-
Notifications
You must be signed in to change notification settings - Fork 7.4k
/
build.cmake
590 lines (507 loc) · 25.3 KB
/
build.cmake
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
# idf_build_get_property
#
# @brief Retrieve the value of the specified property related to ESP-IDF build.
#
# @param[out] var the variable to store the value in
# @param[in] property the property to get the value of
#
# @param[in, optional] GENERATOR_EXPRESSION (option) retrieve the generator expression for the property
# instead of actual value
function(idf_build_get_property var property)
cmake_parse_arguments(_ "GENERATOR_EXPRESSION" "" "" ${ARGN})
if(__GENERATOR_EXPRESSION)
set(val "$<TARGET_PROPERTY:__idf_build_target,${property}>")
else()
get_property(val TARGET __idf_build_target PROPERTY ${property})
endif()
set(${var} ${val} PARENT_SCOPE)
endfunction()
# idf_build_set_property
#
# @brief Set the value of the specified property related to ESP-IDF build. The property is
# also added to the internal list of build properties if it isn't there already.
#
# @param[in] property the property to set the value of
# @param[out] value value of the property
#
# @param[in, optional] APPEND (option) append the value to the current value of the
# property instead of replacing it
function(idf_build_set_property property value)
cmake_parse_arguments(_ "APPEND" "" "" ${ARGN})
if(__APPEND)
set_property(TARGET __idf_build_target APPEND PROPERTY ${property} ${value})
else()
set_property(TARGET __idf_build_target PROPERTY ${property} ${value})
endif()
# Keep track of set build properties so that they can be exported to a file that
# will be included in early expansion script.
idf_build_get_property(build_properties __BUILD_PROPERTIES)
if(NOT property IN_LIST build_properties)
idf_build_set_property(__BUILD_PROPERTIES "${property}" APPEND)
endif()
endfunction()
# idf_build_unset_property
#
# @brief Unset the value of the specified property related to ESP-IDF build. Equivalent
# to setting the property to an empty string; though it also removes the property
# from the internal list of build properties.
#
# @param[in] property the property to unset the value of
function(idf_build_unset_property property)
idf_build_set_property(${property} "") # set to an empty value
idf_build_get_property(build_properties __BUILD_PROPERTIES) # remove from tracked properties
list(REMOVE_ITEM build_properties ${property})
idf_build_set_property(__BUILD_PROPERTIES "${build_properties}")
endfunction()
#
# Retrieve the IDF_PATH repository's version, either using a version
# file or Git revision. Sets the IDF_VER build property.
#
function(__build_get_idf_git_revision)
idf_build_get_property(idf_path IDF_PATH)
git_describe(idf_ver_git "${idf_path}" "--match=v*.*")
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)
idf_build_set_property(COMPILE_DEFINITIONS "-DIDF_VER=\"${idf_ver}\"" APPEND)
git_submodule_check("${idf_path}")
idf_build_set_property(IDF_VER ${idf_ver})
endfunction()
#
# Sets initial list of build specifications (compile options, definitions, etc.) common across
# all library targets built under the ESP-IDF build system. These build specifications are added
# privately using the directory-level CMake commands (add_compile_options, include_directories, etc.)
# during component registration.
#
function(__build_set_default_build_specifications)
unset(compile_definitions)
unset(compile_options)
unset(c_compile_options)
unset(cxx_compile_options)
list(APPEND compile_definitions "-D_GNU_SOURCE")
list(APPEND compile_options "-ffunction-sections"
"-fdata-sections"
# warning-related flags
"-Wall"
"-Werror=all"
"-Wno-error=unused-function"
"-Wno-error=unused-variable"
"-Wno-error=deprecated-declarations"
"-Wextra"
"-Wno-unused-parameter"
"-Wno-sign-compare"
# always generate debug symbols (even in release mode, these don't
# go into the final binary so have no impact on size
"-ggdb")
list(APPEND c_compile_options "-std=gnu99")
list(APPEND cxx_compile_options "-std=gnu++11")
list(APPEND link_options "-Wl,--gc-sections")
idf_build_set_property(COMPILE_DEFINITIONS "${compile_definitions}" APPEND)
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(LINK_OPTIONS "${link_options}" APPEND)
endfunction()
#
# Initialize the build. This gets called upon inclusion of idf.cmake to set internal
# properties used for the processing phase of the build.
#
function(__build_init idf_path)
set(target ${IDF_TARGET})
# Create the build target, to which the ESP-IDF build properties, dependencies are attached to.
# Must be global so as to be accessible from any subdirectory in custom projects.
add_library(__idf_build_target STATIC IMPORTED GLOBAL)
# Set the Python path (which may be passed in via -DPYTHON=) and store in a build property
set_default(PYTHON "python")
file(TO_CMAKE_PATH ${PYTHON} PYTHON)
idf_build_set_property(PYTHON ${PYTHON})
idf_build_set_property(IDF_PATH ${idf_path})
idf_build_set_property(__PREFIX idf)
idf_build_set_property(__CHECK_PYTHON 1)
idf_build_set_property(IDF_COMPONENT_MANAGER 0)
__build_set_default_build_specifications()
# Add internal components to the build
idf_build_get_property(idf_path IDF_PATH)
idf_build_get_property(prefix __PREFIX)
file(GLOB component_dirs ${idf_path}/components/*)
list(SORT component_dirs)
foreach(component_dir ${component_dirs})
# A potential component must be a directory
if(IS_DIRECTORY ${component_dir})
__component_dir_quick_check(is_component ${component_dir})
if(is_component)
__component_add(${component_dir} ${prefix})
endif()
endif()
endforeach()
if("${target}" STREQUAL "linux")
set(requires_common freertos log esp_rom esp_common)
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
else()
# Set components required by all other components in the build
#
# - lwip is here so that #include <sys/socket.h> works without any special provisions
# - esp_hw_support is here for backward compatibility
set(requires_common cxx newlib freertos esp_hw_support heap log lwip soc hal esp_rom esp_common esp_system)
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}")
endif()
__build_get_idf_git_revision()
__kconfig_init()
endfunction()
# idf_build_component
#
# @brief Present a directory that contains a component to the build system.
# Relative paths are converted to absolute paths with respect to current directory.
# All calls to this command must be performed before idf_build_process.
#
# @note This command does not guarantee that the component will be processed
# during build (see the COMPONENTS argument description for command idf_build_process)
#
# @param[in] component_dir directory of the component
function(idf_build_component component_dir)
idf_build_get_property(prefix __PREFIX)
__component_add(${component_dir} ${prefix} 0)
endfunction()
#
# Resolve the requirement component to the component target created for that component.
#
function(__build_resolve_and_add_req var component_target req type)
__component_get_target(_component_target ${req})
__component_get_property(_component_registered ${component_target} __COMPONENT_REGISTERED)
if(NOT _component_target OR NOT _component_registered)
message(FATAL_ERROR "Failed to resolve component '${req}'.")
endif()
__component_set_property(${component_target} ${type} ${_component_target} APPEND)
set(${var} ${_component_target} PARENT_SCOPE)
endfunction()
#
# Build a list of components (in the form of component targets) to be added to the build
# based on public and private requirements. This list is saved in an internal property,
# __BUILD_COMPONENT_TARGETS.
#
function(__build_expand_requirements component_target)
# Since there are circular dependencies, make sure that we do not infinitely
# expand requirements for each component.
idf_build_get_property(component_targets_seen __COMPONENT_TARGETS_SEEN)
__component_get_property(component_registered ${component_target} __COMPONENT_REGISTERED)
if(component_target IN_LIST component_targets_seen OR NOT component_registered)
return()
endif()
idf_build_set_property(__COMPONENT_TARGETS_SEEN ${component_target} APPEND)
get_property(reqs TARGET ${component_target} PROPERTY REQUIRES)
get_property(priv_reqs TARGET ${component_target} PROPERTY PRIV_REQUIRES)
__component_get_property(component_name ${component_target} COMPONENT_NAME)
__component_get_property(component_alias ${component_target} COMPONENT_ALIAS)
idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON)
list(APPEND reqs ${common_reqs})
if(reqs)
list(REMOVE_DUPLICATES reqs)
list(REMOVE_ITEM reqs ${component_alias} ${component_name})
endif()
foreach(req ${reqs})
__build_resolve_and_add_req(_component_target ${component_target} ${req} __REQUIRES)
__build_expand_requirements(${_component_target})
endforeach()
foreach(req ${priv_reqs})
__build_resolve_and_add_req(_component_target ${component_target} ${req} __PRIV_REQUIRES)
__build_expand_requirements(${_component_target})
endforeach()
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
if(NOT component_target IN_LIST build_component_targets)
idf_build_set_property(__BUILD_COMPONENT_TARGETS ${component_target} APPEND)
__component_get_property(component_lib ${component_target} COMPONENT_LIB)
idf_build_set_property(__BUILD_COMPONENTS ${component_lib} APPEND)
idf_build_get_property(prefix __PREFIX)
__component_get_property(component_prefix ${component_target} __PREFIX)
__component_get_property(component_alias ${component_target} COMPONENT_ALIAS)
idf_build_set_property(BUILD_COMPONENT_ALIASES ${component_alias} APPEND)
# Only put in the prefix in the name if it is not the default one
if(component_prefix STREQUAL prefix)
__component_get_property(component_name ${component_target} COMPONENT_NAME)
idf_build_set_property(BUILD_COMPONENTS ${component_name} APPEND)
else()
idf_build_set_property(BUILD_COMPONENTS ${component_alias} APPEND)
endif()
endif()
endfunction()
#
# Write a CMake file containing set build properties, owing to the fact that an internal
# list of properties is maintained in idf_build_set_property() call. This is used to convert
# those set properties to variables in the scope the output file is included in.
#
function(__build_write_properties output_file)
idf_build_get_property(build_properties __BUILD_PROPERTIES)
foreach(property ${build_properties})
idf_build_get_property(val ${property})
set(build_properties_text "${build_properties_text}\nset(${property} \"${val}\")")
endforeach()
file(WRITE ${output_file} "${build_properties_text}")
endfunction()
#
# Check if the Python interpreter used for the build has all the required modules.
#
function(__build_check_python)
idf_build_get_property(check __CHECK_PYTHON)
if(check)
idf_build_get_property(python PYTHON)
idf_build_get_property(idf_path IDF_PATH)
message(STATUS "Checking Python dependencies...")
execute_process(COMMAND "${python}" "${idf_path}/tools/check_python_dependencies.py"
RESULT_VARIABLE result)
if(result EQUAL 1)
# check_python_dependencies returns error code 1 on failure
message(FATAL_ERROR "Some Python dependencies must be installed. Check above message for details.")
elseif(NOT result EQUAL 0)
# means check_python_dependencies.py failed to run at all, result should be an error message
message(FATAL_ERROR "Failed to run Python dependency check. Python: ${python}, Error: ${result}")
endif()
endif()
endfunction()
#
# Prepare for component processing expanding each component's project include
#
macro(__build_process_project_includes)
# Include the sdkconfig cmake file, since the following operations require
# knowledge of config values.
idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
include(${sdkconfig_cmake})
# Make each build property available as a read-only variable
idf_build_get_property(build_properties __BUILD_PROPERTIES)
foreach(build_property ${build_properties})
idf_build_get_property(val ${build_property})
set(${build_property} "${val}")
endforeach()
# Check that the CMake target value matches the Kconfig target value.
__target_check()
idf_build_get_property(build_component_targets __BUILD_COMPONENT_TARGETS)
# Include each component's project_include.cmake
foreach(component_target ${build_component_targets})
__component_get_property(dir ${component_target} COMPONENT_DIR)
__component_get_property(_name ${component_target} COMPONENT_NAME)
set(COMPONENT_NAME ${_name})
set(COMPONENT_DIR ${dir})
set(COMPONENT_PATH ${dir}) # this is deprecated, users are encouraged to use COMPONENT_DIR;
# retained for compatibility
if(EXISTS ${COMPONENT_DIR}/project_include.cmake)
include(${COMPONENT_DIR}/project_include.cmake)
endif()
endforeach()
endmacro()
#
# Utility macro for setting default property value if argument is not specified
# for idf_build_process().
#
macro(__build_set_default var default)
set(_var __${var})
if(NOT "${${_var}}" STREQUAL "")
idf_build_set_property(${var} "${${_var}}")
else()
idf_build_set_property(${var} "${default}")
endif()
unset(_var)
endmacro()
#
# Import configs as build instance properties so that they are accessible
# using idf_build_get_config(). Config has to have been generated before calling
# this command.
#
function(__build_import_configs)
# Include the sdkconfig cmake file, since the following operations require
# knowledge of config values.
idf_build_get_property(sdkconfig_cmake SDKCONFIG_CMAKE)
include(${sdkconfig_cmake})
idf_build_set_property(__CONFIG_VARIABLES "${CONFIGS_LIST}")
foreach(config ${CONFIGS_LIST})
set_property(TARGET __idf_build_target PROPERTY ${config} "${${config}}")
endforeach()
endfunction()
# idf_build_process
#
# @brief Main processing step for ESP-IDF build: config generation, adding components to the build,
# dependency resolution, etc.
#
# @param[in] target ESP-IDF target
#
# @param[in, optional] PROJECT_DIR (single value) directory of the main project the buildsystem
# is processed for; defaults to CMAKE_SOURCE_DIR
# @param[in, optional] PROJECT_VER (single value) version string of the main project; defaults
# to 1
# @param[in, optional] PROJECT_NAME (single value) main project name, defaults to CMAKE_PROJECT_NAME
# @param[in, optional] SDKCONFIG (single value) sdkconfig output path, defaults to PROJECT_DIR/sdkconfig
# if PROJECT_DIR is set and CMAKE_SOURCE_DIR/sdkconfig if not
# @param[in, optional] SDKCONFIG_DEFAULTS (single value) config defaults file to use for the build; defaults
# to none (Kconfig defaults or previously generated config are used)
# @param[in, optional] BUILD_DIR (single value) directory for build artifacts; defautls to CMAKE_BINARY_DIR
# @param[in, optional] COMPONENTS (multivalue) select components to process among the components
# known by the build system
# (added via `idf_build_component`). This argument is used to trim the build.
# Other components are automatically added if they are required
# in the dependency chain, i.e.
# the public and private requirements of the components in this list
# are automatically added, and in
# turn the public and private requirements of those requirements,
# so on and so forth. If not specified, all components known to the build system
# are processed.
macro(idf_build_process target)
set(options)
set(single_value PROJECT_DIR PROJECT_VER PROJECT_NAME BUILD_DIR SDKCONFIG)
set(multi_value COMPONENTS SDKCONFIG_DEFAULTS)
cmake_parse_arguments(_ "${options}" "${single_value}" "${multi_value}" ${ARGN})
idf_build_set_property(BOOTLOADER_BUILD "${BOOTLOADER_BUILD}")
# Check build target is specified. Since this target corresponds to a component
# name, the target component is automatically added to the list of common component
# requirements.
if(target STREQUAL "")
message(FATAL_ERROR "Build target not specified.")
endif()
idf_build_set_property(IDF_TARGET ${target})
__build_set_default(PROJECT_DIR ${CMAKE_SOURCE_DIR})
__build_set_default(PROJECT_NAME ${CMAKE_PROJECT_NAME})
__build_set_default(PROJECT_VER 1)
__build_set_default(BUILD_DIR ${CMAKE_BINARY_DIR})
idf_build_get_property(project_dir PROJECT_DIR)
__build_set_default(SDKCONFIG "${project_dir}/sdkconfig")
__build_set_default(SDKCONFIG_DEFAULTS "")
# Check for required Python modules
__build_check_python()
idf_build_get_property(target IDF_TARGET)
if(NOT "${target}" STREQUAL "linux")
idf_build_set_property(__COMPONENT_REQUIRES_COMMON ${target} APPEND)
endif()
# Call for component manager to download dependencies for all components
idf_build_get_property(idf_component_manager IDF_COMPONENT_MANAGER)
if(idf_component_manager EQUAL 1)
idf_build_get_property(build_dir BUILD_DIR)
set(managed_components_list_file ${build_dir}/managed_components_list.temp.cmake)
set(local_components_list_file ${build_dir}/local_components_list.temp.yml)
set(__contents "components:\n")
foreach(__component_name ${components})
idf_component_get_property(__component_dir ${__component_name} COMPONENT_DIR)
set(__contents "${__contents} - name: \"${__component_name}\"\n path: \"${__component_dir}\"\n")
endforeach()
file(WRITE ${local_components_list_file} "${__contents}")
# Call for the component manager to prepare remote dependencies
idf_build_get_property(python PYTHON)
idf_build_get_property(component_manager_interface_version __COMPONENT_MANAGER_INTERFACE_VERSION)
execute_process(COMMAND ${python}
"-m"
"idf_component_manager.prepare_components"
"--project_dir=${project_dir}"
"--interface_version=${component_manager_interface_version}"
"prepare_dependencies"
"--local_components_list_file=${local_components_list_file}"
"--managed_components_list_file=${managed_components_list_file}"
RESULT_VARIABLE result
ERROR_VARIABLE error)
if(NOT result EQUAL 0)
message(FATAL_ERROR "${error}")
endif()
include(${managed_components_list_file})
# Add managed components to list of all components
# `managed_components` contains the list of components installed by the component manager
# It is defined in the temporary managed_components_list_file file
set(__COMPONENTS "${__COMPONENTS};${managed_components}")
file(REMOVE ${managed_components_list_file})
file(REMOVE ${local_components_list_file})
else()
message(VERBOSE "IDF Component manager was explicitly disabled by setting IDF_COMPONENT_MANAGER=0")
idf_build_get_property(__component_targets __COMPONENT_TARGETS)
set(__components_with_manifests "")
foreach(__component_target ${__component_targets})
__component_get_property(__component_dir ${__component_target} COMPONENT_DIR)
if(EXISTS "${__component_dir}/idf_component.yml")
set(__components_with_manifests "${__components_with_manifests}\t${__component_dir}\n")
endif()
endforeach()
if(NOT "${__components_with_manifests}" STREQUAL "")
message(WARNING "\"idf_component.yml\" file was found for components:\n${__components_with_manifests}"
"However, the component manager is not enabled.")
endif()
endif()
# Perform early expansion of component CMakeLists.txt in CMake scripting mode.
# It is here we retrieve the public and private requirements of each component.
# It is also here we add the common component requirements to each component's
# own requirements.
__component_get_requirements()
idf_build_get_property(component_targets __COMPONENT_TARGETS)
# Finally, do component expansion. In this case it simply means getting a final list
# of build component targets given the requirements set by each component.
# Check if we need to trim the components first, and build initial components list
# from that.
if(__COMPONENTS)
unset(component_targets)
foreach(component ${__COMPONENTS})
__component_get_target(component_target ${component})
if(NOT component_target)
message(FATAL_ERROR "Failed to resolve component '${component}'.")
endif()
list(APPEND component_targets ${component_target})
endforeach()
endif()
foreach(component_target ${component_targets})
__build_expand_requirements(${component_target})
endforeach()
idf_build_unset_property(__COMPONENT_TARGETS_SEEN)
# Get a list of common component requirements in component targets form (previously
# we just have a list of component names)
idf_build_get_property(common_reqs __COMPONENT_REQUIRES_COMMON)
foreach(common_req ${common_reqs})
__component_get_target(component_target ${common_req})
__component_get_property(lib ${component_target} COMPONENT_LIB)
idf_build_set_property(___COMPONENT_REQUIRES_COMMON ${lib} APPEND)
endforeach()
# Generate config values in different formats
idf_build_get_property(sdkconfig SDKCONFIG)
idf_build_get_property(sdkconfig_defaults SDKCONFIG_DEFAULTS)
__kconfig_generate_config("${sdkconfig}" "${sdkconfig_defaults}")
__build_import_configs()
# All targets built under this scope is with the ESP-IDF build system
set(ESP_PLATFORM 1)
idf_build_set_property(COMPILE_DEFINITIONS "-DESP_PLATFORM" APPEND)
# Perform component processing (inclusion of project_include.cmake, adding component
# subdirectories, creating library targets, linking libraries, etc.)
__build_process_project_includes()
idf_build_get_property(idf_path IDF_PATH)
add_subdirectory(${idf_path} ${build_dir}/esp-idf)
unset(ESP_PLATFORM)
endmacro()
# idf_build_executable
#
# @brief Specify the executable the build system can attach dependencies to (for generating
# files used for linking, targets which should execute before creating the specified executable,
# generating additional binary files, generating files related to flashing, etc.)
function(idf_build_executable elf)
# Set additional link flags for the executable
idf_build_get_property(link_options LINK_OPTIONS)
# Using LINK_LIBRARIES here instead of LINK_OPTIONS, as the latter is not in CMake 3.5.
set_property(TARGET ${elf} APPEND PROPERTY LINK_LIBRARIES "${link_options}")
# Propagate link dependencies from component library targets to the executable
idf_build_get_property(link_depends __LINK_DEPENDS)
set_property(TARGET ${elf} APPEND PROPERTY LINK_DEPENDS "${link_depends}")
# Set the EXECUTABLE_NAME and EXECUTABLE properties since there are generator expression
# from components that depend on it
get_filename_component(elf_name ${elf} NAME_WE)
get_target_property(elf_dir ${elf} BINARY_DIR)
idf_build_set_property(EXECUTABLE_NAME ${elf_name})
idf_build_set_property(EXECUTABLE ${elf})
idf_build_set_property(EXECUTABLE_DIR "${elf_dir}")
# Add dependency of the build target to the executable
add_dependencies(${elf} __idf_build_target)
endfunction()
# idf_build_get_config
#
# @brief Get value of specified config variable
function(idf_build_get_config var config)
cmake_parse_arguments(_ "GENERATOR_EXPRESSION" "" "" ${ARGN})
if(__GENERATOR_EXPRESSION)
set(val "$<TARGET_PROPERTY:__idf_build_target,${config}>")
else()
get_property(val TARGET __idf_build_target PROPERTY ${config})
endif()
set(${var} ${val} PARENT_SCOPE)
endfunction()