如何使用cmake创建共享库? [英] How to create a shared library with cmake?

查看:248
本文介绍了如何使用cmake创建共享库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经编写了一个库,该库曾经使用自写的Makefile进行编译,但是现在我想切换到cmake。树看起来像这样(我删除了所有不相关的文件):

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.

我发现的大多数示例都可以用一些共享库,但绝不只是普通共享库。
如果有人可以告诉我一个使用cmake的非常简单的库,这也将很有帮助,因此我可以以此为例。

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.

推荐答案

始终指定 cmake

cmake_minimum_required(VERSION 3.9)

您应声明一个项目。 cmake 说这是强制性的,它将定义方便的变量 PROJECT_NAME PROJECT_VERSION PROJECT_DESCRIPTION (后一个变量需要cmake 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")

声明一个新的库目标。请避免使用 file(GLOB ...)。此功能不提供对编译过程的熟练掌握。如果您很懒,请复制粘贴输出 ls -1 sources / *。cpp

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
    [...]
)

设置 VERSION 属性(可选,但这是一个好习惯):

Set VERSION property (optional but it is a good practice):

set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})

您还可以将 SOVERSION 设置为主要的 VERSION 。因此, libmylib.so.1 将是 libmylib.so.1.0.0 的符号链接。

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)

声明您的库的公共API。将为第三方应用程序安装此API。将其隔离在项目树中是一个好习惯(例如将其放置在 include / 目录中)。请注意,不应安装私有头,我强烈建议将它们与源文件放置在一起。

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)

如果使用子目录,则包括相对路径不是很方便例如 ../ 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 .)

target_include_directories(mylib PRIVATE include)
target_include_directories(mylib PRIVATE src)

为库创建安装规则。我建议使用在 GNUInstallDirs 中定义的变量 CMAKE_INSTALL_ * DIR

Create an install rule for your library. I suggest to use variables CMAKE_INSTALL_*DIR defined in GNUInstallDirs:

include(GNUInstallDirs)

并声明要安装的文件:

install(TARGETS mylib
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

您也可以导出 pkg-config 文件。此文件允许第三方应用程序轻松导入您的库:

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

创建名为 mylib.pc的模板文件.in (请参见 pc(5 )联机帮助页以获取更多信息):

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}

在您的 CMakeLists.txt 中,添加一个扩展规则 @ 宏( @ONLY 要求cmake不扩展 $ {VAR形式的变量} ):

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)

您还可以使用 cmake 导出功能。但是,此功能仅与 cmake 兼容,我觉得很难使用。

You may also use cmake EXPORT feature. However, this feature is only compatible with cmake and I find it difficult to use.

最后整个 CMakeLists.txt 应该看起来像:

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)

这篇关于如何使用cmake创建共享库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆