将CMake子项目与另一个子项目集成
Integrate CMake subproject with another
我已经编写了一个C++库MyLib
,我想将它与另一个项目ExternPro
集成。所以在ExternPro
中,我这样写CMakeLists.txt
:
add_subdirectory(MyLib)
ADD_EXECUTABLE(test test.cpp)
include_directories(${MyLib_INCLUDE_DIRS})
target_link_libraries(test ${MyLib_LIBRARIES})
为了设置变量MyLib_LIBRARIES
和MyLib_INCLUDE_DIRS
,我写道:
set(MyLib_LIBRARIES ${PROJECT_SOURCE_DIR}/src/MyLib.a CACHE INTERNAL "")
set(MyLib_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include CACHE INTERNAL "")
但有些错误"没有规则使目标MyLib/src/MyLib.a,测试需要。停止。"
所以我的问题是,我应该如何正确地编写CMakeLists.txt
,以便cmake
可以帮助我首先构建MyLib
,然后处理ExternPro
的依赖关系?
如果这是两个独立的项目,我通常使用"CMake find scripts"从另一个库引用一个库:http://www.vtk.org/Wiki/CMake:How_To_Find_Libraries#Writing_find_modules
但我通常使用与上面描述的略有不同的find脚本(FindMyLibrary.cmake):
# Find MyLibrary installation
#
# This module needs following variables specified (e.g. through cmake -Dvar=)
# MyLibrary_ROOT_DIR - root directory of the library installation
#
# This module defines the following variables:
# MyLibrary_INCLUDE_DIRS - Where to find the public headers
# MyLibrary_LIBRARIES - List of mandatory and optional libraries
# MyLibrary_FOUND - True if an installation was found
#
# Configuration variables for tis module:
# MyLibrary_USE_STATIC_LIBS - Set to ON to force the use of the static
# libraries. Default is OFF.
# If MyLibrary_ROOT_DIR was defined in the environment, use it.
if(NOT MyLibrary_ROOT_DIR AND NOT $ENV{MyLibrary_ROOT_DIR} STREQUAL "")
set(MyLibrary_ROOT_DIR $ENV{MyLibrary_ROOT_DIR})
endif()
if(NOT MyLibrary_ROOT_DIR)
set(MyLibrary_ROOT_DIR /usr)
endif()
message(STATUS "Using MyLibrary_ROOT_DIR: ${MyLibrary_ROOT_DIR}")
find_path(MyLibrary_INCLUDE_DIRS
NAMES mylib/mylib.hpp
PATHS ${MyLibrary_ROOT_DIR}
PATH_SUFFIXES include)
# Here we set the default components
if(NOT MyLibrary_FIND_COMPONENTS)
set(MyLibrary_FIND_COMPONENTS mylibrary)
endif()
# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
if(MyLibrary_USE_STATIC_LIBS)
set(_mylib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
if(WIN32)
set(CMAKE_FIND_LIBRARY_SUFFIXES .lib .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
else()
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
endif()
foreach(COMPONENT ${MyLibrary_FIND_COMPONENTS})
find_library(MyLibrary_${COMPONENT}_LIBRARY
NAMES ${COMPONENT}
HINTS ${MyLibrary_ROOT_DIR}
PATH_SUFFIXES lib64 lib
NO_DEFAULT_PATH)
set(MyLibrary_LIBRARIES ${MyLibrary_LIBRARIES} ${MyLibrary_${COMPONENT}_LIBRARY})
endforeach()
# Restore the original find library ordering
if(MyLibrary_USE_STATIC_LIBS)
set(CMAKE_FIND_LIBRARY_SUFFIXES ${_mylib_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES})
endif()
# handle the QUIETLY and REQUIRED arguments and set MyLibrary_FOUND to
# TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(
MyLibrary "Could NOT find MyLibrary: set MyLibrary_ROOT_DIR to a proper location"
MyLibrary_LIBRARIES
MyLibrary_INCLUDE_DIRS)
mark_as_advanced(MyLibrary_INCLUDE_DIRS MyLibrary_LIBRARIES)
然后这样使用:
find_package(MyLibrary REQUIRED)
include_directories(SYSTEM ${MyLibrary_INCLUDE_DIRS})
target_link_libraries(${TARGET}
${MyLibrary_LIBRARIES}
)
基本上是这样的:
- 库被构建并安装(makeinstall)到默认位置(例如/usr)或其他位置(通常在开发中)
- FindMyLibrary.cmake是库安装的一部分(对于RPM,为library-devel包),也会安装(例如,安装到${instdir}/share/cmake/Modules中)
- 然后,依赖项目将路径添加到CMAKE_MODULE_path,并使用查找脚本查找已安装的公共标头和库
这样做的好处是,您既可以在开发过程中使用它(当您拥有库源代码并构建库时),也可以不使用库源代码(只在系统中安装库和头文件-devel包)。
Boost等通常使用类似的技术(查找脚本已经由CMake提供)。
对于target_link_libraries
,使用库目标而不是库的路径。
假设您的图书馆项目包含
add_library(MyLib ...)
主项目中可执行文件的链接应使用进行
target_link_libraries(test MyLib)
首先,这不起作用,因为在子目录中设置的变量不是为父目录设置的。
因此,为了正确解决这个问题,你应该定义MyLib,比如:
add_library(MyLib ...)
target_include_directories(MyLib INTERFACE ${PROJECT_SOURCE_DIR}/include)
对于ExternP,您只需要链接到MyLib:
target_link_libraries(test MyLib)
这将自动将include目录添加到test并正确链接MyLib。
- 将公共但非静态的成员函数与ALGLIB集成
- 将IBM Rhapsody模型集成到VS 2019中
- 从R调用C++函数并对其进行集成时出错
- 如何集成 HID USB 控制器?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 通过 CMake 添加子项目
- 将Qt集成到现有的VS项目中以取代WinAPI
- 将 Crashpad 与 Windows Qt 应用程序集成
- Python3.6 模板中的 CGAL C++ 集成错误
- 为什么子项目 CMAKE 不考虑 fno-sanitize,请禁用目标的消毒器
- 基本 Cuda C++项目集成问题
- 如何使用CMake将QtMultimedia组件集成到项目中?
- 在 Mac OS 中将 QT 与 CMAKE 集成
- 使用 GSL 库制作样条曲线并使用它们进行集成
- 在集成终端上运行vscode lldb调试器时,如何获取程序的输出?
- 将Emscripten集成到Clion中
- VIsual Studio:避免控制台弹出,而是将其集成到IDE中
- 包括在子项目中
- 将CMake子项目与另一个子项目集成
- 将非c++子项目集成到CMake项目中