Skip to content

Commit fe9b506

Browse files
hageboeckpcanal
andcommitted
[CMake] Speed up copying of headers.
To copy headers to the build tree, ROOT was creating one target per header. Headers are copied in packs of 100 (Windows doesn't support very long command lines). This significantly reduces the number of CMake targets and speeds up the build. A simple test that only moves headers: make -j6 move_headers New Old 1st invocation 10.7 s 34.5 s 2nd invocation 2.7 s 3.8 s Fix #14953. Co-authored-by: Philippe Canal <pcanal@fnal.gov>
1 parent ccad25b commit fe9b506

File tree

3 files changed

+68
-23
lines changed

3 files changed

+68
-23
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,10 @@ endif()
383383
ROOT_ADD_TEST_SUBDIRECTORY(test)
384384
ROOT_ADD_TEST_SUBDIRECTORY(tutorials)
385385

386+
# Each subdirectory added above will register headers to be copied to the build tree.
387+
# Here, the copy targets are created:
388+
ROOT_CREATE_HEADER_COPY_TARGETS()
389+
386390
get_property(__allHeaders GLOBAL PROPERTY ROOT_HEADER_TARGETS)
387391
get_property(__allBuiltins GLOBAL PROPERTY ROOT_BUILTIN_TARGETS)
388392
add_custom_target(move_headers ALL DEPENDS ${__allHeaders} ${__allBuiltins} gitinfotxt)

builtins/nlohmann/CMakeLists.txt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ unset(JSON_H)
1414
add_custom_command(
1515
OUTPUT ${CMAKE_BINARY_DIR}/include/nlohmann/json.hpp
1616
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/builtins/nlohmann/json.hpp ${CMAKE_BINARY_DIR}/include/nlohmann/json.hpp
17-
COMMENT "Copying nlohmann/json.hpp header to ${CMAKE_BINARY_DIR}/include"
1817
DEPENDS ${CMAKE_SOURCE_DIR}/builtins/nlohmann/json.hpp)
19-
2018
add_custom_target(builtin_nlohmann_json_incl DEPENDS ${CMAKE_BINARY_DIR}/include/nlohmann/json.hpp)
21-
22-
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_TARGETS builtin_nlohmann_json_incl)
19+
set_property(GLOBAL APPEND PROPERTY ROOT_BUILTIN_TARGETS builtin_nlohmann_json_incl)
2320

2421
install(FILES ${CMAKE_SOURCE_DIR}/builtins/nlohmann/json.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/nlohmann/)
2522

cmake/modules/RootMacros.cmake

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1217,7 +1217,9 @@ function(ROOT_FIND_DIRS_WITH_HEADERS result_dirs)
12171217
endfunction()
12181218

12191219
#---------------------------------------------------------------------------------------------------
1220-
#---ROOT_INSTALL_HEADERS([dir1 dir2 ...] OPTIONS [options])
1220+
#---ROOT_INSTALL_HEADERS([dir1 dir2 ...] [FILTER <regex>])
1221+
# Glob for headers in the folder where this target is defined, and install them in
1222+
# <buildDir>/include
12211223
#---------------------------------------------------------------------------------------------------
12221224
function(ROOT_INSTALL_HEADERS)
12231225
CMAKE_PARSE_ARGUMENTS(ARG "OPTIONS" "" "FILTER" ${ARGN})
@@ -1232,35 +1234,77 @@ function(ROOT_INSTALL_HEADERS)
12321234
set (options ${options} REGEX "${f}" EXCLUDE)
12331235
endforeach()
12341236
set (filter "(${filter})")
1237+
set(include_files "")
12351238
foreach(d ${dirs})
12361239
install(DIRECTORY ${d} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
12371240
COMPONENT headers
12381241
${options})
12391242
string(REGEX REPLACE "(.*)/$" "\\1" d ${d})
1240-
ROOT_GLOB_FILES(include_files
1243+
ROOT_GLOB_FILES(globbed_files
12411244
RECURSE
1242-
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/${d}
1245+
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
12431246
FILTER ${filter}
12441247
${d}/*.h ${d}/*.hxx ${d}/*.icc )
1245-
foreach (include_file ${include_files})
1246-
set (src ${CMAKE_CURRENT_SOURCE_DIR}/${d}/${include_file})
1247-
set (dst ${CMAKE_BINARY_DIR}/include/${include_file})
1248-
add_custom_command(
1249-
OUTPUT ${dst}
1250-
COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dst}
1251-
COMMENT "Copying header ${src} to ${CMAKE_BINARY_DIR}/include"
1252-
DEPENDS ${src})
1253-
list(APPEND dst_list ${dst})
1254-
endforeach()
1248+
list(APPEND include_files ${globbed_files})
1249+
endforeach()
1250+
1251+
string(REPLACE ${CMAKE_SOURCE_DIR} "" target_name ${CMAKE_CURRENT_SOURCE_DIR})
1252+
string(REPLACE / _ target_name "copy_header_${target_name}")
1253+
string(REGEX REPLACE "_$" "" target_name ${target_name})
1254+
1255+
# Register the files to be copied for each target directory (e.g. include/ include/ROOT include/v7/inc/ ...)
1256+
list(REMOVE_DUPLICATES include_files)
1257+
list(TRANSFORM include_files REPLACE "(.*)/[^/]*" "\\1/" OUTPUT_VARIABLE subdirs)
1258+
list(REMOVE_DUPLICATES subdirs)
1259+
foreach(subdir ${subdirs})
1260+
set(input_files ${include_files})
1261+
list(FILTER input_files INCLUDE REGEX "^${subdir}[^/]*$")
1262+
set(output_files ${input_files})
1263+
1264+
string(REGEX REPLACE ".*/*inc/" "" destination ${subdir})
1265+
1266+
list(TRANSFORM input_files PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
1267+
list(TRANSFORM output_files REPLACE ".*/" "${CMAKE_BINARY_DIR}/include/${destination}")
1268+
1269+
set(destination destination_${destination})
1270+
1271+
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_COPY_LISTS ${destination})
1272+
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_INPUT_${destination} ${input_files})
1273+
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_OUTPUT_${destination} ${output_files})
12551274
endforeach()
1256-
if (dst_list)
1257-
string(REPLACE ${CMAKE_SOURCE_DIR} "" tgt ${CMAKE_CURRENT_SOURCE_DIR})
1258-
string(MAKE_C_IDENTIFIER move_header${tgt} tgt)
1259-
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_TARGETS ${tgt})
1260-
add_custom_target(${tgt} DEPENDS ${dst_list})
1261-
endif()
12621275
endfunction()
12631276

1277+
#---------------------------------------------------------------------------------------------------
1278+
#--- ROOT_CREATE_HEADER_COPY_TARGETS
1279+
# Creates a target to copy all headers that have been registered for copy in ROOT_INSTALL_HEADERS
1280+
#---------------------------------------------------------------------------------------------------
1281+
macro(ROOT_CREATE_HEADER_COPY_TARGETS)
1282+
get_property(HEADER_COPY_LISTS GLOBAL PROPERTY ROOT_HEADER_COPY_LISTS)
1283+
list(REMOVE_DUPLICATES HEADER_COPY_LISTS)
1284+
foreach(copy_list ${HEADER_COPY_LISTS})
1285+
get_property(inputs GLOBAL PROPERTY ROOT_HEADER_INPUT_${copy_list})
1286+
get_property(outputs GLOBAL PROPERTY ROOT_HEADER_OUTPUT_${copy_list})
1287+
1288+
string(REPLACE "destination_" "${CMAKE_BINARY_DIR}/include/" destination ${copy_list})
1289+
1290+
list(LENGTH inputs LIST_LENGTH)
1291+
# Windows doesn't support long command lines, so split them in packs:
1292+
foreach(range_start RANGE 0 ${LIST_LENGTH} 100)
1293+
list(SUBLIST outputs ${range_start} 100 sub_outputs)
1294+
list(SUBLIST inputs ${range_start} 100 sub_inputs)
1295+
list(LENGTH sub_outputs SUB_LENGTH)
1296+
if(NOT SUB_LENGTH EQUAL 0)
1297+
add_custom_command(OUTPUT ${sub_outputs}
1298+
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${sub_inputs} ${destination}
1299+
COMMENT "Copy headers for ${destination} ${range_start}"
1300+
DEPENDS ${sub_inputs})
1301+
endif()
1302+
endforeach()
1303+
file(MAKE_DIRECTORY ${destination})
1304+
set_property(GLOBAL APPEND PROPERTY ROOT_HEADER_TARGETS ${outputs})
1305+
endforeach()
1306+
endmacro()
1307+
12641308
#---------------------------------------------------------------------------------------------------
12651309
#---ROOT_STANDARD_LIBRARY_PACKAGE(libname
12661310
# [NO_INSTALL_HEADERS] : don't install headers for this package

0 commit comments

Comments
 (0)