0
点赞
收藏
分享

微信扫一扫

从零开始 CMake 学习笔记 (C)static-library

勇敢的趙迦禾 2022-04-19 阅读 89
c++cmake

从零开始 CMake 学习笔记 (C)static-library

开始前先默念三遍口诀:

  • Declare a target
  • Declare target’s traits
  • It’s all about targets
    本系列主要根据GitHub上的 cmake-examples 项目进行翻译总结,同时对于不清晰的概念及函数进行查阅理解记录形成。

文章目录

1 介绍

显示了一个 hello world 示例,它首先创建并链接了一个静态库。同上一节类似,使用不同的文件夹来作为源文件和include文件。整体的文件架构如下所示:

1.1 文件树

1.2 文件简介

  • CMakeLists.txt - 包含了你希望运行的 CMake 命令
cmake_minimum_required(VERSION 3.5)

project(hello_library)

############################################################
//创建一个库
############################################################

//从库源文件生成一个静态库
add_library(hello_library STATIC 
    src/Hello.cpp
)

target_include_directories(hello_library
    PUBLIC 
        ${PROJECT_SOURCE_DIR}/include
)


############################################################
// 创建一个可执行对象
############################################################

// 添加可执行文件
add_executable(hello_binary 
    src/main.cpp
)

# 将新创建的静态库 hello_library 链接到新的要生成的 hello_binary 目标
target_link_libraries( hello_binary
    PRIVATE 
        hello_library
)
  • include/static/Hello.h - 要包含的头文件,会生成一个静态库链接
#ifndef __HELLO_H__
#define __HELLO_H__

class Hello
{
public:
    void print();
};

#endif
  • src/Hello.cpp - 要编译的源文件
#include <iostream>

#include "static/Hello.h"

void Hello::print()
{
    std::cout << "Hello Static Library!" << std::endl;
}
  • src/main.cpp - main 文件
#include "static/Hello.h"

int main(int argc, char *argv[])
{
    Hello hi;
    hi.print();
    return 0;
}

2 概念解析

2.1 添加静态库

add_library() 函数用于从一些源文件创建库,调用方法如下:

add_library(hello_library STATIC
    src/Hello.cpp
)

上面这句命令将基于 Hello.cpp 源文件创建一个名为 hello_library的静态库。
注意:
在上面这句命令中,我们直接将源文件传递给了 add_library() 函数调用,而没有像上一节从零开始 CMake 学习笔记 (B)hello-headers中创建 SOURCES 源变量。现代CMake,鼓励直接传递源文件给 add_library() 函数这种方式。

2.2 添加include路径

在此示例中,使用 target_include_directories() 函数将用到的头文件包含在库中,并将范围设置为 PUBLIC

target_include_directories(hello_library
    PUBLIC
        ${PROJECT_SOURCE_DIR}/include
)

使用这句命令后,在接下来这些情况会包含头文件的路径:

  • 在编译 hello_library 这个静态库的时候;
  • 在编译任何链接到 hello_library 这个静态库的其他库的时候,比如后面的 hello_binary库的时候。

2.2.1 拓展 - target_include_directories() 方法

target_include_directories()该函数用于指定包含的头文件的目录。与这个函数相似的函数有 target_link_libraries()target_compile_options()这两个,这里以 target_include_directories()函数来分析其方法,该函数的所有参数为:

target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
  <INTERFACE|PUBLIC|PRIVATE> [items1...]
  [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])

该函数参数中的 targetadd_executable()add_library()等命令创建生成,同时不能是一个 ALIAS 目标(即使用ALIAS重命名的目标)。

//TODO
通过显式使用 AFTERBEFORE ,可以独立于默认值在追加和前置之间进行选择。目前还没有碰到合适的案例来分析,这里后面再补充。

//TODO
SYSTEM目前也没搞明白。

INTERFACE PUBLICPRIVATE 关键字来指定以下参数的范围。而范围的含义为:

  • PRIVATE - 跟在该参数后面的目录(如上面的${PROJECT_SOURCE_DIR}/include) 仅会被添加到正在构建的这个目标(如上面的hello_library)的 include 目录中。
  • INTERFACE - 该目录将添加到在编译任何链接到 hello_library 这个静态库的其他库的 include 目录中。
  • PUBLIC - 既包含在此库的 include 目录中,也包含任何链接到 hello_library 这个静态库的其他库的 include 目录中。
    //TODO
    这里有待补充!

2.3 链接库

当创建一个可执行文件时,你必须告诉编译器有关这个库的信息。例如本例中,我们要通过 main.cpp 来编译生成一个 hello_binary的库,而在 main.cpp 中包含了静态库中的 Hello 对象,那么我们就通过 target_link_libraries() 这个函数把这些信息告诉它。

add_executable(hello_binary
    src/main.cpp
)

target_link_libraries( hello_binary
    PRIVATE
        hello_library
)

创建将使用您的库的可执行文件时,您必须告诉编译器有关该库的信息。这可以使用 target_link_libraries() 函数来完成。

3 运行结果

构建此示例的标准输出如下所示:

C-static-library$ mkdir build

C-static-library$ cd build

C-static-library$ cmake ..
-- The C compiler identification is GNU 9.4.0
-- The CXX compiler identification is GNU 9.4.0
-- Check for working C compiler: /usr/bin/cc
-- Balabala...
-- Balabala...

C-static-library$ make
Scanning dependencies of target hello_library
[ 50%] Building CXX object CMakeFiles/hello_library.dir/src/Hello.cpp.o
Linking CXX static library libhello_library.a
[ 50%] Built target hello_library
Scanning dependencies of target hello_binary
[100%] Building CXX object CMakeFiles/hello_binary.dir/src/main.cpp.o
Linking CXX executable hello_binary
[100%] Built target hello_binary

C-static-library$ ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  hello_binary  libhello_library.a  Makefile

C-static-library$ ./hello_binary
Hello Static Library!

后记:
从上面这个例子中我们就可以体会到前面的口诀:1. Declare a target、 2. Declare target’s traits ,在CMake中,我们先写创建这个库的语句,然后再补充这个库要用到的依赖等。

举报

相关推荐

0 条评论