一、如何使用外部共享库和头文件
使用上一节中构建的共享库。
1、准备工作
在cmake中创建t4用来存储这一节的资源。
2、编码
编写源文件main.c如下:
t4下的CMakeLists.txt如下:
t4下的src下的CMakeLists.txt如下:
3、外部构建
建立build文件夹,使用cmake …来构建。
cmake ..
make
会的到如下的错误:
/backup/cmake/t4/src/main.c:1:19: error: hello.h:
没有那个文件或目录
4、引入头文件搜索路径
hello.h位于/usr/include/hello目录中,并没有位于系统标准的头文件路径。为了让我们的工程能够找到hello.h头文件,需要引入一个新的指令
INCLUDE_DIRECTORIES([AFTER|BEFORE] [SYATEM] dir1 dir2 ...)
这条指令可以用来向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,可以使用双引号将它括起来,默认的行为是追加到当前的头文件搜索路径的后面,你可以通过两种方式来进行控制搜索路径添加的方式:
CMAKE_INCLUDE_DIRECTORIES_BEFORE
通过SET
这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面。
通过AFTER或者BEFOR参数,也可以控制是追加还是置前。
现在我们在src/CMakeLists.txt添加一个头文件搜索路径,如下:
添加
INCLUDE_DIRECTORIES(/usr/include/hello)
如果只添加头文件搜索路径,则还是会出现一个错误:
main.c:(.text+0x12): undefined reference to `HelloFunc'
因为我们还没有将link到共享库libhello上。所以我们需要为target添加共享库,需要将目标文件连接到libhello,这里我们需要引入两个新的指令:
LINK_DIRECTORIES
TARHGET_LINK_LIBRARIES
LINK_DIRECTORIES(directtory1 directory2 ...)
添加非标准的共享库搜索路径,比如在工程内部同时存在共享库和可执行二进制,在编译时就需要指定一下这些共享库的路径。
TARGET_LINK_LIBRARIES(target library1 <debug | optimized> library2...)
这个指令可以用来为target添加需要连接的共享库,但是同样可以用于为自己编写的共享库添加共享库添加共享库连接。
进入build/src目录,运行main的结果可能还会出现错误+_+.
出现错误的原因是:链接器ld找不到库文件。ld默认目录是/lib和/usr/lib,如果放在其他路径也可以,需要让ld知道文件的所在路径。
解决方法如下:
方案一:
# vim /etc/ld.so.conf //在新的一行中加入库文件所在目录
/usr/lib
# ldconfig //更新/etc/ld.so.cache文件
方案二:
1.将用户用到的库统一放到一个目录,如 /usr/loca/lib
# cp libXXX.so.X /usr/loca/lib/
2.向库配置文件中,写入库文件所在目录
# vim /etc/ld.so.conf.d/usr-libs.conf
/usr/local/lib
3.更新/etc/ld.so.cache文件
# ldconfig
我这里为了方便采用了方案一。如果共享库文件安装到了/lib或/usr/lib目录下, 那么需执行一下ldconfig命令,ldconfig命令的用途, 主要是在默认搜寻目录(/lib和/usr/lib)以及动态库配置文件/etc/ld.so.conf内所列的目录下,搜索出可共享的动态链接库(格式如lib*.so*), 进而创建出动态装入程序(ld.so)所需的连接和缓存文件. 缓存文件默认为/etc/ld.so.cache, 此文件保存已排好序的动态连接库。
得到的结果是:
查看main的动态链接库情况:
可以看到main确实连接到了共享库libhello,而且链接的是动态库libhello.so.1.
那如何链接到动态库?
方法很简单:
将TARGET_LINK_LIBRERIES
(main libhello.a),重新编译连接后。使用指令
指令:ldd src/main(在目录build下)
结果如下:
可以看到,main确实连接到了静态库libhello.a。
6、特殊的环境变量CMAKE_INCLUUDE_PATH和CMAKE_LIBRARY_PATH
注意,这两个是环境变量不是cmake变量。使用的方法是要在bash中使用export或者在csh中使用SET
命令设置或者CMAKE_INCLUDE_PATH
=/home/include
cmake …等方式。
这两个变量指的是,如果头文件没有存放在常规路径中,比如(/usr/include,/usr/local/include等),则可以通过这些变量来弥补。
之前在CMakeList.txt中使用了INCLUDE_DIRECTORIES
(/usr/include/hello)告诉头文件这个头文件目录。
为了将程序更智能一点,我们可以使用CMAKE_INCLUDE_PATH
来进行,使用bash的方法如下:
在指令行中输入:
然后,再将src/CMakeLisrs.txt中的INCLUDE_DIRECTORIES
(/usr/include/hello)替换为:
指令:FIND_PATH
(myHeader NAMES hello.h PATHS /usr/include /usr/include/hello)
这里cmake.h仍然可以找到hello.h存放的路径,就是因为我们设置了环境变量CMAKE_INCLUDE_PATH
.
如果你不使用FIND_PATH
,CMAKE_INCLUDE_PATH
变量是没有作用的,你不能指望他会为变化一起命令添加参数-I<CMAKE_INCLUDE_PATH
>。
以此为例,CMAKE_LIBRARY_PATH
可以用在FIND_LIBRARY
。文章来源:https://www.toymoban.com/news/detail-407843.html
7、小节
如何通过INCLUDE_DIRECTORIES
指令加入非标准的头文件搜索路径。
如何通过LINK_DIRECTORIES
指令加入非标准的库文件搜索路径。
如何通过TARGET_LINK_LIBRARIES
为库或可执行二进制加入库链接。
并解释了如何链接到静态库。下面会介绍一些高级话题,比如编译条件检查、编译器定义、平台判断、如何跟pkgconfig配合使用等等。文章来源地址https://www.toymoban.com/news/detail-407843.html
到了这里,关于cmake使用教程(实操版)(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!