构建和链接静态库和动态库

前提

准备三个文件

1
2
3
4
5
6
7
8
9
10
11
//main.cpp
#include "Message.hpp"
#include <cstdlib>
#include <iostream>
int main() {
Message say_hello("Hello, CMake World!");
std::cout << say_hello << std::endl;
Message say_goodbye("Goodbye, CMake World");
std::cout << say_goodbye << std::endl;
return EXIT_SUCCESS;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//Message.hpp
#pragma once
#include <iosfwd>
#include <string>
class Message {
public:
Message(const std::string &m) : message_(m) {}
friend std::ostream &operator<<(std::ostream &os, Message &obj) {
return obj.printObject(os);
}
private:
std::string message_;
std::ostream &printObject(std::ostream &os);
};
1
2
3
4
5
6
7
8
9
//Message.cpp
#include "Message.hpp"
#include <iostream>
#include <string>
std::ostream &Message::printObject(std::ostream &os) {
os << "This is my very nice message: " << std::endl;
os << message_;
return os;
}

CMake构建和链接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#最低CMake版本
cmake_minimum_required(VERSION 3.5)

#项目信息
project(project4 LANGUAGES CXX)

#
set(USE_LIBRARY YES)
message(STATUS "Compile sources into a library? ${USE_LIBRARY}")

#
set(BUILD_SHARED_LIBS NO)

list(APPEND _sources Message.hpp Message.cpp)

if(USE_LIBRARY)
add_library(message ${_sources})
add_executable(wang4 main.cpp)
target_link_libraries(wang4 message)
else()
add_executable(wang5 main.cpp ${_sources})
endif()

CMake接受其他值作为add_library的第二个参数的有效值,我们来看下本书会用到的值:

  • STATIC:用于创建静态库,即编译文件的打包存档,以便在链接其他目标时使用,例如:可执行文件。
  • SHARED:用于创建动态库,即可以动态链接,并在运行时加载的库。可以在CMakeLists.txt中使用add_library(message SHARED Message.hpp Message.cpp)从静态库切换到动态共享对象(DSO)。
  • OBJECT:可将给定add_library的列表中的源码编译到目标文件,不将它们归档到静态库中,也不能将它们链接到共享对象中。如果需要一次性创建静态库和动态库,那么使用对象库尤其有用。我们将在本示例中演示。
  • MODULE:又为DSO组。与SHARED库不同,它们不链接到项目中的任何目标,不过可以进行动态加载。该参数可以用于构建运行时插件。

CMake还能够生成特殊类型的库,这不会在构建系统中产生输出,但是对于组织目标之间的依赖关系,和构建需求非常有用:

  • IMPORTED:此类库目标表示位于项目外部的库。此类库的主要用途是,对现有依赖项进行构建。因此,IMPORTED库将被视为不可变的。我们将在本书的其他章节演示使用IMPORTED库的示例。
  • INTERFACE:与IMPORTED库类似。不过,该类型库可变,没有位置信息。它主要用于项目之外的目标构建使用。我们将在本章第5节中演示INTERFACE库的示例。
  • ALIAS:顾名思义,这种库为项目中已存在的库目标定义别名。不过,不能为IMPORTED库选择别名。

说明

经过编译和链接测试,CMake的 add_library() 的第一个参数为库名称,第二个参数默认为 STATIC ,即默认会构建成静态链接库。