静态库和动态库的构建
任务:
1,建⽴⼀个静态库和动态库,提供 HelloFunc 函数供其他程序编程使⽤,HelloFunc 向终端输出 Hello World 字
符串。
2,安装头⽂件与共享库。
静态库和动态库的区别
- 静态库的扩展名⼀般为“.a”或“.lib”;动态库的扩展名⼀般为“.so”或“.dll”。
- 静态库在编译时会直接整合到⽬标程序中,编译成功的可执⾏⽂件可独⽴运⾏
- 动态库在编译时不会放到连接的⽬标程序中,即可执⾏⽂件⽆法单独运⾏。
构建实例
[root@localhost cmake2]# tree
.
├── build
├── CMakeLists.txt
└── lib
├── CMakeLists.txt
├── hello.cpp
└── hello.h
hello.h中的内容
#ifndef HELLO_H
#define Hello_H
void HelloFunc();
#endif
hello.cpp中的内容
#include "hello.h"
#include <iostream>
void HelloFunc(){
std::cout << "Hello World" << std::endl; }
项⽬中的cmake内容
PROJECT(HELLO)
ADD_SUBDIRECTORY(lib bin)
lib中CMakeLists.txt中的内容
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
- hello:就是正常的库名,⽣成的名字前⾯会加上lib,最终产⽣的⽂件是libhello.so
- SHARED,动态库 STATIC,静态库
- ${LIBHELLO_SRC} :源⽂件
同时构建静态和动态库
// 如果⽤这种⽅式,只会构建⼀个动态库,不会构建出静态库,虽然静态库的后缀是.a
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC})
// 修改静态库的名字,这样是可以的,但是我们往往希望他们的名字是相同的,只是后缀不同⽽已
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES
这条指令可以⽤来设置输出的名称,对于动态库,还可以⽤来指定动态库版本和 API 版本
同时构建静态和动态库
SET(LIBHELLO_SRC hello.cpp)
ADD_LIBRARY(hello_static STATIC ${LIBHELLO_SRC})
//对hello_static的重名为hello
SET_TARGET_PROPERTIES(hello_static PROPERTIES OUTPUT_NAME "hello")
//cmake 在构建⼀个新的target 时,会尝试清理掉其他使⽤这个名字的库,因为,在构建 libhello.so 时, 就
会清理掉 libhello.a
SET_TARGET_PROPERTIES(hello_static PROPERTIES CLEAN_DIRECT_OUTPUT 1)
ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC})
SET_TARGET_PROPERTIES(hello PROPERTIES OUTPUT_NAME "hello")
SET_TARGET_PROPERTIES(hello PROPERTIES CLEAN_DIRECT_OUTPUT 1)
动态库的版本号
⼀般动态库都有⼀个版本号的关联
libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2
CMakeLists.txt 插⼊如下
SET_TARGET_PROPERTIES(hello PROPERTIES VERSION 1.2 SOVERSION 1)
VERSION 指代动态库版本,SOVERSION 指代 API 版本。
安装共享库和头⽂件
本例中我们将 hello 的共享库安装到/lib⽬录,
将 hello.h 安装到/include/hello ⽬录
//⽂件放到该⽬录下
INSTALL(FILES hello.h DESTINATION include/hello)
//⼆进制,静态库,动态库安装都⽤TARGETS
//ARCHIVE 特指静态库,LIBRARY 特指动态库,RUNTIME 特指可执⾏⽬标⼆进制。
INSTALL(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
注意:
安装的时候,指定⼀下路径,放到系统下
cmake -DCMAKE_INSTALL_PREFIX=/usr ..
使⽤外部共享库和头⽂件
准备⼯作,新建⼀个⽬录来使⽤外部共享库和头⽂件
[root@MiWiFi-R4CM-srv cmake3]# tree
.
├── build
├── CMakeLists.txt
└── src
├── CMakeLists.txt
└── main.cpp
main.cpp
#include <hello.h>
int main(){
HelloFunc();
}
解决:make后头⽂件找不到的问题
PS:include <hello/hello.h> 这样include是可以,这么做的话,就没啥好讲的了
关键字:INCLUDE_DIRECTORIES 这条指令可以⽤来向⼯程添加多个特定的头⽂件搜索路径,路径之间⽤空格分
割在CMakeLists.txt中加⼊头⽂件搜索路径
INCLUDE_DIRECTORIES(/usr/include/hello)
解决:找到引用的函数问题
报错信息:undefined reference to `HelloFunc()’
关键字:LINK_DIRECTORIES 添加⾮标准的共享库搜索路径
关键字:TARGET_LINK_LIBRARIES 添加需要链接的共享库
在CMakeLists.txt中插⼊链接共享库,主要要插在executable的后⾯
TARGET_LINK_LIBRARIES(main libhello.so)
查看main的链接情况
[root@MiWiFi-R4CM-srv bin]# ldd main
linux-vdso.so.1 => (0x00007ffedfda4000)
libhello.so => /lib64/libhello.so (0x00007f41c0d8f000)
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f41c0874000)
libm.so.6 => /lib64/libm.so.6 (0x00007f41c0572000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f41c035c000)
libc.so.6 => /lib64/libc.so.6 (0x00007f41bff8e000)
/lib64/ld-linux-x86-64.so.2 (0x00007f41c0b7c000)
链接静态库
TARGET_LINK_LIBRARIES(main libhello.a)
特殊的环境变量 CMAKE_INCLUDE_PATH 和 CMAKE_LIBRARY_PATH
注意:这两个是环境变量⽽不是 cmake 变量,可以在linux的bash中进⾏设置
我们上⾯例⼦中使⽤了绝对路径INCLUDE_DIRECTORIES(/usr/include/hello)来指明include路径的位置
我们还可以使⽤另外⼀种⽅式,使⽤环境变量export CMAKE_INCLUDE_PATH=/usr/include/hello
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/76866.html