学习使用cmake 生成及使用库,使用cmake 生成 .lib 静态库 及动态库(.dll)。及linux 下使用的静态库 .a 和 动态库(.so, 也称为共享库)
目录
使用工具
生成库(导入库)
add_library()
生成静态库(Windows)
使用 vs 2019 生成静态库
使用Clion 生成静态库(windows .lib)
使用静态库(Windows)
方式一:使用 link_libraries()
使用 target_link_libraries()
使用全路径
使用 link_directories + target_link_libraries
引入头文件(include_directories)不与不引入头文件
error LNK2019:
静态库(.a) 的使用
仅不同是使用 link_directories + target_link_libraries
动态链接库
使用mingw与cmake 生成 .dll
生成共享库
共享库的使用
aux_source_directory 的使用
aux_source_directory 引用文件
aux_source_directory 生成库
开发工具:clion、cmake
平台: win
add_library 除了生成导入库,还可生成对象库,接口库等
使用 cmake CMakeList.txt
项目结构:
声明库函数 .h
#pragma once
double mySqrt(double x);
定义库函数 .cpp
#include "myMathSquare.h"
double mySqrt(double x)
{
return (x * x);
}
CMakeLists.txt
# CMakeList.txt: MyLibraryTest 的 CMake 项目,在此处包括源代码并定义
# 项目特定的逻辑。
#
#注意:cmake的语法支持大小、小写和大小写混合上边的代码中我们使用的cmake语法是小写的.
cmake_minimum_required (VERSION 3.8)
project ("MyLibraryTest")
# 设置系统自带变量
set(cmake_cxx_standard 11)
set(myHeadPath "${CMAKE_CURRENT_SOURCE_DIR}/header")
include_directories(${myHeadPath})
add_library(MyMathFunctions STATIC ./source/myMathSquare.cpp)
# TODO: 如有需要,请添加测试并安装目标。
add_library(
[EXCLUDE_FROM_ALL]
[source1] [source2] [...])
添加名为target_sources()
后续指定
生成的library名会根据STATIC
或SHARED及 生成平台
成为name.a/name.lib 或 name.so/.dll
windows下,如果dll没有export任何信息,则不能使用SHARED
,要标识为MODULE
MODULE: 在使用 dyId 的系统有效,如果不支持dyid, 则被当做shared对待
EXCLUDE_FROM_ALL: 这个库不会被默认构建,除非有其他的组件或者手工构建
开始尝试使用 vs 2019 建立的 cmake 项目生成 静态库。一直未找到生成入口。(生成windows 静态库仅仅只是想尝试使用 cmake生成 .lib 静态库, 更简单的方式是 vs .sln 解决方案中直接设置,或直接新建 生成静态库解决方案)。
偶然终于找到怎么生成 使用 cmake 生成解决方案。然运行解决方案生成 库。
项目右键 打开终端
使用 cmake 生成解决方案
j命令: cmake .
结果:
打开解决方案:
生成:
如果用此种方式生成动态库 貌似 只生成dll,不生成调用 dll 所需的静态库
修改:add_library(MyMathFunctions SHARED ./source/myMathSquare.cpp)
其他步骤一致
打开项目文件夹
设置 Clion 中的 visual studio 环境
打开设置:
新增工具链
改为 64 位
新增cmake 环境
选择debug 或者 release
查看文件夹下 是否出现 visual studio 相应的文件夹
如果没有 打开 cmake reset 或 刷新
选择相应环境 构建
新建一个调用文件 xxx.cpp
#include
using namespace std;
extern double mySqrt(double x);
extern void hello();
void customLibTest() {
double x = 8;
double res = mySqrt(x);
cout << "输入x: " << x << "的平方是" << res << endl;
}
int main()
{
#ifdef MyDebug
cout << "获取版本:" << cPlusPlusTest_version_major << endl;
#else
cout << "获取版本: " << cPlusPlusTest_version_minor << endl;
#endif // DEBUG
customLibTest();
hello();
return 0;
}
link_libraries(${PROJECT_SOURCE_DIR}/3dPart/lib/MyMathFunctions.lib) #使用link_libraries链接MyMathFunctions.lib
运行结果:
target_link_libraries:指定目标链接的库
target_link_directories: 指定目标包含的头文件路径
target_compile_options:指定目标编译选项
target_link_libraries(
- ...
[
- ...]...)
可以链接多个库: 例如:
target_link_libraries(cPlusPlusTestProject ${PROJECT_SOURCE_DIR}/3dPart/lib/MyMathFunctions.lib ${PROJECT_SOURCE_DIR}/3dPart/lib/LibTest.lib)
target_link_libraries(target target1 target2)
target_link_libraries(target3 target target4)
PUBLI:表示target能够使用target1&target2库中的内容,target3 能够使用target1 & target2中定义的内容;默认状态为PUBLIC;
PRIVATE:表示target能够使用target1&target2库中的内容,target3不能使用target1&target2中定义的内容,只能使用target中定义的内容;
INTERFACE:表示target无法使用target1&target2的内容,但是target3 能够使用target1 & target2;
target_link_libraries(cPlusPlusTestProject ${PROJECT_SOURCE_DIR}/3dPart/lib/MyMathFunctions.lib)
link_directories(../3dPart/lib)
target_link_libraries(cPlusPlusTestProject MyMathFunctions)#直接写库的名称
结果:
使用 extern 上述代码不引入头文件 使用 extern 声明
引入头文件:
#include
#include "myMathSquare.h"
using namespace std;
extern void hello();
void customLibTest() {
double x = 8;
double res = mySqrt(x);
cout << "输入x: " << x << "的平方是" << res << endl;
}
int main()
{
#ifdef MyDebug
cout << "获取版本:" << cPlusPlusTest_version_major << endl;
#else
cout << "获取版本: " << cPlusPlusTest_version_minor << endl;
#endif // DEBUG
customLibTest();
hello();
return 0;
}
例如:
无法解析的外部符号 "double __cdecl mySqrt(double)"
遇到的坑,把 .a 当成 .lib 用了
.a 库的使用与 .lib 相差无几。
使用全路径是与 lib 相同(使用库的全名):例如:
target_link_libraries(cPlusPlusTestProject ${PROJECT_SOURCE_DIR}/3dPart/lib/libMyMathFunctions.a)
需要注意的是,生成的.a 有前缀 lib. 例如: libxxxx.a, 去掉前缀使用 例如:
link_directories(${PROJECT_SOURCE_DIR}/3dPart/lib)
target_link_libraries(cPlusPlusTestProject MyMathFunctions)
使用 mingw 与 cmake 生成的是 xxx.dll 与 xxx.dll.a
修改生成库类型:
add_library(MyMathFunctions SHARED ./source/myMathSquare.cpp)
选择配置好的 winGW 环境
生成 动态库 .dll 及静态库 .dll.a
Linux 动态链接库,共享库只生成 .so
将共享库复制第第三方库中,同时复制头文件:如
sharedLibTest.h
//
// Created by ly on 2022/7/21.
//
#ifndef SHAREDLIBTEST_SHAREDLIBTEST_H
#define SHAREDLIBTEST_SHAREDLIBTEST_H
void test();
#endif //SHAREDLIBTEST_SHAREDLIBTEST_H
sharedLibTest.cpp
//
// Created by ly on 2022/7/21.
//
#include
#include "sharedLibTest.h"
#include "myMathSquare.h"
void test(){
double x = 8;
double d = mySqrt(x);
std::cout << "x 的平方是: " << d << std::endl;
}
main.cpp
#include
#include "sharedLibTest.h"
int main() {
std::cout << "Hello, World!" << std::endl;
test();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
project(sharedLibTest)
set(CMAKE_CXX_STANDARD 11)
include_directories(${PROJECT_SOURCE_DIR}/3dPart/include)
include_directories(${PROJECT_SOURCE_DIR}/header)
#link_directories(3dPart/lib)
link_directories(${PROJECT_SOURCE_DIR}/3dPart/lib)
add_executable(sharedLibTest
header/sharedLibTest.h
source/sharedLibTest.cpp
main.cpp)
target_link_libraries(sharedLibTest libMyMathFunctions.so)
方式1:target_link_libraries(testAuxSource MyMathFunctions)
方式2:target_link_libraries(testAuxSource libMyMathFunctions.so)
#target_link_libraries(testAuxSource MyMathFunctions)# 共享库可以调用全名,也可以调用项目名称
运行结果:
在目录中查找所有源文件。
收集指定目录中所有源文件的名称,并将列表存储在提供的变量中。即将某目录下的所有的源码文件设定一个变量名称,便于后期使用变量名代替所有的源码文件,比如与add_library生成静态库一并使用,以便指定子构建系统的构建的库类型和名称。
例如:一个文件夹包含所有头文件,源文件。
aux_source_directory(. DIR_SR)
add_executable(testAuxSource ${DIR_SR})
文件目录
当头文件和源文件不在同一个目录时:
文件目录:
cmakelist.txt 文件内容:
cmake_minimum_required(VERSION 3.17) project(sharedLibTest) set(CMAKE_CXX_STANDARD 11) include_directories(${PROJECT_SOURCE_DIR}/3dPart/include) include_directories(${PROJECT_SOURCE_DIR}/header) #link_directories(3dPart/lib) link_directories(${PROJECT_SOURCE_DIR}/3dPart/lib) aux_source_directory(${PROJECT_SOURCE_DIR}/header/ DIR_SR) aux_source_directory(${PROJECT_SOURCE_DIR}/source/ DIR_SRS) aux_source_directory(. DIR_SRS_MAIN) #add_executable(sharedLibTest # header/sharedLibTest.h # source/sharedLibTest.cpp # main.cpp) SET (MyCode ${DIR_SR} ${DIR_SRS} ${DIR_SRS_MAIN}) #add_executable(sharedLibTest ${DIR_SR} ${DIR_SRS} ${DIR_SRS_MAIN}) add_executable(sharedLibTest ${MyCode}) target_link_libraries(sharedLibTest libMyMathFunctions.so)
运行结果:
思考: 是否可以将头文件一起生存到库中?
aux_source_directory(. DIR_LIB_SRC)
add_library(MyMathFunctions SHARED ${DIR_LIB_SRC})
生成库的其它步骤不变