如何模拟find_package()来做与add_subdirectory()相同的操作?(现代CMake)



我的问题与他们所说的现代CMake有很大关系。我读过很多关于CMake试图获得避免反模式的最佳实践的文章。

我的项目正在开发中,我不想安装我的库,也不想在repo之外生成任何东西。($HOME、/usr/local或任何位置(所有东西都必须留在存储库中。

我使用树外文件夹读取add_subdirectories()是一种反模式。我正在寻找一种更好的方式来做我想做的事。

我有一个图书馆和一个应用程序正在开发中,每个都在自己的文件夹中在开发阶段,不应将库视为库(.a/.so(.

当我编译应用程序时,我希望也能构建lib。

.
+-- lib
|   +- CMakeLists.txt
|   +- src
|   |  +- lib.cpp
|   +- include
|   |  +- lib.h
+-- app
+- CMakeLists.txt
+- src
|  +- app.cpp
+- include
|  +- app.h
  • lib/CMakeLists.txt:
add_library(mylib src/lib.cpp)
# Export the public header files to any future user
target_include_directories(mylib 
PUBLIC ${CMAKE_CURRENT_LIST_DIR}/include
)
  • app/CMakeLists.txt:我在考虑将find_package()cmake/FindMyLib.cmake一起使用
    • cmake/FindMyLib.cmake应该包含到../lib的链接,就像我对add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../lib build)所做的那样
list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_SOURCE_DIR}/cmake)
find_package(mylib REQUIRED)
include_directories("${mylib_INCLUDE_DIRS}")
  • 我的工作流程合法吗
  • 我该怎么做

为什么做这么简单的项目不更容易。。CMake只是一片丛林。

关于您的"现代的";CMake。

您的包含呼叫是错误的,请使用:

target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mylib>
$<INSTALL_INTERFACE:include/mylib>  # <prefix>/include/mylib
)

即,您不希望在安装导出中看到本地路径
参考:https://cmake.org/cmake/help/latest/command/target_include_directories.html

由于您使用的是目标属性,因此不需要任何mylib_INCLUDE_DIRS,只需使用:

target_link_libraries(myapp PRIVATE mylib)

这里CCD_ 7将";向前";它将目录包含到您的应用程序中。

您当然可以将CMakeLists.txt文件添加到libapp的父目录中

project(SomeName)
add_subdirectory(lib)
add_subdirectory(app)

对我来说,这似乎是在同一项目中同时将mylib和应用程序作为目标的唯一选择。这允许您简单地使用

target_link_libraries(app PRIVATE mylib)

在CCD_ 11中。

但是,不需要在存储库之外安装库。只需将CMAKE_INSTALL_PREFIX指定为存储库中的一个目录,并通过设置CPACK_PACKAGING_INSTALL_PREFIX指定一个单独的目录进行打包。事实上,这就是cpack在将所有文件添加到输出文件之前所做的操作。

lib/CMakeLists.txt

add_library(mylib src/lib.cpp include/lib.h) # added header here to show up in IDE
# Export the public header files to any future user
target_include_directories(mylib PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/mylib>
$<INSTALL_INTERFACE:include>
)
set_target_properties(mylib PROPERTIES PUBLIC_HEADER mylib/include/lib.h)
install(TARGETS mylib EXPORT mylib
ARCHIVE DESTINATION lib # .lib destination
LIBRARY DESTINATION lib # .so location
RUNTIME DESTINATION bin # .dll location
PUBLIC_HEADER DESTINATION include 
)
install(EXPORT mylib DESTINATION mylib FILE mylib-config.cmake)

您可以通过从libapp的父目录开始执行以下命令来构建库并将其安装到存储库中的一个目录中(假设此处为linux bash(:

mkdir mylib/build
mkdir local_installs
cmake -D "CMAKE_INSTALL_PREFIX:PATH=$(pwd)/local_installs" -S mylib -B mylib/build
cmake --build mylib/build --target INSTALL

这允许您使用应用程序中的配置版本使用find_package

find_package(mylib REQUIRED
PATHS "${CMAKE_CURRENT_SOURCE_DIR}/../local_installs/mylib" 
NO_PACKAGE_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_ENVIRONMENT_PATH # prevent lookup at location other than local_installs first
)

最新更新