CMake 七步入门

前言

CMake是什么? 官网给出的定义是这样的:”an open-source, cross-platform family of tools designed to build, test and package software”。很容易理解它是一个编译工具,是一个测试工具,也是一个打包工具,它其实就是一个工具箱,可以完成编译,测试以及打包的工作。在使用OpenCV的时候,已经对CMake有了认识。
CMake是跨平台的,这里就win7系统下结合Visual Studio的使用给出一点说明,本文主要内容是基于官方的使用文档,个人认为,官方的文档一直是学习新知识的第一手资料。


Step 1 基础

最简单的应用就是直接利用源码文件来编译可执行程序,利用有这样一份源码,计算一个数的平方根。文件名为tutorial.cpp,代码如下

#tutorial.cpp
// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
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;
}

这里生成一个简单的VS工程,只需要给出一个有2行命令的CMakeLists.txt文件,文件内容是这样的:

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

利用上面CMakeLists文件,可以生成一个名为Tutorial的工程文件。

假设你已安装好CMake程序,并且版本号是2.6以上的。打开CMake,按如图界面操作:
step1

其中源文件路径就是放置上述Tutorial.cpp以及CMakeLists.txt文件的位置,编译路径是一个空目录。配置编译器时,会提示创建build文件夹,点击确定。编译器的配置如图,根据实际情况选择,这里选择VS2010。
step1

点击Generate,生成工程文件,如图:
step1

编译运行结果:
step1

针对上述这样一个简单的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}/config.h.in"
        "${PROJECT_BINARY_DIR}/config.h"
    )

   # add the binary tree to the search path for include files
   # so that we will find config.h
   include_directories("${PROJECT_BINARY_DIR}")

   # add the executable
   add_executable(Tutorial tutorial.cpp)

接着,我们在源文件路径下创建一个文件config.h.in,内容为:

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

当CMake配置congfig.h文件时,@Tutorial_VERSION_MAJOR@以及
@Tutorial_VERSION_MINOR@的值就会被替换成CMakeLists.txt中设置的值。
最后,我们修改tutorial.cpp,添加包含配置头文件,并使用版本号变量。

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#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;
}

编译运行结果如图:
step1


step 2 添加依赖库

这里为工程添加一个依赖库,这个库的功能就是计算一个数的平方根。首先,在源文件路径下新建一个子目录MathFunc,定义使用的库函数:头文件MathFunc.h,源文件mysqrt.cpp以及CMakeLists.txt。

//MathFunc.h
double mysqrt(double x);
//mysqrt.cpp
#include "MathFunc.h"
#include <stdio.h>
// a hack square root calculation using simple operations
double mysqrt(double x)
{
  if (x <= 0) {
    return 0;
  }
  double result;
  double delta;
  result = x;
  // do ten iterations
  int i;
  for (i = 0; i < 10; ++i) {
    if (result <= 0) {
      result = 0.1;
    }
    delta = x - (result * result);
    result = result + 0.5 * delta / result;
    fprintf(stdout, "Computing sqrt of %g to be %g\n", x, result);
  }
  return result;
}
CMakeLists.txt
add_library(MathFunc mysqrt.cpp)

接下来,修改主目录(源文件路径)下的CMakeLists.txt,让主工程能够调用子目录下的库函数,同时,添加一个可选项,可以选择是否使用该库函数。修改如下:

cmake_minimum_required (VERSION 2.6)
project (Tutorial)
# The version number.
set (Tutorial_VERSION_MAJOR 1)
set (Tutorial_VERSION_MINOR 0)
# should we use our own math functions
option(USE_MYMATH "Use tutorial provided math implementation" ON)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
  "${PROJECT_SOURCE_DIR}/config.h.in"
    "${PROJECT_BINARY_DIR}/config.h"
 )
# add the binary tree to the search path for include files
# so that we will find config.h
include_directories ("${PROJECT_BINARY_DIR}")
# add the MathFunc library?
if (USE_MYMATH)
  include_directories ("${PROJECT_SOURCE_DIR}/MathFunc")
  add_subdirectory (MathFunc)
  set (EXTRA_LIBS ${EXTRA_LIBS} MathFunc)
endif ()
# add the executable
add_executable (Tutorial tutorial.cpp)
target_link_libraries (Tutorial  ${EXTRA_LIBS})

修改主函数代码,如下:

// A simple program that computes the square root of a number
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "config.h"

#ifdef USE_MYMATH
#include "MathFunc.h"
#endif

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]);

  #ifdef USE_MYMATH
  double outputValue = mysqrt(inputValue);
  #else
  double outputValue = sqrt(inputValue);
  #endif

  fprintf(stdout,"The square root of %g is %g\n",
          inputValue, outputValue);
  return 0;
}

最后,修改配置文件config.h.in,在文件末尾添加如下一行内容:

  #cmakedefine USE_MYMATH

编译运行结果如图:
step3


step 3 安装与测试

这里将在CMakeLists文件中添加安装规则与测试支持命令。
首先在子目录MathFunc中的CMakeLists.txt添加如下安装指令:

 install (TARGETS MathFunc DESTINATION bin)
 install (FILES MathFunc.h DESTINATION include)

然后修改主目录下CMakeLists.txt末尾添加如下内容:

 # add the install targets
 install (TARGETS Tutorial DESTINATION bin)
 install (FILES "${PROJECT_BINARY_DIR}/config.h"        
     DESTINATION include)

在CMake界面中可以设置安装路径,如图:
step3

在VS工程中可看到安装选项,右击生成即可将项目文件安装到指定目录。
step3

在主目录下的CMakeLists.txt结尾可加入测试用例,验证程序是否能正常运行。

  include(CTest)
  #define a macro to simplify adding tests, then use it
  macro (do_test arg result)
    add_test (TutorialComp${arg} Tutorial ${arg})
    set_tests_properties (TutorialComp${arg}
    PROPERTIES PASS_REGULAR_EXPRESSION ${result})
 endmacro (do_test)

 # do a bunch of result based tests
 do_test (25 "25 is 5")
 do_test (-25 "-25 is 0")

 # does it handle negative numbers
 add_test (TutorialNegative Tutorial -25)
 set_tests_properties (TutorialNegative PROPERTIES 
 ASS_REGULAR_EXPRESSION "-25 is 0")

 # does it handle small numbers
 add_test (TutorialSmall Tutorial 0.0001)
 set_tests_properties (TutorialSmall PROPERTIES 
 ASS_REGULAR_EXPRESSION "0.0001 is 0.01")

 # does the usage message work?
 add_test (TutorialUsage Tutorial)
 set_tests_properties (TutorialUsage PROPERTIES 

测试结果:
step3


step 4-7

至此,CMake的应用有了初步了解和认识。CMake还有其他的功能与特性有待了解,比如CheckFunctionExists.cmake 宏的使用,Generated File and Generator的使用,生成安装包文件等等。具体内容可参考这里

                                                Unicorn Lewis, 04.08.2017
posted @ 2017-04-08 14:30  Louie-Liu  阅读(116)  评论(0编辑  收藏  举报