用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_NAMEPROJECT_VERSIONPROJECT_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 EXPORTfunction 。 但是,这个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})