CMake教程 (一)

本文所有示例来源于CMake官方教程:https://cmake.org/cmake-tutorial/

CMake简介

在开源软件的世界里,使用Makefile来管理源码、定义生成规则是事实上的标准。作为工程师,Makefile的工作原理是必须要掌握的,但在实践中,却通常不需要手写Makefile。autotool系列(autoscan, autoconf等)以及本文所说的CMake,都是辅助我们生成Makefile的工具。

使用工具生成的Makefile首先都满足一定的规范,避免了手写的五花八门的Makefile造成的碎片化问题。对于工程师来说,也无需再关注Makefile的细节,只需在更高的抽象层定义生成规则即可,简化了很多不必要的工作。

CMake基础

CMake的使用方法非常简单,如下:

cmake PATH

PATH 目录是我们需要生成Makefile的目录,此目录中必须存在一个名为CMakeLists.txt的文件。cmake会分析它的内容,生成对应的Makefile文件。有了Makefile文件,那么我们执行make就可以生成目标了。

CMake教程

通过以上我们得知,学习CMake的核心就是CMakeLists.txt文件的编写。我们根据官方的7个例子,来深入浅出的学习一下CMakeLists.txt的规则。

1. 起步

首先来看最简单的场景,我们的工程里只有一个源文件 tutorial.cxx,它是一个求平方根的程序:

// A simple program that computes the square root of a number
#include 
#include 
#include 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

根据上文,我们需要在同级目录添加一个 CMakeLists.txt 文件来定义生成规则。内容非常简单,3行即可:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
add_executable(Tutorial tutorial.cxx)

cmake_minimum_required 解析此文件需要的CMake最低版本
project 生成目标的名字
add_executable 向目标中添加源文件
它们都是CMake的命令,不区分大小写。本文为了统一,全部使用小写。

以上就是我们需要做的全部工作,接下来使用cmake命令来生成Makefile。

➜  Step1_1 cmake .
-- The C compiler identification is AppleClang 10.0.1.10010046
-- The CXX compiler identification is AppleClang 10.0.1.10010046
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/bairixin/Workspace/Test/CMake/Step1/Step1_1

将工程目录作为参数传给cmake,cmake就会帮我们生成相应的Makefile,目前文件列表如下:

➜  Step1_1 ls
CMakeCache.txt      CMakeFiles          CMakeLists.txt      Makefile            cmake_install.cmake tutorial.cxx

可以看到,CMake已成功生成了Makefile文件。当然,同时它还生成了一些缓存文件,这些我们暂不讨论。我们make一下:

➜  Step1_1 make
Scanning dependencies of target Tutorial
[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o
[100%] Linking CXX executable Tutorial
[100%] Built target Tutorial

提示已经成功生成了目标Tutorial。查看文件列表也证实了这一点:

➜  Step1_1 ls
CMakeCache.txt      CMakeFiles          CMakeLists.txt      Makefile            Tutorial            cmake_install.cmake tutorial.cxx

运行Tutorial试一下:

➜  Step1_1 ./Tutorial 4
The square root of 4 is 2

运行成功。可以看出,CMake的使用还是很简单方便的。

接下来,我们做一下扩展,在工程里添加版本号以及config头文件。虽然我们可以把版本定义放在源码中,但是在 CMakeLists.txt 中定义的话,会有更大的灵活性。我们修改CMakeLists.txt文件,如下所示:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
 
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )
 
# add the binary tree to the search path for include files
# so that we will find TutorialConfig.h
include_directories("${PROJECT_BINARY_DIR}")
 
# add the executable
add_executable(Tutorial tutorial.cxx)

我们来看一下相对于上一步新加入的内容,

# The version number.

这是一行注释,CMake的注释以#开始,这之后的本行内容都被认为是注释。

set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)

定义了两个变量,后续我们要把它们传递到源码内。

configure_file (
  "${PROJECT_SOURCE_DIR}/TutorialConfig.h.in"
  "${PROJECT_BINARY_DIR}/TutorialConfig.h"
  )

指定配置文件的位置,其中,TutorialConfig.h 是我们最终要生成的用于源码的配置文件。我们将它放在了${PROJECT_BINARY_DIR}这个目录下。TutorialConfig.h.in 是生成 TutorialConfig.h 的模板文件,后面详述。由于我们把 TutorialConfig.h 放在了${PROJECT_BINARY_DIR}这个目录下,正常情况下,编译器是找不到它的,我们还要告诉编译器,在查找头文件的时候,需要额外查找${PROJECT_BINARY_DIR}这个目录,如下:

include_directories("${PROJECT_BINARY_DIR}")

TutorialConfig.h.in 的内容如下:

// the configured options and settings for Tutorial
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@

TutorialConfig.h.in 使用 @ @ 引用 CMakeLists.txt 里定义的变量,在CMake执行时,会把它们替换为指定的变量值。

再来看修改后的 tutorial.cxx :

// A simple program that computes the square root of a number
#include 
#include 
#include 
#include "TutorialConfig.h"
 
int main (int argc, char *argv[])
{
  if (argc < 2)
    {
    fprintf(stdout,"%s Version %d.%d\n",
            argv[0],
            Tutorial_VERSION_MAJOR,
            Tutorial_VERSION_MINOR);
    fprintf(stdout,"Usage: %s number\n",argv[0]);
    return 1;
    }
  double inputValue = atof(argv[1]);
  double outputValue = sqrt(inputValue);
  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

重新执行cmake试一下:

➜  Step1_1 cmake .
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/bairixin/Workspace/Test/CMake/Step1/Step1_1
➜  Step1_1 ls
CMakeCache.txt      CMakeLists.txt      TutorialConfig.h    cmake_install.cmake
CMakeFiles          Makefile            TutorialConfig.h.in tutorial.cxx

可以看到,已经生成了 TutorialConfig.h 这个文件。make一下:

➜  Step1_1 make
Scanning dependencies of target Tutorial
[ 50%] Building CXX object CMakeFiles/Tutorial.dir/tutorial.cxx.o
[100%] Linking CXX executable Tutorial
[100%] Built target Tutorial
➜  Step1_1 ./Tutorial
./Tutorial Version 1.0
Usage: ./Tutorial number

成功

你可能感兴趣的:(CMake教程 (一))