Skip to content

Commit 6834b75

Browse files
committed
fix: deduplicate runtime dependency and resource copies to avoid parallel copy races
1 parent 4cb0d09 commit 6834b75

1 file changed

Lines changed: 66 additions & 27 deletions

File tree

‎CMake/Target.cmake‎

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,37 @@ function(exp_gather_target_runtime_dependencies_recurse)
8686
set(${arg_OUT_DEP_TARGET} ${result_dep_target} PARENT_SCOPE)
8787
endfunction()
8888

89+
function(exp_add_shared_copy_target)
90+
set(options "")
91+
set(singleValueArgs KEY SRC DST MAKE_DIR OUTPUT_TARGET)
92+
set(multiValueArgs DEPENDS)
93+
cmake_parse_arguments(arg "${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGN})
94+
95+
string(MAKE_C_IDENTIFIER "${arg_KEY}" key_id)
96+
set(registry_property EXP_SHARED_COPY_TARGET_${SUB_PROJECT_NAME}_${key_id})
97+
98+
get_property(copy_target GLOBAL PROPERTY ${registry_property})
99+
if (NOT copy_target)
100+
set(copy_target ${SUB_PROJECT_NAME}.Copy.${key_id})
101+
if (DEFINED arg_MAKE_DIR)
102+
set(copy_commands COMMAND ${CMAKE_COMMAND} -E make_directory ${arg_MAKE_DIR})
103+
else ()
104+
set(copy_commands "")
105+
endif ()
106+
list(APPEND copy_commands COMMAND ${CMAKE_COMMAND} -E copy_if_different ${arg_SRC} ${arg_DST})
107+
108+
add_custom_target(${copy_target} ${copy_commands})
109+
set_target_properties(${copy_target} PROPERTIES FOLDER ${AUX_TARGETS_FOLDER})
110+
set_property(GLOBAL PROPERTY ${registry_property} ${copy_target})
111+
endif ()
112+
113+
if (arg_DEPENDS)
114+
add_dependencies(${copy_target} ${arg_DEPENDS})
115+
endif ()
116+
117+
set(${arg_OUTPUT_TARGET} ${copy_target} PARENT_SCOPE)
118+
endfunction()
119+
89120
function(exp_process_runtime_dependencies)
90121
set(options NOT_INSTALL)
91122
set(singleValueArgs NAME)
@@ -105,28 +136,37 @@ function(exp_process_runtime_dependencies)
105136
OUT_DEP_TARGET dep_dep_targets
106137
)
107138
list(APPEND runtime_deps ${dep_target_runtime_deps})
108-
list(APPEND dep_targets ${dep_dep_targets})
109139
endforeach ()
110140

111-
set(copy_commands COMMAND ${CMAKE_COMMAND} -E make_directory $<TARGET_FILE_DIR:${arg_NAME}>)
112-
foreach(r ${runtime_deps})
113-
list(APPEND copy_commands COMMAND ${CMAKE_COMMAND} -E copy_if_different ${r} $<TARGET_FILE_DIR:${arg_NAME}>)
114-
endforeach()
115-
if (NOT "${copy_commands}" STREQUAL "")
116-
set(custom_target_name ${arg_NAME}.CopyRuntimeDeps)
117-
add_custom_target(
118-
${custom_target_name}
119-
${copy_commands}
120-
)
141+
if (runtime_deps)
142+
list(REMOVE_DUPLICATES runtime_deps)
143+
endif ()
121144

122-
add_dependencies(${arg_NAME} ${custom_target_name})
123-
foreach (t ${dep_targets})
124-
add_dependencies(${custom_target_name} ${t})
125-
endforeach ()
145+
exp_get_runtime_output_dir(OUTPUT out_dir)
146+
foreach (r ${runtime_deps})
147+
set(copy_depends "")
148+
if ("${r}" MATCHES "^\\$<TARGET_FILE:(.+)>$")
149+
set(producer ${CMAKE_MATCH_1})
150+
if (TARGET ${producer})
151+
get_target_property(producer_imported ${producer} IMPORTED)
152+
if (NOT producer_imported)
153+
set(copy_depends ${producer})
154+
endif ()
155+
endif ()
156+
endif ()
126157

127-
set_target_properties(${custom_target_name} PROPERTIES FOLDER ${AUX_TARGETS_FOLDER})
128-
endif ()
129-
if (NOT arg_NOT_INSTALL AND NOT "${runtime_deps}" STREQUAL "")
158+
exp_add_shared_copy_target(
159+
KEY ${r}
160+
SRC ${r}
161+
DST ${out_dir}
162+
MAKE_DIR ${out_dir}
163+
DEPENDS ${copy_depends}
164+
OUTPUT_TARGET copy_target
165+
)
166+
add_dependencies(${arg_NAME} ${copy_target})
167+
endforeach ()
168+
169+
if (NOT arg_NOT_INSTALL AND runtime_deps)
130170
install(
131171
FILES ${runtime_deps} DESTINATION ${SUB_PROJECT_NAME}/Binaries
132172
)
@@ -153,29 +193,28 @@ function(exp_add_resources_copy_command)
153193
set(multiValueArgs RES)
154194
cmake_parse_arguments(arg "${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGN})
155195

196+
exp_get_runtime_output_dir(OUTPUT out_dir)
156197
foreach(r ${arg_RES})
157198
exp_expand_resource_path_expression(
158199
INPUT ${r}
159200
OUTPUT_SRC src
160201
OUTPUT_DST dst
161202
)
162203

163-
list(APPEND copy_commands COMMAND ${CMAKE_COMMAND} -E copy_if_different ${src} $<TARGET_FILE_DIR:${arg_NAME}>/${dst})
204+
exp_add_shared_copy_target(
205+
KEY ${dst}
206+
SRC ${src}
207+
DST ${out_dir}/${dst}
208+
OUTPUT_TARGET copy_target
209+
)
210+
add_dependencies(${arg_NAME} ${copy_target})
164211

165212
cmake_path(SET dst_path NORMALIZE "${SUB_PROJECT_NAME}/Binaries/${dst}")
166213
cmake_path(GET dst_path PARENT_PATH dst_dir)
167214
if (NOT arg_NOT_INSTALL)
168215
install(FILES ${src} DESTINATION ${dst_dir})
169216
endif ()
170217
endforeach()
171-
172-
set(copy_res_target_name ${arg_NAME}.CopyRes)
173-
add_custom_target(
174-
${copy_res_target_name}
175-
${copy_commands}
176-
)
177-
set_target_properties(${copy_res_target_name} PROPERTIES FOLDER ${AUX_TARGETS_FOLDER})
178-
add_dependencies(${arg_NAME} ${copy_res_target_name})
179218
endfunction()
180219

181220
function(exp_gather_target_libs)

0 commit comments

Comments
 (0)