静态库和动态库的构建(Cmake )(三)

静态库和动态库的构建

任务:
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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值