cmake使用教(三)构建动态库、静态库和安装共享库

2023-05-16

前两节简单的介绍了,cmake的简单使用和install的过程,本节将详细介绍构建动态库和静态库,以及共享动态库和静态库的过程

文件存放方式:

 创建test根目录,然后创建lib和build,在根目录下创建CMakeLists.txt,,在lib目录下创建CMakeLists.txt、hello.cpp、hello.h, 其中hello.cpp、hello.h内容如下:

hello.h
#ifndef HELLO_H
#define HELLO_H

#include<iostream>
void helloFunc();

#endif

//#######################################################
hello.cpp

#include "hello.h"
void helloFunc()
{
    std::cout<<"hello world"<<std::endl;
}

1.构建动态库和静态库

在根目录下面的CMakeLists.txt文件中添加如下代码:

因为根目录下的CMakeLists.txt无须构建文件,只需要启动子文件的CMakeLists.txt即可

# 版本判断
cmake_minimum_required(VERSION 3.0)
# 工程名
project(hellolib)
# 添加子目录,该目录为库目录,会调用子目录的cmake文件,进行构建库
add_subdirectory(lib)

主要的构建代码在lib/CMakeLists.txt里:

# 把所有源文件添加到列表
aux_source_directory(. DIR_LIB_SRCS)
# 如果文件很少,可以通过直接指定
# set(DIR_LIB_SRCS hello.cpp)

# 指定编译库输出的位置
set(LIBRARY_OUTPUT_PATH lib)
# 生成动态库
add_library(hello SHARED ${DIR_LIB_SRCS})

# 生成静态库
# 这样写会使得静态库没有构建,报错原因是动态库的名称也是hello即target不能重名
# add_library(hello STATIC ${DIR_LIB_SRCS}) 
# 修改名称后构建是可以成功的,会生成libhello_static.a和libhello.so两个文件,
# 但是同一种库我们希望名称一样
add_library(hello_static STATIC ${DIR_LIB_SRCS}) 

# 想要生成动态库和静态库相同名称的的库文件,则需要一个指令set_target_properties
# 这里只是通过重新命名的方法使其名字相同的,构建时还需不能相同
set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")
# 获取相关属性也是通过set_target_properties
get_target_property(OUTPUT_VALUE hello_static OUTPUT_NAME)
message(STATUS "This is the hello_static OUTPUT_NAME:"${OUTPUT_VALUE})

# 动态库版本号设置 , VERSION指代动态库版本,SOVERSION 指代 API 版本。
set_target_properties(hello PROPERTIES VERSION 1.2 SOVERSION 1)
# 其中,libhello.so.1.2为动态库的文件名(realname),libhello.so.1为动态库的别名(soname),
# libhello.so为动态库的链接名(linkname)。

message(STATUS ${DIR_LIB_SRCS}"--构建库完成")

# 安装共享库和头文件
# 将动态库和静态库安装到<prefix>/lib
install(TARGETS hello hello_static LIBRARY DESTINATION lib ARCHIVE DESTINATION lib)
# 安装头文件
install(FILES hello.h DESTINATION include/hello)

进入build执行以下命令: 

cmake -DCMAKE_INSTALL_PREFIX=/home/ubuntu/work/usr ..
make
make install

代码注释已经很相详细了,这里只需要强调几个指令和注意事项:

如果你要指定libhello.so生成的位置,可以通过在主工程文件CMakeLists.txt 中修改add_subdirectory(lib newdir)指令来指定一个编译输出位置或者在lib/CMakeLists.txt 中添加set(LIBRARY_OUTPUT_PATH newdir)来指定一个新的位置。newdir是相对路径,如下lib的lib里可以直接使用lib替换newdir

add_libraary指令

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [<source>...])

name中你不需要写全libhello.so,只需要填写hello 即可,cmake系统会自动为你生成libhello.X

类型有三种:
SHARED,动态库
STATIC,静态库
MODULE,在使用 dyld 的系统有效,如果不支持dyld,则被当作SHARED对待。
EXCLUDE_FROM_ALL参数的意思是这个库不会被默认构建,除非有其他的组件依赖或者手
工构建。 

动态库和静态库构建

# 生成动态库
add_library(hello SHARED ${DIR_LIB_SRCS})
# 生成静态库
# 这样写会使得静态库没有构建,报错原因是动态库的名称也是hello即target不能重名
# add_library(hello STATIC ${DIR_LIB_SRCS}) 

如果动态库和静态库的名称相同,会导致后一个库无法构建,按照我们的例子因为hello 作为一个target是不能重名的,所以,静态库构建指令无效。

如果把静态库的名称hello 修改为hello_static,则可以顺利的构建,会生成libhello.so和libhello_static.a库文件。

这种结果显示不是我们想要的,我们需要的是名字相同的静态库和动态库,因为 target 名
称是唯一的,所以,我们肯定不能通过 add_library指令来实现了。这时候我们需要用到
另外一个指令:

set_target_properties(target1 target2 ...
                      PROPERTIES prop1 value1
                      prop2 value2 ...)

这条指令可以用来设置输出的名称,对于动态库,还可以用来指定动态库版本和 API版本。
在本例中,我们需要作的是向lib/CMakeLists.txt 中添加一条:

set_target_properties(hello_static PROPERTIES OUTPUT_NAME "hello")


这样,我们就可以同时得到libhello.so/libhello.a 两个库了。

与他对应的指令是:

get_target_property(<VAR> target property)

具体用法如下例,我们向lib/CMakeListst.txt中添加:

get_target_property(OUTPUT_VALUE hello_static OUTPUT_NAME)
message(STATUS "This is the hello_static OUTPUT_NAME:"${OUTPUT_VALUE})

如果没有这个属性定义,则返回NOTFOUND.

动态库版本号的设置

 按照规则,动态库是应该包含一个版本号的,我们可以看一下系统的动态库,一般情况是
libhello.so.1.2
libhello.so ->libhello.so.1
libhello.so.1->libhello.so.1.2
为了实现动态库版本号,我们仍然需要使用 set_target_properties指令。
具体使用方法如下:

set_target_properties(hello PROPERTIES VERSION 1.2 SOVERSION 1)

VERSION指代动态库版本,SOVERSION 指代 API 版本。其中,libhello.so.1.2为动态库的文件名(realname),libhello.so.1为动态库的别名(soname), libhello.so为动态库的链接名(linkname)。

将上述指令加入lib/CMakeLists.txt 中,重新构建看看结果。
在build/lib 目录会生成:
libhello.so.1.2
libhello.so.1->libhello.so.1.2
libhello.so ->libhello.so.1

安装共享库和头文件

安装过程和上一节类似,这里不过得解释。

后面测试调用共享库执行程序

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cmake使用教(三)构建动态库、静态库和安装共享库 的相关文章

  • CMake:如何最好地构建多个(可选)子项目?

    想象一个包含多个组件的整体项目 basic io web app a app b app c 现在 假设 web 依赖于 io 而 io 又依赖于 basic 所有这些东西都在一个存储库中 并且有一个 CMakeLists txt 将它们构
  • “make install”将库安装在 /usr/lib 而不是 /usr/lib64

    我正在尝试在 64 位 CentOS 7 2 上构建并安装一个库 为了这个目的我正在跑步 cmake DCMAKE BUILD TYPE Release DCMAKE INSTALL PREFIX usr DCMAKE C COMPILER
  • Haskell 项目可以使用 cmake 吗?

    我正在计划一个用 Haskell 编写的项目 也许也有一些部分是用 C 编写的 对于构建系统 我决定不选择 Haskell 程序 cabal 的常见选择 主要是因为我想了解其他语言的构建程序是如何工作的 我听说过 CMake 我认为这是一个
  • 在 C 中使用 pow 时,CMake 可以检测是否需要链接到 libm 吗?

    对于某些编译器 using powC 程序中的某些其他函数需要链接到m library https stackoverflow com q 8671366 1959975 但是 某些编译器不需要这样做 并且在链接到m图书馆 C 也存在几乎相
  • 如何将 gnatmake/gnatbind/gnatlink 集成到 C/Ada 代码的 CMake 文件中?

    我用几种语言 C C Fortran77 Fortran90 编写了代码 并且可以使用 CMake 编译它 没有任何问题 效果很完美 现在 我想在用 C 编写的 main 中添加一些 Ada 函数 并且我想通过 CMake 编译它 鉴于我无
  • 如何判断给定目标是库还是可执行文件?

    内置功能install TARGETS 将库目标安装到可执行目标之外的其他位置 我想做类似的事情 给定目标名称列表 我想将其中的所有库目标添加到列表变量中 并将所有运行时目标添加到另一个变量中 我找不到 CMake 的默认目标属性列表 但我
  • 使用 CMake 对 SDL 的未定义引用

    我正在使用 SDL v1 2 15 7 和 CMake 3 2 1 开发一个项目 在 h 文件中我添加了 include
  • 将 Doctest 与代码一起使用时将实现放在哪里

    我在用着doctest https github com onqtam doctest用于我的 C 项目中的测试 我想将测试代码与我的实现放在一起 正如库所说是可能的 但我似乎不知道如何处理 doctest 实现代码 我有一个doctest
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 使用星号更改多个源文件的 CMake 编译器标志

    我正在尝试调试与编译器优化相关的问题 O2 或以下版本没有问题 O3 出现段错误 并且我希望能够切换我的源代码块的编译器标志 以便我可以尝试缩小段错误的来源范围 我可以将全局优化级别设置为 O2 并更改单个文件的属性 如下所示 SET SO
  • 将 dll/lib 链接到 cmake 项目

    我试图将库链接到我的 cmake 项目 但遇到链接器错误 我花了 2 个小时尝试解决这个问题 并创建了一个简单的项目 在其中对所有路径进行了硬编码 CMAKE MINIMUM REQUIRED VERSION 3 0 PROJECT Tes
  • CMake 找不到请求的 Boost 库

    既然我已经浏览了其他人的解决方案几个小时 但找不到适合我的问题的正确答案 我想将我的具体问题带给您 我正在尝试使用 CMake 构建 vsomeip 为此 我之前构建了 boost 1 55 但是 我在 CMake 中收到以下错误 The
  • 使用 CMake 在 iOS 中使用另一个 STATIC 库创建一个 STATIC 库

    我有一个 libfooi a 的集合 libfoo1 a libfoo2 a libfoo3 a 使用工厂 带有静态代码 有一个公共接口来创建 C 对象 使用 CMake 我选择其中之一 并创建一个链接它并添加所有内容的 libfooWra
  • CMake:使用其他平台的生成器。如何?

    如何使用 CMake 在 Linux 上生成 Visual Studio 项目文件 你不能 您必须在 Windows 上运行 CMake 才能为 Visual Studio 生成
  • 使用cmake交叉编译gRPC

    我正在尝试使用 cmake 交叉编译 gRPC 我实际上做到了 不幸的是 我的方法涉及在 CMakeLists txt 内部进行修改 问题是 当我尝试编译 gRPC 时 它使用的是他刚刚编译的 protobuffer 它无法在 x86 计算
  • VS 2010 和 CMake:“rc”未被识别为内部或外部命令

    我正在尝试使用 VS 2010 和 CMake 在 Windows 10 Home 上构建一个项目 我收到以下错误 zutil c lib nologo out zlib lib adler32 obj compress obj crc32
  • CMAKE - 运行时库隐藏文件

    我正在运行 Linux Redhat 我安装了 Anaconda 并且我正在尝试使用安装程序 libspimage CMAKEamd 我收到以下警告 错误 src CMakeLists txt 74 ADD LIBRARY 处的 CMake
  • Clion如何将文件添加到项目中

    这看起来真的很基本 如何将文件添加到项目中而无需手动编辑CMakeLists txt 例如另一个目录中的源文件 CLion 解析CMakeLists txt并使用它生成项目视图 但我相信将文件添加到项目的唯一方法是编辑CMakeLists
  • Cmake:链接到静态内部库而不导出它

    我有一个具有以下结构的项目 path to my project CMakeLists txt internal libs internal lib1 libs lib1 lib2 lib1是一个静态库 lib2是一个静态库 interna
  • 将 cmake 与 nmake x64 一起使用

    我使用 cmake 生成 NMake 文件 一切正常 我使用 x64 工具集 没有 Visual Studio 只有 SDK 因此我输入 nmake 但它生成 x86 构建而不是 x64 构建 你知道为什么吗 以及如何强制 nmake 以

随机推荐