美文网首页
Cmake用例

Cmake用例

作者: Tony__Ren | 来源:发表于2019-04-01 13:25 被阅读0次
    //查看目录结构命令,1表示只看一层结构
    tree -L 1
    

    1.cmake 基础构成

    //cmake最小版本
    cmake_minimum_required (VERSION 2.6)
    //工程名
    project (Tutorial)
    //生成可执行文件
    add_executable(Tutorial tutorial.cxx)
    

    2.添加子项目

    //生成库文件
    add_library(MathFunctions mysqrt.cxx)
    
    //添加目录
    include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
    //添加子项目
    add_subdirectory (MathFunctions) 
    add_executable (Tutorial tutorial.cxx)
    //连接子项目
    target_link_libraries (Tutorial MathFunctions)
    
    .
    ├── CMakeLists.txt
    ├── MathFunctions
    │   ├── CMakeLists.txt
    │   ├── MathFunctions.h
    │   └── mysqrt.cxx
    ├── TutorialConfig.h.in
    └── tutorial.cxx
    

    3.添加开关

    根目录下CMakeLists.txt文件中添加

    # should we use our own math functions?
    option (USE_MYMATH  "Use tutorial provided math implementation" ON)
    

    子目录下CMakeLists.txt文件中添加

    # add the MathFunctions library?
    #
    if (USE_MYMATH)
      include_directories ("${PROJECT_SOURCE_DIR}/MathFunctions")
      add_subdirectory (MathFunctions)
      set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
    endif (USE_MYMATH)
     
    # add the executable
    add_executable (Tutorial tutorial.cxx)
    target_link_libraries (Tutorial  ${EXTRA_LIBS})
    

    这将使用USE_MYMATH的设置来确定是否应该编译和使用mathfunction库。注意,使用一个变量(在本例中是EXTRA_LIBS)来设置可选的库,然后将它们链接到可执行文件中。这是一种常见的方法,用于保持较大的项目具有许多可选组件。
    首先在Configure.h.in文件中添加以下内容:

    #cmakedefine USE_MYMATH
    

    然后我们就可以使用USE_MYMATH这个变量了,最后修改Tutorial.cxx源代码如下:

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

    3.安装

    对于mathfunction库,我们添加了这个库,通过将以下两行添加到mathfunction的CMakeLists.txt中来安装头文件和静态库:

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

    然后根目录下的CMakeLusts.txt文件中添加如下行,用来安装可执行文件和配置文件:

    # add the install targets
    install (TARGETS Tutorial DESTINATION bin)
    install (FILES "${PROJECT_BINARY_DIR}/TutorialConfig.h DESTINATION include)
    
    //编译安装
    cmake .
    make
    make install
    

    注意上边install的第一个参数和第三个参数。
    TARGETS包含六种形式:ARCHIVE, LIBRARY, RUNTIME, OBJECTS, FRAMEWORK, BUNDLE。注意Mathfunction安装的是LIBRARY,而根目录下的可执行文件是RUNTIME类型。
    FILE 将给定的文件复制到指定目录。如果没有给定权限参数,则由该表单安装的文件默认为OWNER_WRITE、OWNER_READ、GROUP_READ和WORLD_READ。
    TARGETS和FILE可指定为相对目录和绝对目录。
    DESTINATION在这里是一个相对路径,取默认值。在unix系统中指向 /usr/local 在windows上c:/Program Files/${PROJECT_NAME}。
    也可以通过设置CMAKE_INSTALL_PREFIX这个变量来设置安装的路径,那么安装位置不指向/usr/local,而指向你所指定的目录。

    文件/库 安装位置
    MathFunctions /usr/local/bin/
    MathFunctions.h /usr/local/include/
    Tutorial /usr/local/bin/
    TutorialConfig.h /usr/local/include

    4.测试

    # 启用测试
    enable_testing()
    # 测试程序是否成功运行
    add_test (test_run Demo 5 2)
    # 测试帮助信息是否可以正常提示
    add_test (test_usage Demo)
    set_tests_properties (test_usage
      PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
    # 测试 5 的平方
    add_test (test_5_2 Demo 5 2)
    set_tests_properties (test_5_2
     PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
    # 测试 10 的 5 次方
    add_test (test_10_5 Demo 10 5)
    set_tests_properties (test_10_5
     PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")
    # 测试 2 的 10 次方
    add_test (test_2_10 Demo 2 10)
    set_tests_properties (test_2_10
    PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")
    

    5.文件生成器

    5.1文件生成代码MakeTable.c

    // A simple program that builds a sqrt table 
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
     
    int main (int argc, char *argv[])
    {
      int i;
      double result;
     
      // make sure we have enough arguments
      if (argc < 2)
        {
        return 1;
        }
      
      // open the output file
      FILE *fout = fopen(argv[1],"w");
      if (!fout)
        {
        return 1;
        }
      
      // create a source file with a table of square roots
      fprintf(fout,"double sqrtTable[] = {\n");
      for (i = 0; i < 10; ++i)
        {
        result = sqrt(static_cast<double>(i));
        fprintf(fout,"%g,\n",result);
        }
     
      // close the table with a zero
      fprintf(fout,"0};\n");
      fclose(fout);
      return 0;
    }
    

    5.2

    add_custom_command的第二个参数COMMAND,相当于执行MakeTable并传入参数${CMAKE_CURRENT_BINARY_DIR}/Table.h。
    首先构建MakeTable可执行文件。然后它将运行MakeTable命令生成Table.h文件。最后,它将编译mysqrt.cxx和table.h生成mathfunction库。

    # first we add the executable that generates the table
    add_executable(MakeTable MakeTable.cxx)
    # add the command to generate the source code
    add_custom_command (
      OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Table.h
      DEPENDS MakeTable
      COMMAND MakeTable ${CMAKE_CURRENT_BINARY_DIR}/Table.h
      )
    # add the binary tree directory to the search path 
    # for include files
    include_directories( ${CMAKE_CURRENT_BINARY_DIR} )
     
    # add the main library
    add_library(MathFunctions mysqrt.cxx ${CMAKE_CURRENT_BINARY_DIR}/Table.h)
     
    install (TARGETS MathFunctions DESTINATION bin)
    install (FILES MathFunctions.h DESTINATION include)
    
    

    6.程序中使用Cmake的配置信息

    6.1添加版本配置

    # The version number.
    # 添加配置key,value
    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)
    

    配置文件将会被写入到可执行文件目录下,所以我们的项目必须包含这个文件夹来使用这些配置头文件。我们需要在工程目录下新建一个TutorialConfig.h.in,内容如下:

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

    上面的代码中的@Tutorial_VERSION_MAJOR@和@Tutorial_VERSION_MINOR@将会被替换为CmakeLists.txt中的1和0。 然后修改Tutorial.cxx文件如下,用来在不输入额外参数的情况下输出版本信息:

    // 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;
    }
    

    6.2测试这些函数的是否存在

    # does this system provide the log and exp functions?
    include (CheckFunctionExists)
    check_function_exists (log HAVE_LOG)
    check_function_exists (exp HAVE_EXP)
    

    然后在TutorialConfig.h.in中添加使用上边定义的变量的代码:

    // does the platform provide exp and log functions?
    #cmakedefine HAVE_LOG
    #cmakedefine HAVE_EXP
    

    log和exp的测试代码一定要在TutorialConfig.h的configure_file命令之前。configure.file命令会立即使用CMake中的当前设置配置文件。最后,在mysqrt函数中,我们可以提供一个基于log和exp的替代实现,如果它们在系统上可用以下代码可用:

    // if we have both log and exp then use them
    #if defined (HAVE_LOG) && defined (HAVE_EXP)
      result = exp(log(x)*0.5);
    #else // otherwise use an iterative approach
      ...
    

    7.cpack生成安装包

    需要在根目录CMakeLists.txt的底部添加几行代码:

    # build a CPack driven installer package
    include (InstallRequiredSystemLibraries)
    set (CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
    set (CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
    set (CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
    include (CPack)
    

    首先要加入InstallRequiredSystemLibraries。这个模块将包括当前平台项目所需要的任何运行时库。接下来,我们将一些CPack变量,如该项目的许可和版本信息。最后,我们将加入CPack模块,它将使用刚才定义的变量变量和系统的一些其他属性来设置安装程序。
    两个生成的文件CPackConfig.cmake,CPackSourceConfig.cmake。

    //CPackConfig.cmake生成二进制版本
    cpack --config CPackConfig.cmake
    //CPackSourceConfig.cmake生成源码版本
    cpack --config CPackSourceConfig.cmake
    

    相关文章

      网友评论

          本文标题:Cmake用例

          本文链接:https://www.haomeiwen.com/subject/xdembqtx.html