【译文】Mastering CMake(chapter 2)Getting Started

第二章 开始

2.1 获取并在您的计算机上安装CMake

在使用CMake之前,您需要在您的系统上安装或构建CMake二进制安装文件。 在许多系统中,您可能会发现CMake已经安装,或者可以使用系统的标准软件包管理工具进行安装。 Cygwin,Debian,FreeBSD,Mac OS X Fink等等都有CMake发行版。 如果您的系统没有CMake包,您可以在www.cmake.org上找到针对大多数常见体系结构的CMake预编译。 如果您没有为您的系统预编译找到二进制文件,那么您可以从源代码构建CMake。 要构建CMake,您需要一个c ++编译器。

UNIX和Mac的安装

如果你的系统提供CMake安装包作为其标准软件包之一,请按照系统的软件包安装说明进行安装。 如果你的系统没有CMake安装包,或者有一个过时的CMake版本,你可以从www.cmake.org下载预编译的二进制文件。这个二进制文件是tar格式。 tar文件包含一个README文件和一个封闭的tar文件。 README文件包含封装的tar文件中包含的文件清单以及一些说明。安装只需将附带的tar文件解压到目标目录(通常是/usr/local)。 但是,它可以是任何目录,并且不需要root权限来进行安装。

Windows二进制安装

CMake有一个NullSoft安装文件可以从www.cmake.org下载。 要安装此文件,只需在要运行CMake的Windows计算机上运行可执行文件即可。 安装后,您将能够从开始菜单运行CMake。

2.2 自己建立CMake

如果您的系统不能使用二进制文件,或者如果二进制文件不是你希望使用的CMake版本,则可以从源代码构建CMake。 您可以按照www.cmake.org上的说明获取CMake源代码。 一旦你有源代码,它可以用两种不同的方式建立。 如果您的系统上有一个CMake版本,则可以使用它来构建其他版本的CMake。 一般来说,CMake的当前开发版本总是可以从以前的CMake版本开始构建。 这是在大多数Windows系统上如何构建新版本的CMake。
构建CMake的第二种方法是运行其构建脚本。你需要改变目录到你的CMake源代码目录并输入

./bootstrap
make
make install
  • 1
  • 2
  • 3

make install步骤是可选的,因为CMake可以直接从build目录运行。 在UNIX上,如果您不使用GNU C++编译器,则需要告诉引导程序脚本使用哪个编译器。 这是通过在运行引导之前设置环境变量cxx来完成的。 如果您需要在编译器中使用任何特殊标志,请设置CXXFLAGS环境变量。 例如,在带有7.3X编译器的SGI上,你可以这样编译CMake:

cd CMake 
(setenv CXX CC; setenv CXXFLAGS "-LANG:std";./bootstrap) 
make 
make install
  • 1
  • 2
  • 3
  • 4

2.3 基本CMake用法和语法

使用CMake很简单。 构建过程是通过创建一个或多个CMakeLists文件(实际上是CMakeLists.txt,但本指南将在大多数情况下脱离扩展)控制在项目的每个目录中。 CMakeLists文件应该包含CMake简单语言的项目描述。 语言表达为一系列命令。 每个命令按照它在CMakeLists文件中出现的顺序进行评估。 这些命令的形式

command (args ... ) 
  • 1

其中command是命令,args是由空格分隔的参数列表。 (带有嵌入式空格的参数应该用双引号。)从版本2.2开始,CMake对命令名不区分大小写。所以在你看到命令的地方你可以使用COMMAND或者Command。较早版本的CMake只接受大写命令。

CMake支持可以是字符串或字符串列表的简单变量。变量是使用$ {VAR}语法引用的。可以使用set命令将多个参数组合到一个列表中。所有其他命令展开列表,就好像它们已经通过空白分隔传递到命令一样。例如,set(Foo a b c)将导致将变量Foo设置为abc,并且如果将Foo传递给另一个命令command($ {Foo}),它将等同于命令(a b c)。如果你想把一个参数列表传递给一个命令,就好像它是一个参数一样,只需双引号即可。例如oomrnand(”$ {Foo}”)将被调用,只传递一个相当于command(”a b c”)的参数。

系统环境变量和Windows注册表值可以直接在CMake中访问。要访问系统环境变量,使用语法$ ENV {VAR}。 CMake还可以使用[HKEY_CURRENT_USER\\ Software \\ pathl \\ path2; key]形式的语法在许多命令中引用注册表项,其中路径是从注册表树和键构建的。

2.4 CMake的Hello World

对于初学者,让我们考虑最简单的CMakeLists文件。 要从一个源文件编译一个可执行文件,CMakeLists文件将包含两行:

project(Hello)
add executable(Hello Hello.c)
  • 1
  • 2

要构建Hello这个可执行文件,请遵循如何运行CMake(参见第2.5节)中描述的过程来生成Makefiles或Microsoft项目文件。 project命令指示生成的工作区的名称应该是什么,add_executable命令将可执行目标添加到生成过程。 这就是这个简单的例子。 如果您的项目需要几个文件,这也很容易,只需修改添加可执行文件行,如下所示。

    add executable (Hello Hello.c File2.c File3.c File4.c)
  • 1

add_executable只是CMake中的众多命令之一。 考虑下面更复杂的例子。

cmake_minimum_required (2.6) 
project (HELLO) 

set (HELLO_SRCS Hello.c File2.c File3.c) 

if (WIN32) 
    set (HELLO_SRCS ${HELLO_SRCS} WinSupport.c) 
else ()     
    set (HELLO_SRCS ${HELLO_SRCS} UnixSupport.c) 
endif () 

add_executable (Hello ${HELLO_SRCS}) 

# look for the Tcl library
find_library(TCL_LIBRARY
    NAMES tcl tc184 tc183 tc182 tc180 
    PATHS /usr/lib /usr/local/lib 
    ) 
if (TCL_LIBRARY) 
    target linklibrary (Hello $ {TCL_LIBRARY}) 
endif ()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这个例子中,set命令用于将源文件分组到一个列表中。 if命令用于判断是否将WinSupport.c或UnixSupport.c添加到此列表中。 最后,add_executable命令用于使用变量HELLO_SRCS中列出的文件构建可执行文件。 find_library命令以几个不同的名字和几个不同的路径查找Tcl库。 if命令检查TCL_LIBRARY是否被找到,是否将其添加到Hello可执行目标的链接行。 请注意使用#字符表示注释行。 从#到行尾的所有字符都被认为是一部分注释。

2.5 如何运行CMake?

一旦CMake安装在您的系统上,使用它来建立一个项目很容易。 CMake在构建项目时使用了两个主目录:源目录和二进制目录。 源目录是您的项目的源代码所在的位置。 这也是CMakeLists文件被找到的地方。 二进制目录是你希望CMake放置生成的目标文件,库和可执行文件的位置。 通常CMake不会将任何文件写入源目录,只有二进制目录。 如果你想要你可以设置源和二进制目录是一样的。 这被称为源代码内部构建,而不同于它的是不同的外部构建。

CMake支持所有操作系统上的源码内部和源码外部构建。 这意味着您可以完全地在源代码树之外配置你的构建,这样可以非常容易地删除构建生成的所有文件。 让构建树不同于源代码树也使得对於单个源代码树进行多个构建变得容易。 当你想要有不同的选项,但只有一个源代码的副本,这是很有用的。 现在让我们考虑使用基于Qt的GUI和命令行界面来运行CMake的细节。

运行CMake的Qt界面

CMake包含一个由Clinton Stimpson开发的基于Qt的用户界面,可以在大多数平台上使用,包括UNIX,Mac OS X和Windows。 这个接口包含在CMake源代码中,但是你需要在你的系统上安装Qt来构建它。

这里写图片描述
Figure 1 - Qt based CMake GUI

在Windows上,可执行文件被命名为cmake-gui.exe,并且应该位于 开始菜单中的Program Files下 。 在你的桌面上也可能有一个快捷方式,或者如果你从源代码构建CMake,它将在build目录中。 对于UNIX和Mac用户,可执行文件被命名为cmake-gui,可以在安装CMake可执行文件的位置找到。可以看到类似于图1所示的GUI。前两个条目是源代码和二进制目录。 它们允许您指定源代码的位置,以及要生成的二进制文件的位置。 你应该先设置这两个值。 如果您指定的二进制目录不存在,它将为您创建。 如果二进制目录已经被CMake配置,那么它会自动设置源码树。

中间区域是你可以为构建过程指定不同选项的位置。更高级的变量可能被隐藏,但是如果从视图下拉菜单中选择“Advanced View”,则可以看到这些变量。您可以通过在搜索框中输入全部或部分名称来搜索中间区域的值。这可以方便地找到大型项目中的特定设置或选项。窗口的底部区域包括“配置”和“生成”按钮以及进度条和可滚动输出窗口。

一旦你指定了源代码和二进制目录,你应该点击配置按钮。这将导致CMake从源代码目录中读取CMakeLists文件,然后更新缓存区域以显示项目的任何新选项。如果你是这个二进制文件目录上首次运行cmake,它会提示你确定你想要使用什么生成器, 如图2所示。这个对话框也会显示选项,用来定制和调整这次构建你想使用的编译器 。

这里写图片描述
Figure 2 - Selecting a Generator

第一次配置后,您可以根据需要调整缓存设置,然后再次单击配置按钮。 由配置过程创建的新值将被标记为红色。 为了确保你已经看到了所有可能的值,你应该点击配置,直到没有值是红色的,并且你对所有的设置感到满意。 一旦你完成配置,点击生成按钮,这将生成合适的文件。

确保你的环境适合运行cmake-gui是非常重要的。如果您使用的是Visual Studio等IDE,那么你的环境将设置正确。如果您正在使用NMake或MinGW,那么您需要确保编译器可以从你的环境运行。您可以直接为您的编译器设置所需的环境变量,也可以使用已经设置好的shell。例如,Microsoft Visual Studio在开始菜单上有一个用于创建Visual Studio命令提示符的选项。这将打开一个命令提示符窗口,其中已经为Visual Studio设置了其环境。如果你想使用NMake Makefiles,你应该从这个命令提示符运行cmake-gui。同样的方法适用于MinGW,你应该从MinGW shell中运行cmake-gui,在它的路径中有一个工作的编译器。

当cmake-gui完成时,它将在您指定的二进制目录中生成构建文件。如果选择Visual Studio作为生成器,则创建一个MSVC工作区(或解决方案)文件。这个文件的名字是基于你在CMakeLists文件开头的PROJECT命令中指定的项目的名字。对于许多其他生成器类型,生成Makefile文件。此过程的下一步是使用MSVC打开工作区。一旦打开,该项目就可以以Microsoft Visual C ++的正常方式构建。 ALL BUILD目标可用于构建包中的所有库和可执行文件。如果您正在使用Makefile构建类型,则可以通过对生成的Makefiles运行make或nmake来构建。

运行cmake Curses界面

在大多数UNIX平台上,如果支持curses库,CMake提供一个名为ccmake的可执行文件。 这个接口是一个基于终端的文本应用程序,非常类似于基于Qt的GUI。 要运行ccmake,将目录(cd)更改为要放置二进制文件的目录。 这可以是我们所说的源代码构建的源代码相同的目录,也可以是您创建的新目录。 然后运行ccmake,在命令行中输入源目录的路径。 对于源代码内部使用“.” 为源目录。 这将启动文本界面,如图3所示(在这种情况下,缓存变量来自VTK,大多数都是自动设置的)。

这里写图片描述
Figure 3 - ccmake running on UNIX

窗口底部显示简要说明。 如果你点击“c”键,它将配置项目,你应该总是在更改缓存中的值之后进行配置,要改变值,使用箭头键选择缓存条目,然后使用回车键来编辑它们。 值会随着回车键一起切换,一旦你设定了所有的值,你可以点击“g”键来生成Makefile并退出,也可以点击“h”来获得帮助,“q”退出 ,“t”切换查看高级缓存条目。 在UNIX平台上的CMake使用的两个例子遵循一个名为Hello的helloworld项目。 在第一个示例中,执行源码内部构建。

cd Hello 
ccmake 
make 
  • 1
  • 2
  • 3

在第二个示例中,执行源码外部构建。

mkdir Hello-Linux 
cd Hello-Linux 
ccmake .. /Hello 
make 
  • 1
  • 2
  • 3
  • 4

从命令行运行CMake

在命令行中,CMake可以作为交互式问答模式运行,也可以作为非交互式程序运行。 要以交互模式运行,只需将“-i”选项传递给CMake。 这将导致CMake向您要求项目缓存文件中的每个条目的值。 CMake将提供合理的默认值,就像基于GUl和curses的接口一样。 当不再有任何问题要求时,该过程停止。 下面提供了一个使用CMake交互模式的例子。

$ cmake -i -G "NMake Makefiles" .. /CMake 
Would you like to see advanced options? [No]: 
Please wait while cmake processes CMakeLists.txt files .... 

Variable Name: BUILD TESTING 
Description: Build the testing tree. 
Current Value: ON 
New Value (Enter to keep current value): 

Variable Name: CMAKE INSTALL PREFIX 
Description: Install path prefix, prepended onto install directories. 
Current Value: C:/Program Files/CMake 
New Value (Enter to keep current value):

Please wait while cmake processes CMakeLists.txt files .... 

CMake complete, run make to build project.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

如果项目有很少或没有选项,使用CMake在非交互模式下建立一个项目是一个简单的过程。 对于像VTK这样的大型项目,推荐使用ccmake,cmake-i或者cmake-gui。 要使用非交互式CMake构建项目,请首先将目录更改为要放置二进制文件的位置。 对于源码内部构建,然后运行cmake。 并使用-D标志传入任何选项。 对于源码外部构建,除了运行cmake,还提供源代码的路径作为参数,这个过程是一样的。 然后键入make,你的项目应该编译。 有些项目也会有安装目标,你可以输入make install来安装它们。

为CMake指定编译器

在某些系统上,可能有多个编译器可供选择,或者编译器可能处于非标准位置。 在这些情况下,您将需要指定到您的编译器所在的位置 。 有三种方法来指定位置; 生成器可以指定编译器,可以设置环境变量,也可以设置缓存条目。 一些生成器绑定了特定的编译器,例如Visual Studio 6生成器始终使用Microsoft Visual Studio 6编译器。 对于基于Makefile的生成器,CMake会尝试一个通常的编译器列表,直到找到一个可用的编译器。 该列表可以在文件中找到:

Modules/CMakeDeterminCCompiler.cmake and
Modules/CMakeDetermineCXXCompiler.cmake
  • 1
  • 2

这些列表可以通过 CMake运行之前设置的环境变量来抢占。 CC环境变量指定C编译器,而cxx环境变量指定C ++编译器。 您可以通过使用DCMAKE_CXX_COMPILER = cl直接在命令行上指定编译器。 如果没有设置,CMake会尝试下面的编译器列表:

c++ g++ CC aCC cl bcc xlC.
  • 1

一旦CMake运行并选择了一个编译器,您可以通过更改缓存条目CMAKE_CXX_COMPILER和CMAKE_C_COMPILER来更改选择,但是不建议这样做。 这样做的问题是您正在配置的项目可能已经在编译器上运行了一些测试,并且已经确定了它支持什么。 更改编译器通常不会导致这些测试重新运行,从而导致错误的结果。 如果您必须更改编译器,请从空的二进制目录开始。 编译器和链接器的标志也可以通过设置环境变量来改变。 设置LDFLAGS将初始化链接标志的缓存值,而CXXFLAGS和CFLAGS将分别初始化CMAKE _ CXX_FLAGS和CMAKE_C_FLAGS。

依赖性分析

CMake为C和C++源代码文件提供了强大的内置依赖分析功能。 CMake对Fortran和Java依赖的支持也有限。由于集成开发环境(IDE)支持和维护依赖信息,所以CMake跳过这个构建系统的步骤。但是,Makefile中有一个make程序不知道如何自动计算并保持最新的依赖信息。对于这些构建,CMake会自动计算C,C++和Fortran文件的依赖信息。这些依赖关系的生成和维护都是由CMake自动完成的。一旦项目最初由CMake配置,用户只需要运行make,CMake就可以完成其余的工作。 CMake的依赖完全支持多处理器系统的并行构建。

虽然用户不需要知道CMake是如何工作的,但查看项目的依赖关系信息文件可能是有用的。每个目标的信息存储在四个文件中,分别叫depend.make,flags.make,build.make和DependInfo.emake。depend.make使所有目标文件的依赖信息存储在目录中。 flags .make包含用于此目标的源文件的编译flags。如果他们改变,那么文件将被重新编译。 DependInfo.emake用来保持最新的依赖信息,并且包含关于什么文件是项目的一部分以及它们在哪些语言中的信息。最后,构建依赖关系的规则被存储在build.make中 。如果依赖关系已经过期,那么将重新计算该目标的所有依赖关系,从而使依赖关系信息保持最新。

2.6 编辑CMakeLists文件

CMakeLists文件几乎可以在任何文本编辑器中编辑。一些编辑器(如Notepad ++)带有内置的CMake语法突出显示和缩进支持。对于像Emacs或Vim CMake这样的编辑器,包括缩进和语法突出显示模式。这些可以在源代码分发的Docs目录中找到,或者从CMake网站下载。文件cmake-mode.el是Emacs模式,cmake-indent.vim和cmakesyntax.vim被Vim使用。在Visual Studio中,CMakeLists文件被列为项目的一部分,您可以通过双击来编辑它们。在任何支持的生成器(Makefiles,Visual Studio等)中,如果编辑CMakeLists文件并重建,则会有一些规则自动调用CMake来根据需要更新生成的文件(例如Makefile或项目文件)。这有助于确保生成的文件始终与您的CMakeLists文件同步。

由于CMake计算并维护依赖关系信息,所以在CMake上make或者运行IDE 生成文件时,CMake可执行文件必须始终可用(尽管它们不必在PATH中)。这意味着如果一个CMake输入文件在磁盘上发生变化,您的编译系统将自动重新运行CMake并生成最新的编译文件。出于这个原因,您通常不应该使用CMake生成Makefile或项目,并将它们移动到没有安装CMake的另一台机器上。

2.7 设置CMake的初始值

虽然CMake在交互模式下运行良好,但有时您需要设置缓存条目而不运行GUI。 这在设置每晚仪表板时很常见,或者您将创建许多具有相同缓存值的构建树。 在这些情况下,CMake缓存可以通过两种不同的方式进行初始化。 第一种方法是使用DCACHE _ VAR:TYPE = VALUE参数在CMake命令行上传递缓存值。 例如,考虑一下UNIX机器的夜间仪表板脚本:

#!/bin/tcsh 

cd ${HOME} 

# wipe out the old binary tree and then create it again 
rm -rf Foo-Linux 
mkdir Foo-Linux
cd Foo-Linux 

# run cmake to setup the cache 
cmake -DBUILD TESTING:BOOL=ON <etc ... > .. /Foo

# generate the dashboard 
ctest -0 Nightly 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Windows上的批处理文件可以使用相同的想法。 第二种方法是使用CMake的-c选项创建一个要加载的文件。 在这种情况下,而不是使用-D选项来设置缓存,而是通过由CMake解析的文件来完成。 这个文件的语法是标准的CMakeLists语法,通常只是一系列的设置命令,例如:

#Build the vtkHybrid kit. 
set (VTK USE HYBRID ON CACHE BOOL "doc string")
  • 1
  • 2

在某些情况下,可能会有已经存在的缓存,并且您想要强制设置缓存值。 例如,即使用户以前运行CMake并将其关闭,你也想要打开Hybrid。 那你可以这样做:

#Build the vtkHybrid kit always. 
set (VTK USE HYBRID ON CACHE BOOL "doc" FORCE)
  • 1
  • 2

另一个选择是你想设置并且之后隐藏这些选项,以便用户以后不会再调整。 这可以使用以下命令完成:

#Build the vtkHybrid kit always and don't distract 
#the user by showing the option. 
set (VTK USE HYBRID ON CACHE INTERNAL "doc" FORCE) 
mark as advanced (VTK USE HYBRID)
  • 1
  • 2
  • 3
  • 4

您可能会试图直接编辑缓存文件,或者通过给项目初始化缓存文件来“初始化”项目。 这可能不起作用,并可能在未来导致更多的问题。 首先,CMake缓存的语法可能会改变。 其次,缓存文件中有完整的路径,使得它们不适合在二叉树之间移动。 所以如果你想初始化一个缓存文件,可以使用上面描述的两种标准方法之一。

2.8 建设你的项目

运行CMake后,您的项目将准备好建立。 如果您的目标生成器基于Makefiles,那么您可以通过将目录更改为二叉树并键入make(或适当的gmake或nmake)来构建项目。 如果为Visual Studio等IDE生成文件,则可以启动IDE,将项目文件加载到该文件中,然后像平常一样进行构建。

另一个选择是从命令行使用CMake的-build选项。 这个选项只是一个简单的方法,允许你从命令行建立你的项目,即使这需要启动一个IDE。 -build选项包括:

Usage: cmake --build <dir> [options] [-- [native-options]] Options: 
<dir>           = Project binary directory to be built.
--target <tgt>  = Build <tgt> instead of default targets. 
--config <cfg>  = For multi-configuration tools, choose <cfg>.
--clean-first   = Build target 'clean' first, then build. 
                  (To clean only, use --target 'clean'.) 
--              = Pass remaining options to the native tool.
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

因此,即使您使用Visual Studio作为您的生成器,如果您愿意,也可以通过命令行键入以下内容来构建您的项目。

cmake --build <your binary dir>
  • 1

这就是为简单的项目安装和运行CMake。 在下面的章节中,我们将更加详细地考虑CMake,以及如何在更复杂的软件项目中使用它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章