cmake rebuild_cache для * просто * подкаталога?

У меня есть проблема с медленной стадией генерации make-файлов CMake, которая похожа на этот вопрос без ответа:

CMake медленно генерирует make-файлы

Мой проект состоит из верхнего уровняCMakeLists.txt файл, который используетadd_subdirectory() добавлять различные подпроекты для отдельных библиотек и исполняемых компонентов.

Для данного компонентаCMakeLists.txt Файл содержит что-то вроде:

add_library(mylib SHARED
  sourceFile1.cpp
  sourceFile2.cpp
  ...
)

Я могу собрать только содержимое этого каталога, используя:

make mylib

Если я изменюCMakeLists.txt файл в подкаталоге (который я много делал как часть перехода с чистых Makefiles на CMake) затем запуститеmake он корректно перезапускает CMake для обновления конфигурации, как если бы я запускалmake rebuild_cache.

Тем не менее, я заметил, что на самом деле это перенастраиваетвсе проект. Я действительно хочу, чтобы CMake был достаточно умен, чтобы знать, что ему нужно только восстановить Makefile в текущем каталоге и подкаталогах.

Есть ли лучший способ структурировать проект CMake для достижения этой цели? Я вижу, что некоторые люди используютпроект () для каждого CMakeLists.txt в каждом подпроекте. Вообще это хорошая идея?

В качестве альтернативы / дополнительно есть ли какой-нибудь способ ускорить этап генерации CMake? (сейчас у меня 60 с +)

Бонусные баллы, если вы хотите обсудить, почему CMake сам должен или не должен работать параллельно (представьтеcmake -j).

Я добавил тэг мезонов в качестве скромной награды, но сам по себе он еще не привлек достаточного внимания, чтобы оправдать ответ. Это такая проблема, которая может заставить людей перейти на сборку систем на мезон-сборку (при условии, что у нее нет похожих проблем) или что-то подобное.

Возможно, правильный ответ - это невозможно сделать без изменения исходного кода на CMake. Чтобы получить награду, мне нужно объяснить, как работает CMake и / или где он имеет недостатки.

Разъяснение: Этопоколение шаг, который медленный в моем случае. Сама конфигурация достаточно быстрая, но CMake довольно долго зависает между выводом"- Настройка выполнена" а также"- Генерация завершена".

Для полной перестройки кэша я запускаю:

make -n rebuild_cache
Running CMake to regenerate build system... 
using Makefile generator
-- FOOBAR_VERSION: 01.02.03
-- Configuring done
-- Generating done
-- Build files have been written to: /home/brucea/work/depot/emma/main/cmake
real 74.87
user 1.74
sys 1.02

Под капотом это работает:

cmake -H<source dir> -B<build dir>

я предполагаю-B это синоним--build, Ни одна из опций не описана правильно в документации.-H является корнем исходного каталога (не совпадает с--help как документация, вы бы поверить).

Это быстро, чтобы добраться до выхода«Настройка выполнена», но медленно оттуда:

Например,

15:44:14 execve("/usr/local/bin/cmake",
>grep Generating cmake_strace.log
>grep "Configuring" cmake_strace.log
15:44:15 write(1, "-- Configuring done\n", 20-- Configuring done
15:45:01 write(1, "-- Generating done\n", 19-- Generating done
>grep "Build files" cmake_strace.log
15:45:22 write(1, "-- Build files have been written"..., 77-- Build files have been written to:

Если редактировать один файл CMakeLists.txt в подкаталоге, а затем запуститьmake -nработает:

cd /home/project/cmake && /usr/local/bin/cmake -H/home/project/cmake -B/home/project/cmake --check-build-system CMakeFiles/Makefile.cmake 0

--check-build-system - еще одна недокументированная опция.

Эффект тот же - восстановить всю систему сборки, а не только текущее поддерево. Нет различий в поведении между сборкой из источника и вне источника.

Если я запускаю трассировку, например:

strace -r cmake --trace -H/home/project/cmake -B/home/project/cmake 2>&1 | tee cmake_rebuild_cache.log
sort -r cmake_rebuild_cache.log | uniq

Большая часть времени, по-видимому, тратится на (или между) вызовами open, access и unlink.

Длина каждой задачи довольно переменна, но их огромное количество накапливается. Я понятия не имею, что такое файлы Labels.json и Labels.txt (что-то внутреннее для CMake).

Один забег:

    49.363537 open("/home/projectbar/main/test/foo2bar/CMakeFiles/test2.foo2bar.testViewingSource1.dir/build.make", O_RDONLY) = 5
     1.324777 access("/home/projectbar/main/test/performance/CMakeFiles/performancetest.chvcthulhu.testChvcthulhuPerformance2.dir", R_OK) = 0
     0.907807 access("/home/projectbar/main/test/foo2bar/CMakeFiles/test2.foo2bar.testPeripheralConnection2.dir", R_OK) = 0
     0.670272 unlink("/home/projectbar/main/src/foo2bar/Foo2Bar/CMakeFiles/foo2bar_lib.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.600272 access("/home/projectbar/main/test/foo2bar/testFilesModel2.ok", R_OK) = 0
     0.599010 access("/home/projectbar/main/test/hve2snafu/testInvalidByte2c.ok", R_OK) = 0
     0.582466 read(5, "openjdk version \"1.8.0_71\"\nOpenJ"..., 1024) = 130
     0.570540 writev(3, [{"# CMAKE generated file: DO NOT E"..., 8190}, {"M", 1}], 2) = 8191
     0.553576 close(4)                  = 0
     0.448811 unlink("/home/projectbar/main/test/snafu2hve/CMakeFiles/test2.snafu2hve.testNoProbes2.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.431559 access("/home/projectbar/main/src/foo2bar/Foo2Bar/CMakeFiles/foo2bar_lib.dir", R_OK) = 0
     0.408003 unlink("/home/projectbar/main/test/lachesis/CMakeFiles/test2.lachesis.testBadSequenceNumber1.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.407120 write(4, "# The set of languages for which"..., 566) = 566
     0.406674 write(3, "# CMAKE generated file: DO NOT E"..., 675) = 675
     0.383892 read(3, "ewingPeriod.cpp.o -c /home/bruce"..., 8191) = 8191
     0.358490 unlink("/home/projectbar/main/cmake/CMakeFiles/mklinks.chvdiff.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)

Еще один прогон той же команды:

     2.009451 unlink("/home/projectbar/main/cmake/CMakeFiles/mklinks.lachesis.dir/Labels.json") = -1 ENOENT (No such file or directory)
) = 20
) = 19
     1.300387 access("/home/projectbar/main/test/chvedit/CMakeFiles/test2.chvedit.tefooultiMatchFactoringEdit2.dir", R_OK) = 0
     1.067957 access("/home/projectbar/main/test/chvedit/CMakeFiles/test2.chvedit.tefooultiMatchFactoringEdit2.dir", R_OK) = 0
)         = 1
     0.885854 unlink("/home/projectbar/main/src/gorkyorks2bar/CMakeFiles/doxygen.correct.gorkyorks2bar.dir/Labels.json") = -1 ENOENT (No such file or directory)
     0.854539 access("/home/projectbar/main/test/reportImpressions/ReportImpressions/CMakeFiles/testsuite1_reportImpressions.dir", R_OK) = 0
     0.791741 unlink("/home/projectbar/main/cmake/CMakeFiles/mklinks.bar_models.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.659506 unlink("/home/projectbar/main/cmake/CMakeFiles/mklinks.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.647838 unlink("/home/projectbar/main/test/libyar/YarModels/CMakeFiles/testsuite1_yarmodels.dir/Labels.txt") = -1 ENOENT (No such file or directory)
     0.620511 unlink("/home/projectbar/main/test/libyar/YarModels/CMakeFiles/testsuite1_yarmodels.dir/Labels.json") = -1 ENOENT (No such file or directory)
     0.601942 unlink("/home/projectbar/main/cmake/CMakeFiles/mklinks.lachesis.dir/Labels.txt") = -1 ENOENT (No such file or directory)
     0.591871 access("/home/projectbar/main/src/runbardemo/simple_demo/CMakeFiles", R_OK) = 0
     0.582448 write(3, "CMAKE_PROGRESS_1 = \n\n", 21) = 21
     0.536947 write(3, "CMAKE_PROGRESS_1 = \n\n", 21) = 21
     0.499758 unlink("/home/projectbar/main/test/foo2bar/CMakeFiles/test2.foo2bar.testInputDirectory1.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.458120 unlink("/home/projectbar/main/test/yak2dcs/CMakeFiles/test2.yak2dcs.testsuite2.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.448104 unlink("/home/projectbar/main/test/reportImpressions/CMakeFiles/test2.reportImpressions.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.444344 access("/home/projectbar/main/src/bananas/CMakeFiles/bin.bananas.dir", R_OK) = 0
     0.442685 unlink("/home/projectbar/main/test/rvedit/CMakeFiles/test2.rvedit.tefooissingOptionValue.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.425604 unlink("/home/projectbar/main/test/listdcs/CMakeFiles/test2.listdcs.testListCalls5.dir/progress.make.tmp") = -1 ENOENT (No such file or directory)
     0.391163 access("/home/projectbar/main/src/siedit/CMakeFiles/siedit.dir", R_OK) = 0
     0.362171 access("/home/projectbar/main/test/foo2bar/CMakeFiles/test2.foo2emma.testHowResults6.dir", R_OK) = 0

Обратите внимание, что генератор ниндзя намного быстрее (хотя все еще не блестящий). Например,

/usr/bin/time -p ninja rebuild_cache
ninja: warning: multiple rules generate ../src/ams2yar/ams2yar. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/vox/vox. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/bananas/bananas. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/fidlertypes2fidlerinfo/fidlertypes2fidlerinfo. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/mkrundir/mkrundir. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/runyar/runyar. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
ninja: warning: multiple rules generate ../src/runyardemo/runyardemo. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]
[1/1] Running CMake to regenerate build system...
Generator=Ninja
-- FOO_VERSION: 01.02.03
-- Configuring done
-- Generating done
-- Build files have been written to: /home/project/cmake/build
real 12.67
user 1.01
sys 0.31

Обратите внимание, что проект еще не совсем готов для Ninja, так как есть ошибки, такие как:

ninja: warning: multiple rules generate ../src/runfoobardemo/runfoobardemo. builds involving this target will not be correct; continuing anyway [-w dupbuild=warn]

а также

ninja: error: dependency cycle: ../src/foobar -> ../src/foobar/CMakeFiles/foobar -> ../src/ams2emma/foobar

быть решенным. Этот вопрос действительно о том, почемуMakefile генератор работает медленно Я не уверен, являются ли проблемы, которые показывает ниндзя, полезными подсказками здесь или красными сельдями.

Сборка CMake с большим количеством оптимизаций не помогает.

Исходя из моего вывода трассировки и выхода времени, маловероятно, что это произойдет. Время пользователя и, следовательно, время, потраченное внутри самого кода CMake, довольно мало. (см. напримерЧто означают «реальный», «пользователь» и «sys» в выводе времени (1)?).

Вот что я попробовал для полноты:

export CXX_FLAGS="-O3 -ftree-vectorise -msse2"
cmake -DCMAKE_BUILD_TYPE=RELEASE

На самом деле, используя более оптимизированный CMakeделает сделать настройку быстрее, но в моем случае этогенерировать часть, которая медленная. Из времени следует, что этот шаг как-то связан с вводом / выводом.

Я решил исследовать идею Флориана о том, что использование памяти в потоке файлов для временных файлов может иметь значение.

Я решил попробовать простой маршрут и взломал CMake, чтобы вместо этого записать файлы .tmp на RAM-диск.

Затем я пошел на попятную и попытался сгенерировать систему сборки на RAM-диске:

sudo mkdir /mnt/ramdisk
sudo mount -t tmpfs -o size=512m tmpfs /mnt/ramdisk
/usr/bin/time -p cmake -H/<source> -B/mnt/ramdisk/build

Я был очень удивлен, обнаружив, что это не имеет никакого значения для времени настенных часов:

real 59.61
user 1.55
sys 0.62
>du -sh /mnt/ramdisk/build/
4.4M    /mnt/ramdisk/build/

Аналогично с ramfs:

real 51.09
user 1.58
sys 0.50

Что здесь может происходить? Я угадывал подпроцессы, но я не могу понять, какие подпроцессы потребляют время настенных часов, если они есть. Они выглядят очень недолго.

Для полноты вот некоторый вывод из perf (CMake построен с-fno-omit-frame-pointer):

perf record -g --call-graph dwarf cmake -H<source> -B<build>
perf report -g graph
Samples: 17K of event 'cycles', Event count (approx.): 14363392067
  Children      Self  Command          Shared Object                 Symbol
+   65.23%     0.00%  cmake            cmake                         [.] do_cmake
+   65.02%     0.00%  cmake            cmake                         [.] cmake::Run
+   60.32%     0.00%  cmake            cmake                         [.] main
+   59.82%     0.00%  cmake            libc-2.17.so                  [.] __libc_start_main
+   57.78%     0.00%  cmake            cmake                         [.] _start
+   55.04%     0.00%  cmake            cmake                         [.] cmGlobalUnixMakefileGenerator3::Generate
+   54.56%     0.00%  cmake            cmake                         [.] cmake::Generate
+   49.90%     0.00%  cmake            cmake                         [.] cmGlobalGenerator::Generate
+   38.87%     0.02%  cmake            cmake                         [.] cmLocalUnixMakefileGenerator3::Generate
+   18.65%     0.01%  cmake            cmake                         [.] cmMakefileTargetGenerator::WriteTargetBuildRules
+   17.05%     0.02%  cmake            cmake                         [.] cmMakefile::ExecuteCommand
+   16.99%     0.01%  cmake            cmake                         [.] cmMakefile::ReadListFile
+   16.84%     0.01%  cmake            cmake                         [.] cmCommand::InvokeInitialPass
+   16.79%     0.00%  cmake            cmake                         [.] cmMakefile::Configure
+   14.71%     0.00%  cmake            cmake                         [.] cmMakefile::ConfigureSubDirectory
+   14.67%     0.05%  cmake            cmake                         [.] cmMacroHelperCommand::InvokeInitialPass
+   14.27%     0.02%  cmake            cmake                         [.] cmMakefileUtilityTargetGenerator::WriteRuleFiles
+   13.91%     0.00%  cmake            cmake                         [.] cmGlobalGenerator::Configure
+   13.50%     0.05%  cmake            cmake                         [.] cmOutputConverter::Convert
+   13.48%     0.00%  cmake            cmake                         [.] cmAddSubDirectoryCommand::InitialPass
+   13.46%     0.00%  cmake            cmake                         [.] cmMakefile::AddSubDirectory
+   12.91%     0.00%  cmake            cmake                         [.] cmGlobalUnixMakefileGenerator3::Configure
+   12.82%     0.00%  cmake            cmake                         [.] cmake::ActualConfigure
+   10.90%     0.00%  cmake            cmake                         [.] cmake::Configure
+   10.55%     0.02%  cmake            cmake                         [.] cmMakefileTargetGenerator::WriteObjectRuleFiles
+   10.35%     0.09%  cmake            cmake                         [.] cmLocalUnixMakefileGenerator3::WriteMakeRule
+    9.76%     0.03%  cmake            cmake                         [.] cmMakefileTargetGenerator::WriteObjectBuildFile
+    7.97%     0.00%  cmake            cmake                         [.] cmMakefileLibraryTargetGenerator::WriteRuleFiles
+    7.93%     0.00%  cmake            cmake                         [.] cmMakefileExecutableTargetGenerator::WriteRuleFiles
+    7.88%     0.00%  cmake            cmake                         [.] cmLocalUnixMakefileGenerator3::WriteLocalMakefile
+    7.68%     0.02%  cmake            [kernel.kallsyms]             [k] sysret_audit
+    7.60%     0.05%  cmake            [kernel.kallsyms]             [k] __audit_syscall_exit
+    7.40%     0.08%  cmake            cmake                         [.] cmsys::SystemTools::CollapseFullPath

А такжеотчет о перфекте -g граф:

+    2.86%  cmake            libc-2.17.so                  [.] _int_malloc
+    2.15%  cmake            libc-2.17.so                  [.] __memcpy_ssse3_back
+    2.11%  cmake            [kernel.kallsyms]             [k] find_next_bit
+    1.84%  cmake            libc-2.17.so                  [.] __memcmp_sse4_1
+    1.83%  cmake            libc-2.17.so                  [.] _int_free
+    1.71%  cmake            libstdc++.so.6.0.20           [.] std::__ostream_insert >
+    1.18%  cmake            libstdc++.so.6.0.20           [.] std::basic_string, std::allocator >::~basic_string
+    1.13%  cmake            libc-2.17.so                  [.] malloc
+    1.12%  cmake            cmake                         [.] cmOutputConverter::Shell__ArgumentNeedsQuotes
+    1.11%  cmake            libstdc++.so.6.0.20           [.] std::string::compare
+    1.08%  cmake            libc-2.17.so                  [.] __strlen_sse2_pminub
+    1.05%  cmake            cmake                         [.] std::string::_S_construct
+    1.04%  cmake            cmake                         [.] cmsys::SystemTools::ConvertToUnixSlashes
+    0.97%  cmake            cmake                         [.] yy_get_previous_state
+    0.87%  cmake            cmake                         [.] cmOutputConverter::Shell__GetArgument
+    0.76%  cmake            libstdc++.so.6.0.20           [.] std::basic_filebuf >::xsputn
+    0.75%  cmake            libstdc++.so.6.0.20           [.] std::string::size
+    0.75%  cmake            cmake                         [.] cmOutputConverter::Shell__SkipMakeVariables
+    0.74%  cmake            cmake                         [.] cmOutputConverter::Shell__CharNeedsQuotesOnUnix
+    0.73%  cmake            [kernel.kallsyms]             [k] mls_sid_to_context
+    0.72%  cmake            libstdc++.so.6.0.20           [.] std::basic_string, std::allocator >::basic_string
+    0.71%  cmake            cmake                         [.] cmOutputConverter::Shell__GetArgumentSize
+    0.65%  cmake            libc-2.17.so                  [.] malloc_consolidate
+    0.65%  cmake            [kernel.kallsyms]             [k] mls_compute_context_len
+    0.65%  cmake            cmake                         [.] cmOutputConverter::Shell__CharNeedsQuotes
+    0.64%  cmake            cmake                         [.] cmSourceFileLocation::Matches
+    0.58%  cmake            cmake                         [.] cmMakefile::ExpandVariablesInStringNew
+    0.57%  cmake            cmake                         [.] std::__deque_buf_size
+    0.56%  cmake            cmake                         [.] cmCommandArgument_yylex
+    0.55%  cmake            cmake                         [.] std::vector >::size
+    0.54%  cmake            cmake                         [.] cmsys::SystemTools::SplitPath
+    0.51%  cmake            libstdc++.so.6.0.20           [.] std::basic_streambuf >::xsputn

Ответы на вопрос(1)

Ваш ответ на вопрос