我已经编写了一个库,过去我使用自编的Makefile编译它,但现在我想切换到cmake。树是这样的(我删除了所有不相关的文件):
.
├── include
│ ├── animation.h
│ ├── buffers.h
│ ├── ...
│ ├── vertex.h
│ └── world.h
└── src
├── animation.cpp
├── buffers.cpp
├── ...
├── vertex.cpp
└── world.cpp
我只是想把它编译到一个共享的文件库中。
我发现的大多数示例都使用一些共享库编译可执行文件,但绝不仅仅是一个普通的共享库。如果有人能告诉我一个使用cmake的非常简单的库,那也会很有帮助,所以我可以用这个作为例子。
我正在尝试自己学习如何实现这一点,您似乎可以这样安装库:
cmake_minimum_required(VERSION 2.4.0)
project(mycustomlib)
# Find source files
file(GLOB SOURCES src/*.cpp)
# Include header files
include_directories(include)
# Create shared library
add_library(${PROJECT_NAME} SHARED ${SOURCES})
# Install library
install(TARGETS ${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME})
# Install library headers
file(GLOB HEADERS include/*.h)
install(FILES ${HEADERS} DESTINATION include/${PROJECT_NAME})
这是最小的CMakeLists。txt文件编译了一个简单的共享库:
cmake_minimum_required(VERSION 2.8)
project (test)
set(CMAKE_BUILD_TYPE Release)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
add_library(test SHARED src/test.cpp)
但是,我没有使用CMake将文件复制到其他目的地的经验。带有COPY/INSTALL签名的file命令看起来可能有用。
始终指定cmake
的最低要求版本
cmake_minimum_required(VERSION 3.9)
您应该声明一个项目。cmake
说它是强制性的,它将定义方便的变量PROJECT_NAME
,PROJECT_VERSION
和PROJECT_DESCRIPTION
(后一个变量需要cmake 3.9):
project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")
声明一个新的库目标。请避免使用file(GLOB...)
。此功能不提供编译过程的参与式掌握。如果您是懒惰的,请复制粘贴输出ls-1 source/*. cpp
:
add_library(mylib SHARED
sources/animation.cpp
sources/buffers.cpp
[...]
)
设置VERSION
属性(可选,但这是一个良好的做法):
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
您还可以将SOVERSION
设置为VERSION
的主要编号。所以libmylib。所以1
将是指向libmylib的符号链接。所以1.0.0
。
set_target_properties(mylib PROPERTIES SOVERSION 1)
声明库的公共API。此API将为第三方应用程序安装。将其隔离在项目树中是一个很好的做法(如将其放在包括/
目录中)。请注意,不应该安装私有头,我强烈建议将它们与源文件放在一起。
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)
如果您使用子目录,包含像".../包括/mylib. h"
这样的相对路径不是很方便。所以,在包含的目录中传递一个顶部目录:
target_include_directories(mylib PRIVATE .)
或者
target_include_directories(mylib PRIVATE include)
target_include_directories(mylib PRIVATE src)
为你的库创建一个安装规则。我建议使用CMAKE_INSTALL_*DIR
中定义的变量GNUInstallDir
:
include(GNUInstallDirs)
并声明要安装的文件:
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
您还可以导出pkg config
文件。此文件允许第三方应用程序轻松导入您的库:
pkg-config
PKG_CHECK_MODULES
pkg_check_modules
创建一个名为mylib.pc.in
的模板文件(有关详细信息,请参阅pc(5)manpage):
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}
的变量):
configure_file(mylib.pc.in mylib.pc @ONLY)
最后,安装生成的文件:
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
您也可以使用cmakeEXPORT
功能。然而,该功能仅与cmake
兼容,我发现很难使用。
最后是整个CMakeLists。txt应该是这样的:
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)
编辑
正如评论中提到的,为了符合标准,您应该能够生成静态库和共享库。这个过程有点复杂,与最初的问题不匹配。但是值得一提的是,这里有很多解释。
我正在尝试链接一个名为libtest lib的预编译共享库文件。所以这是我在CMakeLists的底部所拥有的。txt: 如上所述,我得到以下错误: 如果我注释掉add_library行,我会得到以下结果: 在库中链接时,似乎绝对需要源文件(.c、cpp等)。但我如何在一个。那档案呢?这些文档对target_link_库()做了如下介绍: 被命名的必须是由add_executable()或add_
我想为消息驱动的EJB创建一个主题上的共享、非持久订阅,并想知道如何使用@MessageDriven和@ActivationConfigProperty来实现这一点。 我发现一篇文章描述了类似的事情,但我不确定这是否适用于我的问题: 订阅的共享依赖于客户端id的设置,不仅对于持久订阅(总是需要客户端id),对于非持久订阅(通常不需要客户端id)也是如此。如果订阅是由资源适配器创建的,以供消息驱动b
JMS 2.0规范引入了共享持久订阅的概念。我有一个用例,我必须在服务器启动时以编程方式创建订阅。我们有集群的JBoss服务器。因此,每个JBoss都有类似的配置,每个JBoss都有将创建持久订阅者的应用程序(消息提供者是WMQ)。由于持久订阅必须有一个唯一的名称,我想到了使用共享订阅。现在的问题是Spring的4.0.6.RELEASE支持JMS 2.0中的新功能,但是我没有找到通过Spring
我的groovy脚本都在git存储库中,使用jenkins checkout SCM。其中一个groovy脚本中有一些常用函数,我想使这个groovy成为一个共享库,而无需打开jenkins并在jenkins管理表中添加共享库。 我可以使用RESTAPI或其他方法添加新库吗?
现在我想为我们的系统开发一个通用的邮件服务。在设计时,我们希望开发一个生产者和消费者。在消费者方面,我们可以开发和部署或应用程序,但在生产者方面,我们希望提供一个通用的邮件客户端,如下面的接口,并为其他系统建立jar依赖关系。 但我看到spring boot和spring cloud使用了许多声明性方法,似乎必须使用一个应用程序类,但我只想要一个类引用,不需要部署。我不知道如何实施它。
我建立了一个具有两个节点和外部Zookeper集合的SOLR集群。该ZK集合有3个节点。我使用参数启动solr实例: 这意味着,我希望SOLR配置在/solr5下,而不是默认情况下的/下。 文件夹 /solr5在ZK中创建: 我还可以毫无问题地将SOLR配置上传到/solr5中。 我的问题是,在创建集合时,如何将生成的文件置于/solr5之下? 我用来创建集合的命令是: 我查看了本页上的文档,但没