02 项目设置
如果没有构建系统,那么项目仅仅是一些文件的集合。CMake通过使用名为CMakeLists.txt的文件为项目中文件的集合定义了一些规则,这些规则定义了构建的内容、如何构建、运行哪些测试以及创建哪些包。CMakeLists.txt文件是普通文本文件且是平台无关的,可以直接用文本编辑器进行修改,CMake会将其转换为对应平台的特定构建工具的项目文件。此文件的内容将在后续章节中进行详细介绍,但目前,我们只需要直到它的作用是控制CMake来设置和执行构建的过程就足够了。
CMake的一个基本概念是项目同时具有源目录(source directory)和二进制目录(binary directory)。源目录是CMakeLists.txt文件所在的位置,项目的源文件和其他构建所需要的文件也组织在这个目录下,源目录通常使用git、subversion等工具进行版本控制。
二进制目录是构建过程中生成的文件的所在位置。通常也被称为构建目录(build directory)。CMake官方通常使用二进制目录一词,而开发人员通常使用构建目录的称呼,本书中也使用这个名称,因为它更加直观。CMake、构建工具(例如make、Visual Studio等)、CTest和CPack等都会在构建目录及其子目录中创建各种文件,可执行文件、库、测试输出和包也都在构建目录中生成。CMake还在构建目录中创建一个名为CMakeCache.txt的文件来存储多种信息,以便在后续运行时复用。开发人员通常不需要关注CMakeCache.txt文件,但在后续章节中我们也会讨论一些此文件相关的内容。构建工具对应的项目文件(例如Xcode或Visual Studio项目文件、Makefiles等)同样应该在构建目录中生成,且不应该由版本管理工具控制。CMakeLists.txt文件是项目的正确描述,其生成的项目文件应被视为是构建输出的一部分。
当开发人员创建项目时,必须确认构建目录应该放置在哪里。相对于源目录位置来说,有两种放置方法:源内构建(in-source builds)和源外构建(out-of-source builds)。
2.1 源内构建
不鼓励使用这种方式。可以使用同一个目录同时作为源目录和构建目录,这种方式被称为源内构建。新手开发者经常使用这种方法,因为他们认为这种方法比较简单。但是,源内构建的麻烦之处在于它将所有的构建输出和源文件都混在了一起。源目录和构建目录缺少隔离会导致同一个目录中充斥着各种文件和子目录,使得项目管理更加困难,并且存在构建输出覆盖源文件的风险。使用源内构建也使得代码的版本控制更加困难,因为有许多文件是由构建创建的,版本控制工具必须知道哪些文件需要忽略或者开发人员必须在提交时手动排除这些文件。源内构建的另一个缺点是很难简单的清除所有构建输出并还原到原始代码树。所以,即使对于简单的项目,开发人员也不应该使用源内构建。
2.2 源外构建
另一种更好的方式是将源目录和构建目录分开,这种方式称为源外构建,可以避免源内构建的各种缺点。源外构建的一个优点是开发人员可以为同一个源目录创建多个使用不同设置选项的构建目录,例如调试和发布版本等。
本书将始终使用源外构建,并将源目录和构建目录置于相同父级目录下,构建目录通常命名为build
,例如:
另一种方式是使用构建目录成为源目录的一个子目录,这种方式提供了源外构建的大部分优点,但仍具有源内构建的一些缺点,除非有充足的理由以这种方式组织文件,否则还是推荐将构建目录完全置于源代码树之外。
2.3 生成项目文件
在决定了项目的目录结构之后,开发人员会运行CMake,CMake将读取CMakeLists.txt文件,并且在构建目录中创建项目文件。开发人员通过使用不同项目文件生成器(generator)来创建不同的项目文件的类型。CMake支持一系列不同的项目文件生成器,其中的一些如下:
一些生成器可以生成多种配置的项目(例如调试、发布等),它们允许开发人员在不重新运行CMake的情况下在不同的构建配置间进行切换,这种生成器更适合在Xcode和Visual Studio等IDE环境中使用。而对于不支持多个配置的生成器,开发者需要重新运行CMake才能在调试、发布等配置模式之间切换,这种方式更加简单,并且在与特定编译器关系不紧密的IDE环境中(Qt Creator、KDevelop等)通常有很好的支持。
运行CMake的最基本方法是在命令行终端中使用cmake
命令,首先切换到构建目录,然后将生成器类型和源码树位置作为参数传递给cmake
。例如:
mkdir build
cd build
cmake -G "Unix Makefiles" ../source
如果省略-G
选项,那么CMake将根据平台选择一个默认的生成器类型。无论是哪种生成器类型,CMake会执行一系列动作来确认如何设置项目文件,包括验证编译器是否工作、确认编译器支持的功能集以及一些其他任务。CMake在执行时会记录各种信息,如果执行成功,则会在末尾处有如下类似信息:
-- Confituring done
-- Generating done
-- Build file have been written to: /some/path/build
创建项目文件实际包含两个步骤:配置(configuring)和生成(generating)。在配置阶段,CMake读取CMakeLists.txt文件,并建立整个项目的内部表示。配置结束后,生成阶段将创建项目文件。在后续的章节中,配置和生成的区别很重要,我们在10 生成器表达式TODO中进行讨论。
当CMake运行结束后,它将在构建目录中保存一个CMakeCache.txt文件,Cmake使用此文件来保存一些信息以便于在CMake重新执行时能够复用这些信息,加快项目生成速度,它还允许在运行时保存开发人员选项。GUI应用程序cmake-gui
可以作为运行cmake
命令的替代方案,它的作用在使用变量时更加明显,将在05 变量TODO中讨论它。
2.4 运行构建工具
现在,项目的文件已经被创建出来,开发人员可以使用对应项目文件的构建工具了。构建目录中包含了必要的项目文件,这些文件可以被加载到IDE中后者被命令行工具读取。cmake
命令也可以调用构建工具,例如:
cmake --build /some/path/build --config Debug --target MyApp
这种方式同样适用于Xcode或Visual Studio等IDE所使用的项目类型。--build
选项指定CMake项目使用的构建目录。对于多配置生成器,--config
选项指定要生成的构件类型,单配置生成器则会忽略此选项并且使用CMake项目在生成步骤中使用并提供的信息,构件类型在13 构建类型TODO中进行介绍。--target
选项指明要构建的内容,如果省略,则构建默认目标。
虽然开发人员通常会在开发中直接调用构建工具,但是在自动构建脚本中使用cmake
命令来调用构建工具更加有用,一个简单的脚本如下:
mkdir build
cd build
cmake -G "Unix Makefiles" ../source
cmake --build . --config Release --target MyApp
如果开发人员希望使用不同的生成器,仅需修改-G
选项,cmake
将会调用正确的构建工具。
2.5 建议
即使是第一次使用CMake,也要养成将构建目录和源代码树完全分开的习惯,体验这种方式带来的好处的一个好方法是为同一个源目录设置两个或多个不同的构建,一个可以使用Debug
构件类型,另一个使用Release
构件类型。另一种方法是在不同的构建目录中使用不同的项目生成器,例如Unix Makefiles和Xcode,这样有助于理解特定构建工具的非预期依赖关系或不同生成器的编译器设置。
在项目早期阶段,仅使用一种特定类型的项目生成器的做法很诱人,特别是在开发人员不习惯编写跨平台软件的情况下。然而,项目常常需要支持更多的平台,因此需要不同的生成器类型,定期的使用不同的项目生成器来执行构建,检查是否有不必要的平台相关代码可以在后续开发中减少代码的改动。定期构建的另一个好处是使得项目在后续过程中可以使用任何新的生成器。一种好的方式是除了使用目标平台的默认生成器进行构建外,还使用另一个生成器进行构建。Ninja
生成器是后者的一个绝佳选择,因为它在所有生成器中拥有最广的平台支持范围,而且它的构建十分高效。
如果项目包含构建脚本,那么就通过cmake --build
来调用,而不是直接调用构建工具,这样允许脚本在不同的生成器类型之间轻松切换。
标签:02,文件,CMake,项目,生成器,构建,设置,目录 From: https://www.cnblogs.com/pannnn/p/16666671.html