【CMake】教程:第2步 添加库

2 篇文章 0 订阅

【CMake】教程:第2步 添加库

【问题】

当写的程序由多个模块组成,如何组织这些代码,以及如何利用模块代码生成的库呢?

【解答思路】

  1. 编写模块代码
  2. 将模块代码生成库
  3. 编写调用程序
  4. 编译链接模块库

以求一个数的平方根为例。

编写模块代码

MathFunctions.h
#ifndef __MATHFUNCTIONS_H__
#define __MATHFUNCTIONS_H__

// 求一个数的平方根
double mysqrt(double x);

#endif /* __MATHFUNCTIONS_H__ */

每个头文件需要加上 #ifndef ,以免重复添加头文件,造成重复声明。

mysqrt.cpp
#include <iostream>
#include "MathFunctions.h"

double mysqrt(double x)
{
    if (x <= 0)
    {
        return 0;
    }

    double result = x;

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

生成库

一个模块生成库,用 add_library 即可。

CMakeLists.txt
# 如果模块引用其他模块,应链接相应库
add_library(MathFunctions mysqrt.cpp)

调用程序

调用程序可能用c++自带的函数库也可以用模块库,可以用选择编译的方式进行调用;

tutorial.cpp
// 一个简单的计算平方根的程序
#include <cmath>
//#include <cstdlib> // when use c++11
#include <iostream>
#include <string>
#include "MathFunctions.h"
#include "TutorialConfig.h"

int main(int argc, char* argv[])
{
    // 打印版本号
    std::cout << argv[0] << " Version " << Tutorial_VERSION_MAJOR << "."
                << Tutorial_VERSION_MINOR << std::endl;

    if (argc < 2) {
        std::cout << "Usage: " << argv[0] << " number" << std::endl;
        return 1;
    }

    // 数据转换为 double
    // const double inputValue = atof(argv[1]);
    const double inputValue = std::stod(argv[1]);  // c++11

#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;

}

#ifdef USE_MYMATH 中的 USE_MYMATH 是在 CMakeLists.txt里定义的,然后通过 config 的方法将其配置到头文件 TutorialConfig.h中。

链接库

CMakeLists.txt

主CMakeLists.txt如下

cmake_minimum_required(VERSION 3.10)

# 设置项目名称
# project(Tutorial)
# 设置项目名称及版本号
project(Tutorial VERSION 1.1)

# 设置C++
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)

option(USE_MYMATH "Use tutorial provided math implementation" ON)

# 通过配置文件将版本号配置到程序中,当然也可以通过git的编号或版本号自动配置进去
# 当然也可以通过配置文件将其他的CMake参数配置到程序中,
# 例如一些不常改变的参数可以通过宏配置进去
configure_file(TutorialConfig.h.in TutorialConfig.h)

if (USE_MYMATH)
    add_subdirectory(MathFunctions)
    list(APPEND EXTRA_LIBS MathFunctions)
    list(APPEND EXTRA_INCS "${PROJECT_SOURCE_DIR}/MathFunctions")
endif(USE_MYMATH)


# 添加执行程序
add_executable(Tutorial tutorial.cpp)

# 添加链接库
target_link_libraries(Tutorial PUBLIC ${EXTRA_LIBS})


# 添加头文件
target_include_directories(Tutorial PUBLIC 
                        "${PROJECT_BINARY_DIR}" 
                        ${EXTRA_INCS}
                        )

option 指令可以将某些变量设置成开关量,可以根据开关量进行编译。
如果 option 里设置为 ON,在例子中实际就是将 USE_MYMATH 设置为 True

add_subdirectory: 将包含子目录,进入子目录后会查找内部的 CMakeLists.txt 继续执行。

target_link_libraries: 添加链接库,除了自己编译的模块,也可以链接其他开源库等。

target_include_directories: 添加目标的链接目录。

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

如果 USE_MYMATH 在编译的时候指定为 ON,则 #cmakedefine USE_MYMATH配置后变成 #define USE_MYMATH

#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@@...@部分替换成 CMakeLists.txt里定义的值,如本例中为 1

【汇总】

## 目录结构如下
.
├── build
├── CMakeLists.txt
├── MathFunctions
│   ├── CMakeLists.txt
│   ├── MathFunctions.h
│   └── mysqrt.cpp
├── TutorialConfig.h.in
└── tutorial.cpp
mkdir build && cd build
cmake ..
make 
./Tutorial 100
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

黄金旺铺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值