我写了一个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
的依赖关系?
答案 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}
)
基本上,它是这样的:
这样做的好处是你可以在开发过程中使用它(当你有库源并构建库时),或者没有库源(只有库和头文件--devel包安装)在系统中)。
类似的技术通常由Boost等使用(CMake已经提供的查找脚本)。