已知
库函数的源文件名字叫hello.c,库函数的头文件名字叫hello.h,生成的动态链接库函数的名称叫libhello.so,目标是在/hello/install文件夹下安装这个库,以便后来调用。设库函数源文件在/home/hello/libhello目录,编译生成的中间文件夹在/home/hello/build
生成库
文件夹结构如下
编辑文件
在libhello文件夹下编辑hello.cpp文件
#include "hello.h"
#include <iostream>
void hello(){
std::cout << "Hello, sososs!" << std::endl;
}
和hello.h头文件
#ifndef HELLO_HELLO_H
#define HELLO_HELLO_H
void hello();
#endif //HELLO_HELLO_H
使用cmake编译和安装
在/home/hello/CMakeLists.txt,添加以下内容
# cmake至少3.16以上
cmake_minimum_required(VERSION 3.16)
# 工程名叫做hello
project(hello)
# cpp 14
set(CMAKE_CXX_STANDARD 14)
add_library(hello SHARED ${PROJECT_SOURCE_DIR}/libhello/hello.cpp)
install(TARGETS hello LIBRARY DESTINATION lib)
其中
add_library(hello SHARED ${PROJECT_SOURCE_DIR}/libhello/hello.cpp)
hello SHARED
表示生成动态库,名字叫做helloPROJECT_SOURCE_DIR
就是顶层CMakeList.txt
所在文件路径的值。 采用的是hello.cpp所在的绝对路径
# CMAKE_INSTALL_PREFIX选择可执行文件安装的路
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR}/install)
install(TARGETS hello LIBRARY DESTINATION lib)
install(FILES ${PROJECT_SOURCE_DIR}/libhello/hello.h DESTINATION include)
- 设置(set)插入路径为PROJECT_SOURCE_DIR}/install
- 将目标(TARGETS )hello(hello) 动态库(LIBRARY )插入到(DESTINATION ) lib(lib)路径下
- 将文件(TARGETS )hello.h(hello.h) 插入到(DESTINATION ) include(include)路径下
进入到buid目录下,执行命令cmake ..
、make
,make install
目录如下:
使用生成的动态链接库
方法1.直接用g++指定头文件路径和动态链接库路径
- 新建工程usehellolib,并将install下的所有文件复制到新工程下
- 在usehellolib目录下,使用gcc命令链接并执行生成可执行文件
语法: gcc 源文件 -I头文件目录 -L动态链接库目录 动态链接库文件名(去掉lib在前面加l) -o 生成的可执行文件名字
g++ main.cpp -I include/ -L lib/ -lhello -o usehello
发现可以链接成功
但是输入./usehellolib
会出现这个错误
# ./usehello
./usehello: error while loading shared libraries: libhello.so: cannot open shared object file: No such file or directory
说明找不到库,因为采用的是动态链接库,所谓动态链接是在运行时链接,编译链接的时候是直接告诉了GCC库的位置,因此会成功,而运行是如果不告诉操作系统库在哪个位置,当然找不到这个库,程序也就不能运行。因此要告诉操作系统库在哪个地方,linux使用LD_LIBRARY_PATH告诉系统库在哪个地方。(LD_LIBRARY_PATH是Linux环境变量名,该环境变量主要用于指定查找共享库(动态链接库)时除了默认路径之外的其他路径)。
偷个懒:直接将lib库下的libhello.so和usehello 放在同一个目录下,然后执行./usehello
方法2.Cmake链接动态链接库
那么在大型工程中怎么链接外部共享库呢?本节介绍编辑CMakeLists.txt来使用生成的动态链接库。
在usehellolib下新建CMakeLists.txt如下
cmake_minimum_required(VERSION 3.16)
project(usehellolib)
set(CMAKE_CXX_STANDARD 14)
link_directories (${PROJECT_SOURCE_DIR}/lib)
add_executable(${PROJECT_NAME} main.cpp)
include_directories( ${PROJECT_SOURCE_DIR}/include)
target_link_libraries (${PROJECT_NAME} libhello.so)
解析:
include_directories
: 告诉编译器头文件在哪个位置。link_directories
: 添加非标准的共享库搜索路径target_link_libraries
: 把目标文件与库文件进行链接${PROJECT_NAME}
: 项目名称
输入
- cmake.
- make
使用库的步骤
- 在工程文件中包含库函数的头文件(可以是绝对路径,也可以配置成全局环境变量用相对路径)
- 在CMakeLists.txt或者集成开发环境中指定库函数的动态链接库或者静态链接库所在的文件夹路径
- 在CMakeLists.txt或集成开发环境中指定头文件的文件夹路径
- 如果是动态链接库,且库函数不在linux默认查找路径下,运行时要修改环境变量才能使用
其他
ps: centos 的tree命令:
yum -y install tree
tree命令行参数:
-a 显示所有文件和目录。
-A 使用ASNI绘图字符显示树状图而非以ASCII字符组合。
-C 在文件和目录清单加上色彩,便于区分各种类型。
-d 显示目录名称而非内容。
-D 列出文件或目录的更改时间。
-f 在每个文件或目录之前,显示完整的相对路径名称。
-F 在执行文件,目录,Socket,符号连接,管道名称名称,各自加上"*","/","=","@","|"号。
-g 列出文件或目录的所属群组名称,没有对应的名称时,则显示群组识别码。
-i 不以阶梯状列出文件或目录名称。
-I 不显示符合范本样式的文件或目录名称。
-l 如遇到性质为符号连接的目录,直接列出该连接所指向的原始目录。
-n 不在文件和目录清单加上色彩。
-N 直接列出文件和目录名称,包括控制字符。
-p 列出权限标示。
-P 只显示符合范本样式的文件或目录名称。
-q 用"?"号取代控制字符,列出文件和目录名称。
-s 列出文件或目录大小。
-t 用文件和目录的更改时间排序。
-u 列出文件或目录的拥有者名称,没有对应的名称时,则显示用户识别码。
-x 将范围局限在现行的文件系统中,若指定目录下的某些子目录,其存放于另一个文件系统上,则将该子目录予以排除在寻找范围外。