天道酬勤,学无止境

'cmake rebuild_cache'仅用于子目录?('cmake rebuild_cache' for *just* a subdirectory?)

问题

我有一个问题,即CMake的makefile生成阶段很慢,这类似于以下未解决的问题:

CMake生成文件的速度很慢

我的项目由顶层CMakeLists.txt文件组成,该文件使用add_subdirectory()为单个库和可执行组件添加各种子项目。

对于给定的组件, CMakeLists.txt文件包含以下内容:

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

我可以使用以下命令构建该目录的内容:

make mylib

如果我修改CMakeLists.txt在子目录中的文件(我已经做了很多从纯粹的Makefile向CMake迁移的一部分),然后运行make它正确地重新运行CMake的更新配置,如果我” d运行make rebuild_cache

但是,我注意到它实际上重新配置了整个项目。 我真的希望CMake足够聪明,以便知道它只需要在当前目录和子目录中重新生成Makefile。

有没有更好的方法来构建CMake项目来实现这一目标? 我看到有人在每个子项目中为每个CMakeLists.txt使用project() 。 总的来说,这是个好主意吗?

另外/是否有某种方法可以加快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 )。

到达“ Configuring done”的输出很快,但是从那里开始很慢:

例如,

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

花费的大部分时间似乎都花在了打开,访问和取消链接呼叫上(或之间)。

每个任务的时间长短不一,但是数量却很多。 我不知道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

请注意,Ninja生成器要快得多(尽管仍然不够出色)。 例如,

/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代码本身中花费的时间非常少。 (请参见例如time(1)输出中的“ real”,“ user”和“ sys”是什么意思? )。

这是我为完整性所做的尝试:

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

实际上,使用更优化的CMake确实会使配置部分更快,但是在我的情况下,生成部分却很慢。 从时间上看来,此步骤某种程度上受I / O约束。


我决定研究Florian的想法,即使用文件流的内存流作为临时文件可能会有所作为。

我决定尝试简单的方法,并入侵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的一些输出(使用-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

perf报告-g图-no-children

+    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

定义CMake的配置和生成步骤的持续时间有很多方面(除了您在CMakeLists.txt文件中实际执行的操作;例如,您的主机系统,工具链以及所使用的CMake版本/发行版)。

因此,我尝试着重于您的特定问题。

只是为子目录重建/重写makefile?

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

因此,CMake会做什么(考虑“我已经触摸了子目录中的一个CMakeLists.txt文件”在这里讨论的情况):

  • 如果更改了CMakeLists.txt文件,它将再次遍历CMakeLists.txt文件的完整层次结构,并再次在内存中重建构建环境。
  • 现在,它会临时重新创建所有必要的构建/生成文件,并检查它们是否与现有文件有所不同(请参见cmGeneratedFileStreamBase :: Close())。
  • 如果文件已更改,它将用新文件替换现有文件。

此行为是必需的,因为即使仅更改了子目录的CMakeLists.txt文件,并且任何makefile都可以更改,并且该文件已进行了优化,以防止在实际的make步骤中(通过接触的makefile) make不必要的重建。

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

因此,是的,它确实会临时重写所有makefile文件(这可能会很慢),并且不,您不能在将add_subdirectory()仅用于更改的子目录时最小化此文件。

也许将来在CMake自己的代码中进行性能优化的一种可能是使用内存流代替临时文件的文件流。

@BruceAdams通过使用RAM磁盘对生成的Makefile环境进行了测试,没有任何效果。

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

帮助我加快配置/生成速度的原因在于,它使用比正常发行版更多的优化选项来重建CMake自身,并使用64位工具链而不是当前仍在发行的32位版本。

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

  1. CMake 3.2.2官方版本:

     $ time -p cmake -G "MSYS Makefiles" .. [...] real 43.93 user 0.00 sys 0.03
  2. 使用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
  3. 使用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位版本并针对您的处理器平台进行优化来加快配置步骤(当然,您必须为所有的主机找到通用的-march = ...或-mtune = ...项目的构建PC)。

第二:生成步骤通常可以通过搜索CMake之外的文件I / O瓶颈来加快。 就我而言,告诉防病毒软件每次我对它们进行读/写操作时都不要检查工具链并建立目录,这确实在加快速度。

备注:我确认@BruceAdams的测试结果表明,编译器的自动矢量化(默认为-O3-Ofast )不能对CMake源代码在多个进程/多个内核上运行的能力做很多事情。

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

是的,例如,如果您知道CMake脚本代码的某个子树仅生成一个库且没有依赖项,则可以使用ExternalProject_Add()将其放入外部项目中。 是的,对于大型CMake项目也有类似的担忧,这被视为良好的“现代CMake”实践(另请参见下面的参考资料)。

参考

  • CMake性能提示
  • CMake:并行生成make文件
  • GCC:三月与mtune有何不同?
  • CMake:如何设置源,库和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

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 'cmake rebuild_cache' for *just* a subdirectory?
    I have an issue with the generation of makefiles stage of CMake being slow which is similar to this unanswered question: CMake is slow to generate makefiles My project is made up of a top level CMakeLists.txt file which uses add_subdirectory() to add various subprojects for individual library and executable components. For a given component, the CMakeLists.txt file contains something like: add_library(mylib SHARED sourceFile1.cpp sourceFile2.cpp ... ) I can build just the contents of that directory using: make mylib If I modify the CMakeLists.txt file in the sub-directory (which I've been
  • CMake / Ninja尝试编译已删除的`.cpp`文件(CMake/Ninja attempting to compile deleted `.cpp` file)
    问题 我发现,当我使用cmake和ninja从项目中删除cpp文件时,如果不首先完全删除构建目录并从头开始,就无法轻松地对其进行编译。 CMake和/或Ninja显然会cpp对其编译的所有cpp文件的大量引用,甚至在重新运行CMake不会删除所有引用之前删除CMake缓存。 这是一个已知的问题? 有解决方案吗? 我偶尔只是运行rm $(grep -R <filename> <builddir>) ,但这是一个可怕的麻烦。 编辑:看来我弄错了,因为我无法重现此问题。 手动重新运行CMake似乎总是生成正确的.cpp文件列表,即使使用GLOB生成源列表也是如此。 回答1 把我的评论变成答案 使用file(GLOB ...)收集源文件 是的,当使用file(GLOB ...)命令收集源文件时,CMake将不知道新的或已删除的源文件。 这是CMake的已知限制。 正因为如此,我更改了CMake项目以单独列出所有源文件。 为了方便起见,我仍然使用file(GLOB ...)命令收集头文件。 引用CMake的file()命令文档: 我们不建议使用GLOB从源代码树中收集源文件列表。 如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的生成系统将不知道何时要求CMake重新生成。 删除CMakeCache.txt以重新触发配置 仅删除CMakeCache
  • 向CMake生成的构建系统本身添加依赖项(Add dependency to the CMake-generated build-system itself)
    问题 简而言之:我知道如何在CMake生成的构建系统中向目标添加依赖项。 但是,我想向生成的构建系统本身添加依赖项。 更长的问题:在CMake生成的cgal生成过程中,我们希望CMake在修改某些文件后自动重新运行配置步骤。 不需要的详细信息隐藏在下面: 事实上,我们使用CMake为CGAL库/示例/演示生成了生成系统,同时也为Doxygen生成的文档生成了生成系统。 Doxyfile是从多个文件生成的。 当CMake的生成是“ Makefile ”,存在于一个特殊的目标Makefile ,名为rebuild_cache ,但该目标(在Makefile级别)不是CMake的目标。 无论如何,我正在寻找一种跨平台的解决方案,即:可用于所有CMake生成器。 我的印象是我想要的东西还不能用CMake做到。 能否请您确认,以便我可以填写文档中的功能要求? 回答1 从CMake 3.0开始,您可以将这样的文件添加到目录属性CMAKE_CONFIGURE_DEPENDS。 该属性保存文件列表。 如果其中任何一个发生更改,CMake将触发重新配置。 这是一个小例子。 假设您的Doxyfile是从当前源目录中的Doxyfile.in.1和Doxyfile.in.2生成的,则可以按以下方式使用该属性: set_property( DIRECTORY APPEND PROPERTY CMAKE
  • 如何加快启用CMake的C ++项目的编译时间?(How to speed up Compile Time of my CMake enabled C++ Project?)
    问题 我最近遇到了几个有关改善CMake支持的C ++项目的周转时间的特定方面的问题(例如“我应该在什么级别分发构建过程?”或“仅对子目录使用cmake rebuild_cache?”),我当时是想知道是否有利用CMake提供的特定可能性的更一般的指导。 如果可能没有跨平台的编译时间优化,那么我主要对基于Visual Studio或GNU toochain的方法感兴趣。 而且我已经意识到并投资于一般推荐的领域,以加快C ++的构建: 更改/优化/微调工具链优化您的代码库/软件体系结构(例如,减少依赖关系并使用定义明确的子项目-单元测试) 购买更好的硬件(SSD,CPU,内存) 就像这里,这里或这里推荐的一样。 因此,我在这个问题上的重点是第一点。 另外,我知道可以在CMake Wiki中找到的建议: CMake:以您的所有核心进行构建 CMake性能提示 前者只处理基本知识(并行生成),而后者则主要处理如何加快CMake文件的解析速度。 为了使这一点更加具体,如果我从这里使用100个使用MSYS / GNU的库的CMake示例,我得到以下time测量结果: $ cmake --version cmake version 3.5.2 CMake suite maintained and supported by Kitware (kitware.com/cmake). $ time
  • How to speed up Compile Time of my CMake enabled C++ Project?
    I came across several SO questions regarding specific aspects of improving the turn-around time of CMake enabled C++ projects lately (like "At what level should I distribute my build process?" or "cmake rebuild_cache for just a subdirectory?"), I was wondering if there is a more general guidance utilizing the specific possibilities CMake offers. If there is probably no cross-platform compile time optimization, I'm mainly interested in Visual Studio or GNU toochain based approaches. And I'm already aware of and investing into the generally recommended areas to speed up C++ builds: Change
  • Add dependency to the CMake-generated build-system itself
    In short: I know how to add dependencies to targets, in a CMake-generated build system. But I would like to add dependencies to the generated build-system itself. Longer question: In the CMake-generated build process of cgal, we would like CMake to automatically re-run the configuration step, when certain files are modified. Unneeded details are hidden below: As a matter of fact, we generate using CMake the build system for the CGAL libraries/examples/demos, but also at the same time the build system for our Doxygen-generated documentation. The Doxyfile is generated from multiple files. When
  • 如何使用需要先安装的CMake项目中的库?(How to use libraries within my CMake project that need to be installed first?)
    问题 我的CMake构建系统有问题。 有CMakeLists.txt文件定义运行时或库,或使用ExternalProjects_Add()下载和构建外部代码。 由于依赖关系,这些项目必须相互查找。 现在,我想在顶层有一个CMakeLists.txt ,它可以一次构建所有这些。 为了找到一个项目,必须安装。 但是查找项目已经在CMake的配置时完成。 repository ├─project │ ├─game (Depends on engine, uses EngineConfig.cmake once installed) │ │ ├─CMakeLists.txt │ │ ├─include │ │ ├─src │ │ └─textures │ ├─engine (Depends on boost, uses built-in FindBoost.cmake) │ │ ├─CMakeLists.txt │ │ ├─include │ │ └─src │ ├─boost (Not the source code, just an ExternalProject_Add call) │ : └─CMakeLists.txt │ ├─build │ ├─game │ ├─engine │ ├─boost (Source will be downloaded and built here
  • C ++项目组织(带有gtest,cmake和doxygen)(C++ project organisation (with gtest, cmake and doxygen))
    问题 我是编程的新手,所以我决定从用C ++创建一个简单的矢量类开始。 但是,我想从一开始就养成良好的习惯,而不是稍后再尝试修改我的工作流程。 我目前只有两个文件vector3.hpp和vector3.cpp 。 随着我对一切的熟悉,这个项目将开始慢慢发展(使它更多地成为通用的线性代数库),因此我想采用“标准”项目布局,以使以后的生活更轻松。 因此,环顾四周后,我发现了两种组织hpp和cpp文件的方法,第一种是: project └── src ├── vector3.hpp └── vector3.cpp 第二个是: project ├── inc │ └── project │ └── vector3.hpp └── src └── vector3.cpp 您会推荐哪个?为什么? 其次,我想使用Google C ++测试框架对我的代码进行单元测试,因为它似乎很容易使用。 您是否建议将其与我的代码捆绑在一起,例如在inc/gtest或contrib/gtest文件夹中? 如果捆绑在一起,您是否建议使用fuse_gtest_files.py脚本减少文件数量或保留原样? 如果不捆绑在一起,该依赖性如何处理? 在编写测试时,通常如何组织这些测试? 我当时想为每个类test_vector3.cpp一个cpp文件(例如, test_vector3.cpp ),但是全部编译成一个二进制文件
  • 在Fedora中安装OpenCV-Python | 二
    目标 在本教程中 我们将学习在你的Fedora系统中设置OpenCV-Python。针对Fedora 18(64位)和Fedora 19(32位)进行以下步骤。 介绍 可以通过两种方式在Fedora中安装OpenCV-Python:1)从fedora存储库中可用的预构建二进制文件安装,2)从源代码进行编译。在本节中,我们将同时看到这两种方法。 另一个重要的事情是所需的其他库。OpenCV-Python仅需要Numpy(除了其他依赖关系,我们将在后面看到)。但是在本教程中,我们还使用Matplotlib进行一些简单而又漂亮的作图(与OpenCV相比,感觉好多了)。Matplotlib是可选的,但强烈建议安装。同样,我们还将看到IPython,这是一个强烈推荐的交互式Python终端。 从预构建的二进制文件安装OpenCV-Python 以root用户身份在终端中使用以下命令安装所有软件包。 $ yum install numpy opencv * 打开Python IDLE(或IPython),然后在Python终端中键入以下代码。 >>> import cv2 as cv >>> print( cv.__version__ ) 如果打印出来的结果没有任何错误,那就恭喜!你已经成功安装了OpenCV-Python。 这很简单。但是这里有一个问题。Yum仓库可能不总是包含最新版本的
  • 使用cmake在复杂项目中仅安装一个目标(及其依赖项)(开放给更好的解决方案)(Installing only one target (and its dependencies) out of a complex project with cmake (open to better solutions))
    问题 假设我有一个由几个子项目A,B,C,D组成的项目...所有子项目都依赖于A ,而A经常更改。 另外,可能还存在一些依赖关系:在本示例中, D依赖于B。 现在:许多人正在从事这些项目。 主CMakeLists.txt文件应包含所有目录,以便build all可以构建所有内容。 但是人们也希望只能在其中一个项目上工作,而不必每次都构建/安装所有项目。 如果我在D上工作,则可以通过调用来轻松构建“仅” D cmake --build . --target D -- -j7 或者 ninja -j7 D 如果它们的某些更改,这也会构建A和B。 完美的。 但是如何调用D的仅安装而不触发所有构建? 我想打电话给我: ninja -j7 D install 它仅构建D(及其依赖项),然后仅安装D及其依赖项(A和B)。 相反,它将构建所有目标并安装所有目标。 我想保持所有目标都在继续构建所有目标。 因此,EXCLUDE_FROM_ALL将不是一个选择。 但是朝那个方向前进,我找不到任何解决方案。 因此,我正在考虑以下策略: 除子项目A外,所有其他目标在安装时均设置为EXCLUDE_FROM_ALL,并设置为OPTIONAL。 我添加了一个额外的子项目,该子项目完全依赖于所有其他子项目(也许我通过使用在PARENT_SCOPE上设置的变量来使每个目标发布其名称)
  • 如何使用CMake正确添加包含目录(How to properly add include directories with CMake)
    问题 大约一年前,我询问了CMake中的标头依赖性。 最近我意识到问题似乎是CMake认为这些头文件在项目外部。 至少在生成Code :: Blocks项目时,头文件不会出现在项目中(源文件会出现)。 因此,在我看来,CMake认为这些标头在项目外部,而不在依赖中跟踪它们。 在CMake教程中快速搜索仅指向include_directories ,这似乎并没有达到我的期望... 向CMake发出信号的正确方法是什么,即特定目录包含要包含的标头,并且应由生成的Makefile跟踪这些标头? 回答1 必须做两件事。 首先添加要包含的目录: target_include_directories(test PRIVATE ${YOUR_DIRECTORY}) 如果您使用的是非常老的CMake版本(2.8.10或更旧版本)而又不支持target_include_directories ,则也可以改用旧的include_directories : include_directories(${YOUR_DIRECTORY}) 然后,还必须将头文件添加到当前目标的源文件列表中,例如: set(SOURCES file.cpp file2.cpp ${YOUR_DIRECTORY}/file1.h ${YOUR_DIRECTORY}/file2.h) add_executable(test $
  • 在CMake中设置通用编译标志的现代方法是什么?(What is the modern method for setting general compile flags in CMake?)
    问题 CMake提供了多种机制来获取编译器的标志: CMAKE_ <LANG> _FLAGS_ <CONFIG>变量 add_compile_options命令 set_target_properties命令 在现代使用中,有没有一种方法比另一种方法更可取? 如果可以,为什么? 另外,该方法如何与MSVC等多个配置系统一起使用? 回答1 对于现代CMake(版本2.8.12及更高版本),应使用target_compile_options,它在内部使用目标属性。 CMAKE_<LANG>_FLAGS是全局变量,最容易使用。 它还不支持生成器表达式,该表达式非常有用。 add_compile_options基于目录属性,在某些情况下可以使用,但是通常不是指定选项的最自然的方法。 target_compile_options基于每个目标工作(通过设置COMPILE_OPTIONS和INTERFACE_COMPILE_OPTIONS目标属性),通常会生成最干净的CMake代码,因为源文件的编译选项由文件所属的项目(而不是哪个目录)确定。它放在硬盘上)。 这样做还有一个好处,就是如果需要的话,它可以自动将选项传递给相关的目标。 尽管每个目标命令有些冗长,但它们可以对不同的构建选项进行合理的细粒度控制,并且(以我个人的经验)从长远来看,最不容易引起头痛。 从理论上讲,您也可以直接使用set
  • 如何以跨平台方式使用CMake ExternalProject_Add或替代项?(How do I use CMake ExternalProject_Add or alternatives in a cross-platform way?)
    问题 我想构建一个第三方项目,该项目已经将CMake作为我项目的CMake条的一部分。 ExternalProject_Add是用于此目的的,但是我发现它只能与特定的生成器一起使用,并且我希望它可以轻松地在许多平台上运行。 例如,这是我的外部项目,其中添加了zlib脚本,该脚本具有自己的CMakeLists.txt: set(USE_PROJECT_CMAKE_MODULE_PATH "-DCMAKE_MODULE_PATH=${MAKE_MODULE_PATH}") ExternalProject_Add(ZLIB SOURCE_DIR ${CMAKE_SOURCE_DIR}/external/zlib DOWNLOAD_COMMAND "" UPDATE_COMMAND "" CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR> -DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS} -DCMAKE_C_FLAGS=${CMAKE_C_FLAGS} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} ${USE_PROJECT_CMAKE_MODULE_PATH} INSTALL_COMMAND "") ExternalProject_Add_Step(ZLIB
  • CMake如何使用? [关闭](How is CMake used? [closed])
    问题 关门了。 这个问题需要更加集中。 它当前不接受答案。 想要改善这个问题吗? 更新问题,使其仅通过编辑此帖子即可将重点放在一个问题上。 3年前关闭。 改善这个问题 众所周知,作为初学者,很难获得有关CMake的任何有用信息。 到目前为止,我已经看了一些关于如何建立一些非常基础的项目或其他项目的教程。 然而,没有这些解释背后是他们出,总是留下许多孔,以填补任何的理由。 在CMakeLists上调用CMake是什么意思? 每个构建树应该调用一次还是什么? 如果它们都使用来自相同来源的相同C​​MakeLists.txt文件,如何为每个内部版本使用不同的设置? 为什么每个子目录都需要自己的CMakeLists文件? 在项目根目录以外的CMakeLists.txt上使用CMake是否有意义? 如果是这样,在什么情况下? 指定如何从自己子目录中的CMakeLists文件构建可执行文件或库与在所有源根目录的CMakeLists文件中进行构建之间有什么区别? 我可以在调用CMake时更改-G选项,就为Eclipse创建一个项目,为Visual Studio创建一个项目吗? 那甚至是如何使用的? 到目前为止,我所见过的任何教程,文档页面或问题/答案都无法对理解如何使用CMake提供任何有用的见解。 这些例子只是不彻底的。 无论阅读什么教程,我都觉得自己缺少了一些重要的东西。
  • 如何在CMake中使用CCache?(How to Use CCache with CMake?)
    问题 我想执行以下操作:如果PATH中存在CCache,请使用“ ccache g ++”进行编译,否则请使用g ++。 我尝试编写一个小的my-cmake脚本,其中包含 CC="ccache gcc" CXX="ccache g++" cmake $* 但它似乎不起作用(运行make仍不使用ccache;我使用CMAKE_VERBOSE_MAKEFILE选中了它)。 更新: 根据此链接,我尝试将脚本更改为 cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $* 但是cmake可以避免抱怨使用编译器ccache失败(这是可以预期的)。 回答1 我个人在$PATH有/usr/lib/ccache 。 该目录包含符号链接的负载,其中包含指向编译器可调用的每个可能名称的符号链接(如gcc和gcc-4.3 ),均指向ccache。 而且我什至没有创建符号链接。 当我在Debian上安装ccache时,该目录已预先填充。 回答2 从CMAKE 3.4开始,您可以执行以下操作: -DCMAKE_CXX_COMPILER_LAUNCHER=ccache 回答3
  • 在某些情况下CMake找不到Boost的可能原因?(Possible causes for Boost not being found by CMake in certain situations?)
    问题 我使用CMake (3.4.1)根据Boost库构建一个C ++项目。 宿主平台是Linux ,目标是宿主和交叉构建Android NDK。 我只使用Boost头文件,我只是下载/提取了boost文件夹(并且我没有/usr/include/boost目录)。 在我的CMakeLists.txt文件中,我这样声明对Boost的依赖关系: find_package(Boost 1.57 REQUIRED) 然后按以下方式配置我的构建: BOOST_ROOT=/path/to/boost cmake ../src 这实际上可以像我的本机版本那样工作。 现在,当我以完全相同的方式配置构建时(仅指定一些其他环境变量和CMAKE_TOOLCHAIN_FILE),CMake会给我以下信息: BOOST_ROOT=/path/to/boost JAVA_HOME=/bla/bla/bla \ ANDROID_NDK=/bla/bla/bla \ ANDROID_SDK=/bla/bla/bla \ ANT=/usr/bin/ant \ cmake ../src -DCMAKE_TOOLCHAIN_FILE=/bla/bla/android.toolchain.cmake CMake Error at /usr/share/cmake/Modules/FindBoost.cmake:1247
  • CMake target_include_directories范围的含义(CMake target_include_directories meaning of scope)
    问题 与CMake的target_include_directories相关的关键字PUBLIC , PRIVATE和INTERFACE是什么意思? 回答1 这些关键字用于指示何时需要您传递给目标的包含目录列表。 在when时,表示是否需要包含这些目录: 编译目标本身。 编译依赖于该目标的其他目标(例如使用其公共标头)。 在上述两种情况下。 CMake编译目标时,它将使用目标INCLUDE_DIRECTORIES , COMPILE_DEFINITIONS和COMPILE_OPTIONS属性。 在target_include_directories()等中使用PRIVATE关键字时,您告诉CMake填充这些目标属性。 当CMake检测到目标A与另一个目标B之间的依赖关系时(例如,当您使用target_link_libraries(AB)命令时),它会将B使用要求传递给A目标。 这些目标使用需求是包含目录,编译定义等,所有依赖于B目标都必须满足。 它们由上面列出的属性的INTERFACE_*版本指定(例如INTERFACE_INCLUDE_DIRECTORIES ),并在调用target_*()命令时使用INTERFACE关键字进行填充。 PUBLIC关键字的含义大致为PRIVATE + INTERFACE 。 因此,假设您正在创建使用某些Boost标头的库A 您可以这样做:
  • 扩展setuptools扩展以在setup.py中使用CMake吗?(Extending setuptools extension to use CMake in setup.py?)
    问题 我正在编写一个链接C ++库的Python扩展,并且正在使用cmake来帮助构建过程。 这意味着,现在,我知道如何捆绑它的唯一方法,必须首先使用cmake对其进行编译,然后才能运行setup.py bdist_wheel。 一定会有更好的办法。 我想知道是否有可能(或有人尝试过)在setup.py ext_modules构建过程中调用CMake? 我猜有一种方法可以创建某些东西的子类,但是我不确定在哪里看。 我之所以使用CMake,是因为它为我提供了更多控制权,可以完全按照我的意愿使用复杂的构建步骤来构建c和c ++库扩展。 另外,我可以使用findPythonLibs.cmake中的PYTHON_ADD_MODULE()命令直接使用cmake轻松构建Python扩展。 我只希望这是所有步骤。 回答1 您基本上需要做的是在setup.py覆盖build_ext命令类,并将其注册到命令类中。 在build_ext的自定义build_ext ,配置并调用cmake进行配置,然后构建扩展模块。 不幸的是,官方文档对如何实现自定义distutils命令distutils (请参阅扩展Distutils)。 我发现直接研究命令代码会更有帮助。 例如,这是build_ext命令的源代码。 示例项目 我准备了一个简单的项目,该项目由一个C扩展名foo和一个python模块spam.eggs
  • 如何使用cmake将git SHA1作为定义传递给编译器?(How can I pass git SHA1 to compiler as definition using cmake?)
    问题 在Makefile中,可以通过以下方式完成此操作: g++ -DGIT_SHA1="`git log -1 | head -n 1`" ... 这非常有用,因为二进制文件知道确切的提交SHA1,因此在出现段错误的情况下可以将其转储。 如何使用CMake达到相同的目的? 回答1 我已经制作了一些CMake模块,它们可以混入git repo中以进行版本控制和类似目的-它们都在我的存储库中,网址为https://github.com/rpavlik/cmake-modules 这些功能的好处是,每次HEAD提交更改时,它们将在构建之前强制进行重新配置(cmake的重新运行)。 与仅使用execute_process进行一次操作不同,您无需记住重新进行make来更新哈希定义。 为此,您至少需要GetGitRevisionDescription.cmake和GetGitRevisionDescription.cmake.in文件。 然后,在您的主要CMakeLists.txt文件中,您将得到如下内容 list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/whereYouPutMyModules/") include(GetGitRevisionDescription) get_git_head_revision(GIT
  • 设置和使用变量的CMake语法是什么?(What's the CMake syntax to set and use variables?)
    问题 我问这是我下次使用CMake时的提醒。 它永远不会停留,而且Google的结果也不是很好。 在CMake中设置和使用变量的语法是什么? 回答1 在编写CMake脚本时,您需要了解很多有关语法以及如何在CMake中使用变量的知识。 语法 使用set()字符串: set(MyString "Some Text") set(MyStringWithVar "Some other Text: ${MyString}") set(MyStringWithQuot "Some quote: \"${MyStringWithVar}\"") 或使用string() : string(APPEND MyStringWithContent " ${MyString}") 使用set()列出: set(MyList "a" "b" "c") set(MyList ${MyList} "d") 或与list()更好: list(APPEND MyList "a" "b" "c") list(APPEND MyList "d") 文件名列表: set(MySourcesList "File.name" "File with Space.name") list(APPEND MySourcesList "File.name" "File with Space.name") add_excutable