始终指定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 sources/*.cpp 的输出:
add_library(mylib SHARED
sources/animation.cpp
sources/buffers.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 PRIVATE src)
为您的库创建安装规则。我建议使用在GNUInstallDirs 中定义的变量CMAKE_INSTALL_*DIR:
include(GNUInstallDirs)
并声明要安装的文件:
install(TARGETS mylib
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
您还可以导出pkg-config 文件。此文件允许第三方应用程序轻松导入您的库:
创建一个名为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)
您也可以使用cmake EXPORT feature。不过这个功能只兼容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)
编辑
如 cmets 中所述,为了符合标准,您应该能够生成静态库以及共享库。这个过程有点复杂,与最初的问题不匹配。不过值得一提的是here大大解释了。