用cmake创build一个共享库
我写了一个库,使用自编的Makefile进行编译,但现在我想切换到cmake。 树看起来像这样(我删除了所有不相关的文件):
. ├── include │ ├── animation.h │ ├── buffers.h │ ├── ... │ ├── vertex.h │ └── world.h └── src ├── animation.cpp ├── buffers.cpp ├── ... ├── vertex.cpp └── world.cpp
所以我想要做的只是将源代码编译成共享库,然后将其与头文件一起安装。
我发现的大多数例子都是用一些共享库编译可执行文件,但从来不只是一个普通的共享库。 如果有人能够告诉我一个使用cmake的非常简单的库,这也是有帮助的,所以我可以使用这个例子。
始终指定最低要求的cmake
版本
cmake_minimum_required(VERSION 3.9)
你应该申报一个项目。 cmake
说它是强制性的,它将定义方便的variablesPROJECT_NAME
, PROJECT_VERSION
和PROJECT_DESCRIPTION
(这后一个variables需要cmake 3.9):
project(mylib VERSION 1.0.1 DESCRIPTION "mylib description")
宣布一个新的图书馆目标。 请避免使用file(GLOB ...)
。 这个function不能提供编译过程的精通。 如果你是懒惰的,复制粘贴输出ls -1 sources/*.cpp
:
add_library(mylib SHARED sources/animation.cpp sources/buffers.cpp [...] )
设置VERSION
属性(可选,但这是一个很好的做法):
set_target_properties(mylib PROPERTIES VERSION ${PROJECT_VERSION})
您也可以将SOVERSION
设置SOVERSION
VERSION
。 所以libmylib.so.1
将成为libmylib.so.1
的符号链接。
set_target_properties(mylib PROPERTIES SOVERSION 1)
声明你的库的公共API。 该API将被安装用于第三方应用程序。 在项目树中隔离它是个很好的做法(比如放置它include/
目录)。 注意,私人头文件不应该被安装,我强烈build议把它们放在源文件中。
set_target_properties(mylib PROPERTIES PUBLIC_HEADER include/mylib.h)
如果你使用子目录,像"../include/mylib.h"
这样的相对path是不太方便的。 所以,在包含的目录中传递顶层目录:
target_include_directories(mylib PRIVATE .)
要么
target_include_directories(mylib PRIVATE include) target_include_directories(mylib PRIVATE src)
为您的库创build安装规则。 我build议使用在GNUInstallDirs
定义的variablesCMAKE_INSTALL_*DIR
:
include(GNUInstallDirs)
并声明要安装的文件:
install(TARGETS mylib LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
您也可以导出一个pkg-config
文件。 这个文件允许第三方应用程序轻松导入你的库:
- 使用Makefile,请参阅
pkg-config
- 与Autotools,请参阅
PKG_CHECK_MODULES
- 用cmake,请参阅
pkg_check_modules
创build一个名为mylib.pc.in
的模板文件:
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
,添加一条规则来展开@
macros( @ONLY
要求cmake不要展开${VAR}
forms的${VAR}
):
configure_file(mylib.pc.in mylib.pc @ONLY)
最后,安装生成的文件:
install(FILES ${CMAKE_BINARY_DIR}/mylib.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
您也可以使用cmake EXPORT
function 。 但是,这个function只与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)
这个最小的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签名的文件命令看起来可能有用。
我正在努力学习如何自己做这个,看来你可以像这样安装库:
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})