CMake使用教程二:CMake依赖外部库

1. 概述

此教程旨在说明通过CMake构建时,对外部库的处理方式,同时此教程会涉及以下主要点:

  1. 通过CMake定义C++的宏
  2. 子模块构建

2. 源码

目录结构:

.
├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cpp
├── TutorialConfig.h.in
└── tutorial.cpp
  1. tutorial.cpp

    // A simple program that computes the square root of a number
    #include <cmath>
    #include <iostream>
    #include <string>
    
    #include "TutorialConfig.h"
    
    // should we include the MathFunctions header?
    #ifdef USE_MYMATH
    #include "MathFunctions.h"
    #endif
    
    int main(int argc, char* argv[])
    {
      if (argc < 2) {
        // report version
        std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
                  << Tutorial_VERSION_MINOR << std::endl;
        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return 1;
      }
    
      // convert input to double
      const double inputValue = std::stod(argv[1]);
    
      // which square root function should we use?
    #ifdef USE_MYMATH
      const double outputValue = mysqrt(inputValue);
    #else
      const double outputValue = sqrt(inputValue);
    #endif
      std::cout << "The square root of " << inputValue << " is " << outputValue
                << std::endl;
    
      return 0;
    }
    
  2. TutorialConfig.h.in

    // the configured options and settings for Tutorial
    #define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
    #define Tutorial_VERSION_MINOR @Tutorial_VERSION_MINOR@
    #cmakedefine USE_MYMATH
    
  3. mysqrt.cpp

    #include <iostream>
    #include "MathFunctions.h"
    
    // a hack square root calculation using simple operations
    double mysqrt(double x)
    {
      if (x <= 0) {
        return 0;
      }
    
      double result = x;
    
      // do ten iterations
      for (int i = 0; i < 10; ++i) {
        if (result <= 0) {
          result = 0.1;
        }
        double delta = x - (result * result);
        result = result + 0.5 * delta / result;
        std::cout << "Computing sqrt of " << x << " to be " << result << std::endl;
      }
      return result;
    }
    
  4. MathFunctions.h

    double mysqrt(double x);
    

3. CMakeLists.txt

  1. ./CMakeLists.txt

    cmake_minimum_required(VERSION 3.10)
    
    # set the project name and version
    project(Tutorial VERSION 1.0)
    
    # specify the C++ standard
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_CXX_STANDARD_REQUIRED True)
    
    # should we use our own math functions
    # 类似于C语言中的宏条件编译,可以使TutorialConfig.h.in中的#cmakedefine USE_MYMATH生效,也可以通过 cmake -B ./bin -S ./ -DUSE_MYMATH=ON 方式使其生效
    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(TutorialConfig.h.in TutorialConfig.h)
    
    # add the MathFunctions library
    if(USE_MYMATH)
      # 添加子模块的构建
      add_subdirectory(MathFunctions)
      # 将要链接的库名添加到 EXTRA_LIBS 列表变量中
      list(APPEND EXTRA_LIBS MathFunctions)
      # 将头文件的包含目录添加到 EXTRA_INCLUDES 列表变量中
      list(APPEND EXTRA_INCLUDES "${PROJECT_SOURCE_DIR}/MathFunctions")
    endif()
    
    # add the executable
    add_executable(Tutorial tutorial.cpp)
    
    # 链接依赖库
    target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})
    
    # add the binary tree to the search path for include files
    # so that we will find TutorialConfig.h
    target_include_directories(Tutorial PUBLIC
                               "${PROJECT_BINARY_DIR}"
                               ${EXTRA_INCLUDES}
                               )
    
    
  2. ./MathFunctions/CMakeLists.txt

    add_library(MathFunctions mysqrt.cpp)
    

4. CMake文件解析

  • add_subdirectory(source_dir [binary_dir])
    向这个build中添加子目录
    source_dir指定源CMakeLists.txt和代码文件所在的目录,通常是一个相对路径也可以是绝对路径
    binary_dir指定输出文件的目录,若未设置,则输出到source_dir所在目录
  • #cmakedefine
    #cmakedefine的作用是通过CMake定义C++的宏,在configure_file()调用后,会将其进行替换。
    CMake中通过option(USE_MYMATH "Use tutorial provided math implementation" ON)进行设置,或在构建时指定cmake -B ./bin -S ./ -DUSE_MYMATH=ON,可以设置ONOFF

5. 优化

由于每个依赖MathFunctions的目标,都需要包含MathFunctions 的目录,所以最好可以在./MathFunctions/CMakeLists.txt将这个事情处理,这样依赖MathFunctions的目标就不需要进行其他处理。

  1. 修改./MathFunctions/CMakeLists.txt
add_library(MathFunctions mysqrt.cpp)

# INTERFACE 指定的是使用者(依赖此库的目标)需要的东西,因此其他使用者就不用额外添加这个库的包含目录
target_include_directories(MathFunctions INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
  1. 修改./CMakeLists.txt
cmake_minimum_required(VERSION 3.10)

# set the project name and version
project(Tutorial VERSION 1.0)

# specify the C++ standard
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

# should we use our own math functions
# 类似于C语言中的宏条件编译,可以使TutorialConfig.h.in中的#cmakedefine USE_MYMATH生效,也可以通过 cmake -B ./bin -S ./ -DUSE_MYMATH=ON 方式使其生效
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(TutorialConfig.h.in TutorialConfig.h)

# add the MathFunctions library
if(USE_MYMATH)
  # 添加子模块的构建
  add_subdirectory(MathFunctions)
  # 将要链接的库名添加到 EXTRA_LIBS 列表变量中
  list(APPEND EXTRA_LIBS MathFunctions)
endif()

# add the executable
add_executable(Tutorial tutorial.cpp)

# 链接依赖库
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})

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

6. 参考

  1. CMake Tutorial Step 2
  2. CMake Tutorial Step 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值