3 # Define a variable to a default value if otherwise unset.
5 # Priority for new value is:
6 # - Existing cmake value (ie set with cmake -D, or already set in CMakeLists)
7 # - Value of any non-empty environment variable of the same name
8 # - Default value as provided to function
10 function(set_default variable default_value)
12 if(DEFINED ENV{${variable}} AND NOT "$ENV{${variable}}" STREQUAL "")
13 set(${variable} $ENV{${variable}} PARENT_SCOPE)
15 set(${variable} ${default_value} PARENT_SCOPE)
22 # Take a variable whose value was space-delimited values, convert to a cmake
23 # list (semicolon-delimited)
25 # Note: if using this for directories, keeps the issue in place that
26 # directories can't contain spaces...
28 # TODO: look at cmake separate_arguments, which is quote-aware
29 function(spaces2list variable_name)
30 string(REPLACE " " ";" tmp "${${variable_name}}")
31 set("${variable_name}" "${tmp}" PARENT_SCOPE)
37 # Take a variable with multiple lines of output in it, convert it
38 # to a cmake list (semicolon-delimited), one line per item
40 function(lines2list variable_name)
41 string(REGEX REPLACE "\r?\n" ";" tmp "${${variable_name}}")
42 string(REGEX REPLACE ";;" ";" tmp "${tmp}")
43 set("${variable_name}" "${tmp}" PARENT_SCOPE)
49 # If 'source' has different md5sum to 'destination' (or destination
50 # does not exist, move it across.
52 # If 'source' has the same md5sum as 'destination', delete 'source'.
54 # Avoids timestamp updates for re-generated files where content hasn't
56 function(move_if_different source destination)
58 file(GLOB dest_exists ${destination})
60 file(MD5 ${source} source_md5)
61 file(MD5 ${destination} dest_md5)
62 if(source_md5 STREQUAL dest_md5)
68 message("Moving ${source} -> ${destination}")
69 file(RENAME ${source} ${destination})
71 message("Not moving ${source} -> ${destination}")
72 file(REMOVE ${source})
78 # add_compile_options variant for C++ code only
80 # This adds global options, set target properties for
81 # component-specific flags
82 function(add_cxx_compile_options)
83 foreach(option ${ARGV})
84 # note: the Visual Studio Generator doesn't support this...
85 add_compile_options($<$<COMPILE_LANGUAGE:CXX>:${option}>)
89 # add_compile_options variant for C code only
91 # This adds global options, set target properties for
92 # component-specific flags
93 function(add_c_compile_options)
94 foreach(option ${ARGV})
95 # note: the Visual Studio Generator doesn't support this...
96 add_compile_options($<$<COMPILE_LANGUAGE:C>:${option}>)
101 # target_add_binary_data adds binary data into the built target,
102 # by converting it to a generated source file which is then compiled
103 # to a binary object as part of the build
104 function(target_add_binary_data target embed_file embed_type)
106 get_filename_component(embed_file "${embed_file}" ABSOLUTE)
108 get_filename_component(name "${embed_file}" NAME)
109 set(embed_srcfile "${CMAKE_BINARY_DIR}/${name}.S")
111 add_custom_command(OUTPUT "${embed_srcfile}"
112 COMMAND "${CMAKE_COMMAND}"
113 -D "DATA_FILE=${embed_file}"
114 -D "SOURCE_FILE=${embed_srcfile}"
115 -D "FILE_TYPE=${embed_type}"
116 -P "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake"
117 MAIN_DEPENDENCY "${embed_file}"
118 DEPENDENCIES "${IDF_PATH}/tools/cmake/scripts/data_file_embed_asm.cmake"
119 WORKING_DIRECTORY "${CMAKE_BINARY_DIR}")
121 set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${embed_srcfile}")
123 target_sources("${target}" PRIVATE "${embed_srcfile}")
126 macro(include_if_exists path)
132 # Append a single line to the file specified
133 # The line ending is determined by the host OS
134 function(file_append_line file line)
135 if(DEFINED ENV{MSYSTEM} OR CMAKE_HOST_WIN32)
136 set(line_ending "\r\n")
138 set(line_ending "\n")
140 file(READ ${file} existing)
141 string(FIND ${existing} ${line_ending} last_newline REVERSE)
142 string(LENGTH ${existing} length)
143 math(EXPR length "${length}-1")
144 if(NOT length EQUAL last_newline) # file doesn't end with a newline
145 file(APPEND "${file}" "${line_ending}")
147 file(APPEND "${file}" "${line}${line_ending}")
150 # Add one or more linker scripts to the target, including a link-time dependency
152 # Automatically adds a -L search path for the containing directory (if found),
153 # and then adds -T with the filename only. This allows INCLUDE directives to be
154 # used to include other linker scripts in the same directory.
155 function(target_linker_script target)
156 foreach(scriptfile ${ARGN})
157 get_filename_component(abs_script "${scriptfile}" ABSOLUTE)
158 message(STATUS "Adding linker script ${abs_script}")
160 get_filename_component(search_dir "${abs_script}" DIRECTORY)
161 get_filename_component(scriptname "${abs_script}" NAME)
163 get_target_property(link_libraries "${target}" LINK_LIBRARIES)
164 list(FIND "${link_libraries}" "-L ${search_dir}" found_search_dir)
165 if(found_search_dir EQUAL "-1") # not already added as a search path
166 target_link_libraries("${target}" "-L ${search_dir}")
169 target_link_libraries("${target}" "-T ${scriptname}")
171 # Note: In ESP-IDF, most targets are libraries and libary LINK_DEPENDS don't propagate to
172 # executable(s) the library is linked to. This is done manually in components.cmake.
173 set_property(TARGET "${target}" APPEND PROPERTY LINK_DEPENDS "${abs_script}")
177 # Convert a CMake list to a JSON list and store it in a variable
178 function(make_json_list list variable)
179 string(REPLACE ";" "\", \"" result "[ \"${list}\" ]")
180 set("${variable}" "${result}" PARENT_SCOPE)
185 # Adds a prefix to each item in the specified list.
187 function(add_prefix var prefix)
189 list(APPEND newlist "${prefix}${elm}")
191 set(${var} "${newlist}" PARENT_SCOPE)