将CMake子项目与另一个子项目集成

时间:2016-05-18 07:21:18

标签: c++ cmake

我写了一个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_LIBRARIESMyLib_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的依赖关系?

3 个答案:

答案 0 :(得分:1)

使用库目标代替target_link_libraries

的路径。

假设您的图书馆项目包含

add_library(MyLib ...)

主项目中可执行文件的链接应该用

执行
target_link_libraries(test MyLib)

答案 1 :(得分:1)

首先,这不起作用,因为没有为父目录设置子目录中设置的变量。

所以要正确解决这个问题,你应该像MyLib一样定义:

add_library(MyLib ...)
target_include_directories(MyLib INTERFACE ${PROJECT_SOURCE_DIR}/include)

对于ExternPro,您只需链接到MyLib:

target_link_libraries(test MyLib)

这会自动将include目录添加到测试并正确链接MyLib。

答案 2 :(得分:1)

如果这些是两个独立的项目,我通常使用“CMake find scripts”来引用另一个库:http://www.vtk.org/Wiki/CMake:How_To_Find_Libraries#Writing_find_modules

但我通常使用略微不同的查找脚本(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}
)

基本上,它是这样的:

  1. 构建并安装(安装)库到默认位置(例如/ usr)或其他位置(通常在开发中)。
  2. FindMyLibrary.cmake是库安装的一部分(对于RPM的库devel包)并安装(例如,在$ {instdir} / share / cmake / Modules中)。
  3. 依赖项目然后将路径添加到CMAKE_MODULE_PATH,并使用find脚本查找已安装的公共标头和库。
  4. 这样做的好处是你可以在开发过程中使用它(当你有库源并构建库时),或者没有库源(只有库和头文件--devel包安装)在系统中)。

    类似的技术通常由Boost等使用(CMake已经提供的查找脚本)。