zoukankan      html  css  js  c++  java
  • 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
    ",argv[0]);
        return 1;
        }
      double inputValue = atof(argv[1]);
      double outputValue = sqrt(inputValue);
      fprintf(stdout,"The square root of %g is %g
    ",
              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
    ",
                argv[0],
                Tutorial_VERSION_MAJOR,
                Tutorial_VERSION_MINOR);
        fprintf(stdout,"Usage: %s number
    ",argv[0]);
        return 1;
        }
      double inputValue = atof(argv[1]);
      double outputValue = sqrt(inputValue);
      fprintf(stdout,"The square root of %g is %g
    ",
              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
    ", 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
    ",
                argv[0],
                Tutorial_VERSION_MAJOR,
                Tutorial_VERSION_MINOR);
        fprintf(stdout,"Usage: %s number
    ",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
    ",
              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
    
  • 相关阅读:
    MD5 Hashing in Java
    Caching in Presto
    ORC 文件存储格式
    Presto 性能优化点
    数据分页问题
    ES
    ES
    ES
    ES
    ES
  • 原文地址:https://www.cnblogs.com/brother-louie/p/13976572.html
Copyright © 2011-2022 走看看