How to create a shared library with cmake?(如何使用 cmake 创建共享库?)
问题描述
我已经写了一个库,我曾经使用自己编写的 Makefile 进行编译,但现在我想切换到 cmake.树看起来像这样(我删除了所有不相关的文件):<预><代码>.├── 包括│ ├── animation.h│ ├── buffers.h│ ├── ...│ ├── vertex.h│ └── world.h└── src├──动画.cpp├──缓冲区.cpp├── ...├── 顶点.cpp└── world.cpp
所以我想要做的只是将源代码编译成共享库,然后与头文件一起安装.
我发现的大多数示例都使用一些共享库编译可执行文件,但绝不仅仅是一个普通的共享库.如果有人能告诉我一个使用 cmake 的非常简单的库也会很有帮助,所以我可以以此为例.
始终指定 cmake
cmake_minimum_required(VERSION 3.9)
您应该声明一个项目.cmake
说这是强制性的,它将定义方便的变量 PROJECT_NAME
、PROJECT_VERSION
和 PROJECT_DESCRIPTION
(后一个变量需要 cmake3.9):
project(mylib 版本 1.0.1 描述mylib 描述")
声明一个新的库目标.请避免使用file(GLOB ...)
.此功能不提供编译过程的有人参与的掌握.如果你懒惰,复制粘贴 ls -1 sources/*.cpp
的输出:
add_library(mylib 共享来源/动画.cpp源/缓冲区.cpp[...])
设置 VERSION
属性(可选,但这是一个好习惯):
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
您还可以将SOVERSION
设置为VERSION
的主要编号.所以 libmylib.so.1
将是 libmylib.so.1.0.0
的符号链接.
set_target_properties(mylib PROPERTIES SOVERSION 1)
声明您的库的公共 API.将为第三方应用程序安装此 API.将它隔离在您的项目树中是一个很好的做法(比如将它放在 include/
目录中).请注意,不应安装私有头文件,我强烈建议将它们与源文件放在一起.
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)
如果您使用子目录,则包含诸如 ../include/mylib.h"
之类的相对路径不是很方便.因此,在包含的目录中传递一个顶级目录:
target_include_directories(mylib PRIVATE .)
或
target_include_directories(mylib PRIVATE include)target_include_directories(mylib 私有源代码)
为您的库创建安装规则.我建议使用 GNUInstallDirs
中定义的变量 CMAKE_INSTALL_*DIR
:
include(GNUInstallDirs)
并声明要安装的文件:
安装(目标 mylib图书馆目的地 ${CMAKE_INSTALL_LIBDIR}PUBLIC_HEADER 目的地 ${CMAKE_INSTALL_INCLUDEDIR})
您也可以导出 pkg-config
文件.此文件允许第三方应用程序轻松导入您的库:
- 使用 Makefile,参见
pkg-config
- 对于 Autotools,请参阅
PKG_CHECK_MODULES
- 使用 cmake,请参阅
pkg_check_modules
一个>
创建一个名为 mylib.pc.in
的模板文件(参见 pc(5) 手册页了解更多信息):
prefix=@CMAKE_INSTALL_PREFIX@exec_prefix=@CMAKE_INSTALL_PREFIX@libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@includeir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@姓名:@PROJECT_NAME@描述:@PROJECT_DESCRIPTION@版本:@PROJECT_VERSION@要求:库:-L${libdir} -lmylibCflags: -I${includedir}
在你的 CMakeLists.txt
中,添加一个规则来扩展 @
宏(@ONLY
要求 cmake 不扩展表单的变量${VAR}
):
configure_file(mylib.pc.in mylib.pc @ONLY)
最后,安装生成的文件:
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
您也可以使用 cmake <代码>导出代码>功能.不过这个功能只兼容cmake
,我觉得很难用.
最后整个 CMakeLists.txt
应该看起来像:
cmake_minimum_required(VERSION 3.9)项目(mylib 版本 1.0.1 描述mylib 描述")包括(GNUInstallDirs)add_library(mylib 共享 src/mylib.c)set_target_properties(mylib 属性版本 ${PROJECT_VERSION}SOVERSION 1PUBLIC_HEADER api/mylib.h)配置文件(mylib.pc.in mylib.pc @ONLY)target_include_directories(mylib PRIVATE .)安装(目标 mylib图书馆目的地 ${CMAKE_INSTALL_LIBDIR}PUBLIC_HEADER 目的地 ${CMAKE_INSTALL_INCLUDEDIR})安装(文件 ${CMAKE_BINARY_DIR}/mylib.pc目的地 ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
编辑
正如评论中提到的,为了符合标准,您应该能够生成静态库和共享库.这个过程有点复杂,与最初的问题不符.但值得一提的是,它在这里有很好的解释.
I have written a library that I used to compile using a self-written Makefile, but now I want to switch to cmake. The tree looks like this (I removed all the irrelevant files):
.
├── include
│ ├── animation.h
│ ├── buffers.h
│ ├── ...
│ ├── vertex.h
│ └── world.h
└── src
├── animation.cpp
├── buffers.cpp
├── ...
├── vertex.cpp
└── world.cpp
So what I am trying to do is just to compile the source into a shared library and then install it with the header files.
Most examples that I have found compile executables with some shared libraries but never just a plain shared library. It would also be helpful if someone could just tell me a very simple library that uses cmake, so I can use this as an example.
Always specify the minimum required version of cmake
cmake_minimum_required(VERSION 3.9)
You should declare a project. cmake
says it is mandatory and it will define convenient variables PROJECT_NAME
, PROJECT_VERSION
and PROJECT_DESCRIPTION
(this latter variable necessitate cmake 3.9):
project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")
Declare a new library target. Please avoid the use of file(GLOB ...)
. This feature does not provide attended mastery of the compilation process. If you are lazy, copy-paste output of ls -1 sources/*.cpp
:
add_library(mylib SHARED
sources/animation.cpp
sources/buffers.cpp
[...]
)
Set VERSION
property (optional but it is a good practice):
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
You can also set SOVERSION
to a major number of VERSION
. So libmylib.so.1
will be a symlink to libmylib.so.1.0.0
.
set_target_properties(mylib PROPERTIES SOVERSION 1)
Declare public API of your library. This API will be installed for the third-party application. It is a good practice to isolate it in your project tree (like placing it include/
directory). Notice that, private headers should not be installed and I strongly suggest to place them with the source files.
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)
If you work with subdirectories, it is not very convenient to include relative paths like "../include/mylib.h"
. So, pass a top directory in included directories:
target_include_directories(mylib PRIVATE .)
or
target_include_directories(mylib PRIVATE include)
target_include_directories(mylib PRIVATE src)
Create an install rule for your library. I suggest to use variables CMAKE_INSTALL_*DIR
defined in GNUInstallDirs
:
include(GNUInstallDirs)
And declare files to install:
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
You may also export a pkg-config
file. This file allows a third-party application to easily import your library:
- with Makefile, see
pkg-config
- with Autotools, see
PKG_CHECK_MODULES
- with cmake, see
pkg_check_modules
Create a template file named mylib.pc.in
(see pc(5) manpage for more information):
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: @PROJECT_DESCRIPTION@
Version: @PROJECT_VERSION@
Requires:
Libs: -L${libdir} -lmylib
Cflags: -I${includedir}
In your CMakeLists.txt
, add a rule to expand @
macros (@ONLY
ask to cmake to not expand variables of the form ${VAR}
):
configure_file(mylib.pc.in mylib.pc @ONLY)
And finally, install generated file:
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
You may also use cmake EXPORT
feature. However, this feature is only compatible with cmake
and I find it difficult to use.
Finally the entire CMakeLists.txt
should looks like:
cmake_minimum_required(VERSION 3.9)
project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")
include(GNUInstallDirs)
add_library(mylib SHARED src/mylib.c)
set_target_properties(mylib PROPERTIES
VERSION ${PROJECT_VERSION}
SOVERSION 1
PUBLIC_HEADER api/mylib.h)
configure_file(mylib.pc.in mylib.pc @ONLY)
target_include_directories(mylib PRIVATE .)
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
EDIT
As mentioned in comments, to comply with standards you should be able to generate a static library as well as a shared library. The process is bit more complex and does not match with the initial question. But it worths to mention that it is greatly explained here.
这篇关于如何使用 cmake 创建共享库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何使用 cmake 创建共享库?
基础教程推荐
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- Windows Media Foundation 录制音频 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- 使用从字符串中提取的参数调用函数 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01