使用具有外部依赖性的库构建多个子项目
Build of multiple subprojects with library that has external dependency
我正在努力处理一个包含 CMake(版本 3.11)和子目录的项目。它包括 ITK 作为外部库。
我想创建可以在不同子目录(如 MyApp)中使用的库,以构建基于 MyLib 的多个应用程序,并且 MyLib 中的每个更改都会在其他应用程序中更新。 MyLib 是一个 header-only 模板化库。另外这类库在VisualStudio中没有自己的项目。
我的问题是:
- 在这种情况下使用 CMake 的正确方法是什么?我已经搜索并尝试了一些示例但没有成功。理想情况下,我可以独立地构建依赖于 MyLib 的应用程序。顶部 CMakeLists.txt 可能不会从库中提取包含。这应该由应用程序完成。
- 如果 MyLib 变成一个非header-only库会有什么变化?将来我可能会添加非模板化类.
加分题:
- 如何将header-only库添加到VisualStudio中?这是一个方便的问题。
感谢任何帮助,如有必要,我可以提供更多详细信息。
源环境是这样的:
ProjectDirectory
- CMakeLists.txt
-- MyLib
- CMakeLists.txt
-- include
- File1.h (template header)
- File1.hxx (template body)
-- src
- (empty for now)
-- MyApp
- CMakeLists.txt
- AppFile1.cxx (File containing main function)
这是一个 out-of-source-build 项目。理想情况下,编译的库和应用程序放在这样的目录中(在 Windows 上):
└── bin
├── Debug
│ ├── MyApp.exe
│ └── MyLib.lib
└── Release
├── MyApp.exe
└── MyLib.lib
项目目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(project_name)
# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
add_subdirectory(MyLib)
add_subdirectory(MyApp)
MyLib CMakeLists.txt:
find_package(ITK REQUIRED
COMPONENTS RTK ITKImageIO)
include(${ITK_USE_FILE})
set(HDRS
${CMAKE_CURRENT_SOURCE_DIR}/include/File1.h
${CMAKE_CURRENT_SOURCE_DIR}/include/File1.hxx
)
add_library(MyLib ${HDRS})
target_include_directories(MyLib
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
src)
target_link_libraries(MyLib
PUBLIC ${ITK_LIBRARIES})
export(TARGETS MyLib FILE MyLibConfig.cmake)
MyAppCMakeLists.txt
find_package(ITK REQUIRED
COMPONENTS RTK ITKRegistrationMethodsv4 ITKTransformIO ITKImageIO)
include(${ITK_USE_FILE})
set(SRCS
AppFile1.cxx)
add_executable(MyApp ${SRCS})
include_directories(${CMAKE_SOURCE_DIR}/MyLib/include)
target_link_libraries(MyApp
${ITK_LIBRARIES}
MyLib)
Edit1:从 MyLib 和 MyApp CMakeLists.txt 中删除项目 (X) 并将目标更改为 MyLib。
您可以有一个空项目,只需创建一个自定义目标即可:
add_custom_target(MyLib SOURCES ${CMAKE_MYLIB_SRC} ${CMAKE_MYLIB_HDR})
由于您的代码仅为 header,因此任何依赖目标都将看到文件中的更改并重新编译。除此之外无事。您不必创建目标,尽管对于您的第三个问题,这就是答案。
但是如果 ITK 只是你的依赖项,既然你有一个目标,你可以在它上面添加 PUBLIC
属性,比如因为你的库需要链接到它的依赖库。
在这种情况下,他们的代码需要添加:
target_link_library(${NEWTARGET} PRIVATE MyLib) # PUBLIC/PRIVATE has to be tailored
这就是问题 1 的答案。
如果您的图书馆变为 non-header,只需更改 add_custom_target
调用即可。
我正在努力处理一个包含 CMake(版本 3.11)和子目录的项目。它包括 ITK 作为外部库。
我想创建可以在不同子目录(如 MyApp)中使用的库,以构建基于 MyLib 的多个应用程序,并且 MyLib 中的每个更改都会在其他应用程序中更新。 MyLib 是一个 header-only 模板化库。另外这类库在VisualStudio中没有自己的项目。
我的问题是:
- 在这种情况下使用 CMake 的正确方法是什么?我已经搜索并尝试了一些示例但没有成功。理想情况下,我可以独立地构建依赖于 MyLib 的应用程序。顶部 CMakeLists.txt 可能不会从库中提取包含。这应该由应用程序完成。
- 如果 MyLib 变成一个非header-only库会有什么变化?将来我可能会添加非模板化类.
加分题:
- 如何将header-only库添加到VisualStudio中?这是一个方便的问题。
感谢任何帮助,如有必要,我可以提供更多详细信息。
源环境是这样的:
ProjectDirectory
- CMakeLists.txt
-- MyLib
- CMakeLists.txt
-- include
- File1.h (template header)
- File1.hxx (template body)
-- src
- (empty for now)
-- MyApp
- CMakeLists.txt
- AppFile1.cxx (File containing main function)
这是一个 out-of-source-build 项目。理想情况下,编译的库和应用程序放在这样的目录中(在 Windows 上):
└── bin
├── Debug
│ ├── MyApp.exe
│ └── MyLib.lib
└── Release
├── MyApp.exe
└── MyLib.lib
项目目录CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(project_name)
# Setup build locations.
if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
endif()
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
endif()
add_subdirectory(MyLib)
add_subdirectory(MyApp)
MyLib CMakeLists.txt:
find_package(ITK REQUIRED
COMPONENTS RTK ITKImageIO)
include(${ITK_USE_FILE})
set(HDRS
${CMAKE_CURRENT_SOURCE_DIR}/include/File1.h
${CMAKE_CURRENT_SOURCE_DIR}/include/File1.hxx
)
add_library(MyLib ${HDRS})
target_include_directories(MyLib
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE
src)
target_link_libraries(MyLib
PUBLIC ${ITK_LIBRARIES})
export(TARGETS MyLib FILE MyLibConfig.cmake)
MyAppCMakeLists.txt
find_package(ITK REQUIRED
COMPONENTS RTK ITKRegistrationMethodsv4 ITKTransformIO ITKImageIO)
include(${ITK_USE_FILE})
set(SRCS
AppFile1.cxx)
add_executable(MyApp ${SRCS})
include_directories(${CMAKE_SOURCE_DIR}/MyLib/include)
target_link_libraries(MyApp
${ITK_LIBRARIES}
MyLib)
Edit1:从 MyLib 和 MyApp CMakeLists.txt 中删除项目 (X) 并将目标更改为 MyLib。
您可以有一个空项目,只需创建一个自定义目标即可:
add_custom_target(MyLib SOURCES ${CMAKE_MYLIB_SRC} ${CMAKE_MYLIB_HDR})
由于您的代码仅为 header,因此任何依赖目标都将看到文件中的更改并重新编译。除此之外无事。您不必创建目标,尽管对于您的第三个问题,这就是答案。
但是如果 ITK 只是你的依赖项,既然你有一个目标,你可以在它上面添加 PUBLIC
属性,比如因为你的库需要链接到它的依赖库。
在这种情况下,他们的代码需要添加:
target_link_library(${NEWTARGET} PRIVATE MyLib) # PUBLIC/PRIVATE has to be tailored
这就是问题 1 的答案。
如果您的图书馆变为 non-header,只需更改 add_custom_target
调用即可。