仅用于*子目录的缓存?

我遇到了一个类似于这个没有答案的问题的一代cmake生成文件缓慢的问题:

CMake生成makefiles的速度很慢

我的项目由顶级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项目来实现这一目标? 我发现有些人在每个子项目中都使用了project()作为每个CMakeLists.txt。 一般来说,这是一个好主意?

另外/还有一些方法可以加快cmake的生成步骤吗? (目前我有60多个+)

如果你想讨论为什么cmake本身应该或不应该能够并行运行(想象一下cmake -j)


我已经添加了meson-build标签,因为仅仅是一个微薄的奖励还没有吸引足够的注意力来保证答案。 它的这种问题可能会导致人们切换到构建介子系统(假设它没有类似的问题)或类似的东西。

如果没有将源代码修改为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的同义词--build在文档中都没有正确描述选项(@todo报告错误)-H是源目录的根目录(不同于docs会让你相信的--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 donen", 20-- Configuring done
15:45:01 write(1, "-- Generating donen", 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

大部分时间似乎花费在(或之间)打开,访问和取消链接电话。 每个任务的长度是相当可变的,但它们的数量庞大。 我不知道Labels.json和Labels.txt文件是关于什么(cmake内部的东西)

1次运行:

    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 = nn", 21) = 21
     0.536947 write(3, "CMAKE_PROGRESS_1 = nn", 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: 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代码中的时间本身是非常低的。 (参见例如,在时间(1)的输出中'真正','用户'和'sys'是什么意思?)以下是我为完整性所做的尝试:

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

实际上使用更优化的cmake确实可以使配置部分更快,但在我的情况下, 生成部分很慢。 从这个步骤以某种方式I / O限制的时间开始。


我决定调查Florian的想法,即使用文件流的内存空间来存放临时文件可能会有所帮助。 我决定尝试一下简单的路线,并且攻击cmake来将.tmp文件写入一个ramdisk。 然后我去了整个猪,并尝试在虚拟盘上生成构建系统

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的一些输出(用-fno-omit-frame-pointer构建的cmake):

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

将我的意见转化为答案

回答这个问题并不容易,因为有很多方面可以定义CMake的配置和生成步骤持续时间(除了您在CMakeLists.txt文件中实际执行的操作,例如您的主机系统,工具链以及您的CMake版本/分发使用)。

所以我尽量专注于你的具体问题。

重建/重写makefiles只是一个子目录?

开始之前:使用add_subdirectory()有助于构建CMake代码。 但是您必须记住,您始终可以在子目录中更改全局CMake属性,并且这些子目录中的目标可能具有交叉依赖关系。

那么CMake做了什么(考虑到“我在这里讨论的一个子目录中触及了一个CMakeLists.txt文件”):

  • 如果CMakeLists.txt文件被更改,它将再次遍历CMakeLists.txt文件的完整历史并在内存中重新构建构建环境。
  • 现在它暂时重新创建所有必要的构建/构建文件,并检查它们是否从现有构建文件延迟(请参阅cmGeneratedFileStreamBase::Close()
  • 如果文件已经改变,则用新文件替换现有文件
  • 此行为是必需的,因为即使只有子目录CMakeLists.txt文件发生更改,任何生成文件都可以更改,并且已对其进行了优化,以防止在实际生成步骤(来自所触及的makefiles)期间make不必要的重新生成。

    有什么方法可以加快cmake的生成步骤吗?

    所以是的,它会暂时重写所有makefile(可能会很慢),并且不会,但是在将add_subdirectory()仅用于更改的子目录时,不能将此最小化。

    也许在CMake自己的代码中为将来做出的一个可能的性能优化是使用内存流而不是文件流来处理临时文件。

    编辑: @BruceAdams通过使用RAM磁盘为生成的生成文件环境进行测试,但没有任何效果。

    是的,CMake生成的cmake_check_build_system规则几乎与rebuild_cache规则相同,并且是使用的-B-H--check-build-system选项是CMake内部命令行选项,因此没有记录(即使经常提到StackOverflow,例如我在这里的答案之一)。

    帮助我加速配置/生成的是重建CMake本身,比正常发行版有更多的优化选项,并使用64位工具链而不是目前仍然分布的32位版本。

    编辑 :下面是我的Windows PC上的一些测试结果(使用下面有100个子目录/库的CMake测试脚本)总是使用相同的MSYS环境,但是使用相同CMake源代码的不同CMake编译:

  • 官方CMake 3.2.2版本:

    $ time -p cmake -G "MSYS Makefiles" ..
    [...]
    real 43.93
    user 0.00
    sys 0.03
    
  • 使用mingw32GNU 4.8.1我重建CMake 3.2.2

    cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-O3" -G "MSYS Makefiles" ..
    

    得到了

    $ time -p /c/temp/cmake-3.2.2/MSYS32/bin/cmake.exe -G "MSYS Makefiles" ..
    [...]
    real 41.37
    user 0.01
    sys 0.04
    

    和我的防病毒软件关闭一样

    $ time -p /c/temp/cmake-3.2.2/MSYS32/bin/cmake.exe -G "MSYS Makefiles" ..
    [...]
    real 20.98
    user 0.00
    sys 0.04
    
  • 使用mingw-w64GNU 5.3.0我重建CMake 3.2.2

    $ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-march=native -m64 -Ofast  -flto" -G "MSYS Makefiles" ..
    

    得到了

    $ time -p /c/temp/cmake-3.2.2/MSYS64/bin/cmake.exe -G "MSYS Makefiles" ..
    [...]
    real 25.59
    user 0.00
    sys 0.04
    

    和我的防病毒软件关闭一样

    $ time -p /c/temp/cmake-3.2.2/MSYS64/bin/cmake.exe -G "MSYS Makefiles" ..
    [...]
    real 6.95
    user 0.00
    sys 0.03
    
  • 总而言之,我看到两个主要影响:

    第一 :配置步骤可以通过使用64位版本来加速,并针对处理器平台进行优化(对于您的所有项目的构建,您肯定必须找到一个通用base -march=...-mtune=...个人电脑)。

    第二 :通过在CMake之外搜索可能的文件I / O瓶颈,主要可以加速生成步骤。 在我的情况下,告诉防病毒软件不要检查工具链,并建立目录,每次我读/写这些都是真正加速的事情。

    备注 :我证实@BruceAdams测试结果表明,编译器自动向量化(默认为-O3-Ofast )对CMake源代码在多个进程/多核上运行的能力无能为力。

    有没有更好的方法来构建cmake项目来实现这一目标?

    是的,如果你知道你的CMake脚本代码的某个子树只是生成了一个库并且没有依赖关系,那么你可以使用ExternalProject_Add()将该部分放到一个外部项目中。 是的,对于大型CMake项目有类似的担忧,这被视为一种很好的“现代cmake”实践(另请参见下面的参考资料)。

    参考

  • CMake性能提示
  • CMake:并行生成make文件
  • 海湾合作委员会:三月与三月有什么不同?
  • CMake:如何设置Source,Library和CMakeLists.txt依赖关系?
  • 通过其他cmake软件包自动访问cmake库
  • 在CMake项目中使用启用CMake的库
  • 我用什么来重现你的问题?

    为了完整起见,如果有人想在这里检查这些数字,我的测试代码是:

    cmake_minimum_required(VERSION 3.0)
    
    project(CMakeTest CXX)
    
    #set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_DEBUG_MODE 1)
    
    set(_idx 1)
    
    while (_idx LESS 100)
        math(EXPR _next_idx "${_idx} + 1")
        if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/lib${_idx}")
            file(MAKE_DIRECTORY "lib${_idx}")
            file(
                WRITE "lib${_idx}/lib${_idx}.h" 
                    "int lib${_idx}_func();"
            )
            file(
                WRITE "lib${_idx}/lib${_idx}.cc" 
                    "#include "lib${_next_idx}.h"n"
                    "int lib${_idx}_func() { return lib${_next_idx}_func(); }"
            )
            file(
                WRITE "lib${_idx}/CMakeLists.txt" 
                    "add_library(lib${_idx} "lib${_idx}.cc")n"
                    "target_link_libraries(lib${_idx} lib${_next_idx})n"
                    "target_include_directories(lib${_idx} PUBLIC ".")"
            )
        endif()
        add_subdirectory("lib${_idx}")
        set(_idx "${_next_idx}")
    endwhile()
    
    if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/lib${_idx}")
        file(MAKE_DIRECTORY "lib${_idx}")
        file(
            WRITE "lib${_idx}/lib${_idx}.h"
                "int lib${_idx}_func();"
        )
        file(
            WRITE "lib${_idx}/lib${_idx}.cc" 
                "int lib${_idx}_func() { return 0; }"
        )
        file(
            WRITE "lib${_idx}/CMakeLists.txt" 
                "add_library(lib${_idx} "lib${_idx}.cc")n"
                "target_include_directories(lib${_idx} PUBLIC ".")"
        )
    endif()
    add_subdirectory("lib${_idx}")
    
    if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/main.cc")
        file(
            WRITE "main.cc" 
                "#include "lib1.h"n"
                "int main() { return lib1_func(); }"
        )
    endif()
    
    add_executable(${PROJECT_NAME} "main.cc")
    target_link_libraries(${PROJECT_NAME} lib1)
    

    然后-第一后cmake ..make电话-这样做:

    $ touch ../lib100/CMakeLists.txt
    $ time -p cmake ..
    -- Configuring done
    -- Generating done
    -- Build files have been written to: [your path here]
    real 28.89
    user 0.01
    sys 0.04
    
    链接地址: http://www.djcxy.com/p/32181.html

    上一篇: cache for *just* a subdirectory?

    下一篇: Serial.println() affects Serial1 readings