【发布时间】:2020-09-24 07:51:03
【问题描述】:
我正在构建一个应用程序,它使用 tinyxml2 和一些其他依赖项(即 Irrlicht 和 IrrKlang),这些依赖项是我在项目的 Dependency 子目录中作为 .zip 文件提供的:
.
├── CMakeLists.txt
├── Dependencies
│ ├── irrKlang-1.5.0.zip
│ ├── irrKlang-32bit-1.5.0.zip
│ ├── irrKlang-64bit-1.5.0.zip
│ ├── irrlicht-1.8.4.zip
│ └── tinyxml2-master.zip
├── Editor
│ ├── CMakeLists.txt
│ └── Sources
│ └── main.cpp
└── Game
├── CMakeLists.txt
└── Sources
└── main.cpp
注意:仅供参考,可提供完整的资源on GitHub,在这里我偷工减料以缩短问题。
顶层CMakeFiles.txt设置为:
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
project(shoot-them VERSION 1.0.1 LANGUAGES CXX)
include(ExternalProject)
# few platform-specific variables like MAKE_COMMAND, PLATFORM_ARCH, etc.
# libraries (see below)
add_subdirectory(Game)
add_subdirectory(Editor
Irrlicht 和 IrrKlang 都带有适用于 x86 的 Windows 的预构建库,但不适用于 Windows x64 和 OSX。因此我将它添加为这样的依赖项(使用if(NOT IRRLICHT_LIBRARY_PATH) 只是为了将代码分成一个块:
if(NOT IRRLICHT_LIBRARY_PATH)
ExternalProject_Add(irrlicht-dep
URL ${CMAKE_CURRENT_LIST_DIR}/Dependencies/irrlicht-1.8.4.zip
PREFIX Dependencies/irrlicht
SOURCE_SUBDIR source/Irrlicht
CONFIGURE_COMMAND ""
BUILD_COMMAND "${MAKE_COMMAND}"
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(irrlicht-dep SOURCE_DIR)
set(IRRLICHT_PATH ${SOURCE_DIR})
add_library(irrlicht SHARED IMPORTED GLOBAL)
set_target_properties(
irrlicht PROPERTIES
IMPORTED_LOCATION ${IRRLICHT_PATH}/lib/${IRRLICHT_PATH_SUFFIX}/Irrlicht${CMAKE_LINK_LIBRARY_SUFFIX}
IMPORTED_IMPLIB ${IRRLICHT_PATH}/lib/${IRRLICHT_PATH_SUFFIX}/Irrlicht${CMAKE_IMPORT_LIBRARY_SUFFIX}
INTERFACE_INCLUDE_DIRECTORIES ${IRRLICHT_PATH}/include
)
endif()
我对@987654335@ 遵循相同的原则。但是由于tinyxml2 是作为头文件和源文件出现的,并且它包含CMakeLists.txt,所以我只是这样包含它:
ExternalProject_Add(tinyxml2-dep
URL ${CMAKE_CURRENT_LIST_DIR}/Dependencies/tinyxml2-master.zip
PREFIX Dependencies/tinyxml2
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(tinyxml2-dep SOURCE_DIR)
set(TINYXML2_PATH ${SOURCE_DIR})
add_subdirectory(${TINYXML2_PATH})
我将Game 和Editor 子项目定义如下:
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
project(Editor VERSION 1.0.1 LANGUAGES CXX)
set(EXECUTABLE_NAME Editor)
set(SOURCES Sources/main.cpp)
# platform-specific variables
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
)
add_dependencies(${EXECUTABLE_NAME} tinyxml2 irrlicht)
target_link_libraries(${EXECUTABLE_NAME} PUBLIC ${LIBRARIES} tinyxml2 irrlicht)
if(NOT APPLE)
# Copy libraries' DLLs
add_custom_command(
TARGET ${EXECUTABLE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:tinyxml2> $<TARGET_FILE_DIR:${EXECUTABLE_NAME}>
)
endif()
# TODO: copy DLLs, not LIBs
add_custom_command(
TARGET ${EXECUTABLE_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:irrlicht> $<TARGET_FILE_DIR:${EXECUTABLE_NAME}>
)
我使用ExternalProject的方式具体是因为
- 我想修复我构建项目时使用的版本
- 我不想通过安装库来污染我的系统(因此没有
INSTALL步骤,尽管我可能完全误解了这个概念) - 我不依赖 3rd 方存储库已死(因此将 ZIP 文件与源代码一起发送)
- 我不依赖令人难以置信的过时(因此可能无法正常工作)查找 CMake 模块
公平地说:我不知道使用 CMake 构建项目的任何最佳实践,所以我很可能对以上所有内容都完全错误,所以请纠正我。 p>
当我在 Windows 上的 Visual Studio 2019 中构建这个项目时,它就像一个魅力。但是每当我尝试在 OSX 上构建这个东西时,我都会失败:
- 任何依赖项都没有被解包
-
(因为 p.1)
${TINYXML2_DIR}永远不会设置 -
(因为 p.2) 找不到
tinyxml2目录,因此通过add_subdirectory()添加 -
(因为第 3 页)
$<TARGET_FILE:tinyxml2>表达式不计算 - (作为全球性后果) 项目未构建
我构建项目的方式比较简单:
cmake -Bbuild -H. && cmake --build build
我做错了什么?
另外,使用 CMake 处理 3rd 方依赖项的正确方法是什么?
我非常清楚 CMake 在技术上只是一个 makefile(粗略地说,因为每个构建工具链都不同)生成器,所以我的问题更多关于我如何告诉 CMake 为应该使用我的项目构建的每种类型的依赖项生成正确的构建文件(预构建,使用 CMake 从源构建,使用自定义命令从源构建)。我认为ExternalProject 应该可以处理这个问题,但显然在此过程中出现了可怕的错误。
【问题讨论】:
-
您应该尝试在配置时使用 FetchContent(),因为 ExternalProject 是在构建时执行的,或者您需要使用此技巧在配置时强制外部项目:crascit.com/2015/07/25/cmake-gtest
标签: c++ macos visual-studio cmake dependency-management