为什么我使用 Cmake build 和 VS 2019 build 时相对路径不同?

why the relative path is different when I use Cmake build and VS 2019 build?

我是 Cmake 的新手。我尝试使用 Cmake 构建我的项目。

在我的项目中,我需要在运行时间内加载一些资源。例如:

string inFileName = "../Resources/resource.txt";
// string inFileName = "../../Resources/resource.txt";
ifstream ifs;
ifs.open(inFileName.c_str());
if (ifs) {
....
}

但是当我在project/build中使用命令行cmake ../cmake --build . --config Release时。我的文件路径应该是相对于 ${PROJEDCT_BINARY},即 inFileName = "../resources/resource.txt".

但是当我使用 cmake ../ 并用 VS2019 打开 sln 文件然后右键单击构建和 运行 时,我的文件路径应该是相对于可执行文件的,即 inFileName = "../../resources/resource.txt" .

不知道为什么会这样,网上搜了一下,好像没人遇到过这种傻问题...

下面是我的文件结构。

|--3rdParty
|----CmakeLists.txt
|--include
|----header.h
|--source
|----source.cpp
|----CmakeLists.txt
|--resources
|----resource.txt
|--CmakeLists

和我的根CmakeLists.txt

cmake_minimum_required(VERSION 3.12)

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

project(OBMI VERSION 0.1.0.0 LANGUAGES C CXX CUDA)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})

add_subdirectory(3rdParty)

add_subdirectory(source)

source/CmakeLists.txt

add_executable(mSI)

target_sources(mSI PRIVATE
    ${PROJECT_SOURCE_DIR}/include/header.h
    # source
    source.cpp
)

target_include_directories(multiSpectrumImaging 
    PRIVATE 
    ${PROJECT_SOURCE_DIR})

target_link_libraries(mSI
    PRIVATE
    ...
)

通过生成 MSVS 解决方案文件,您 (CMake) 为生成解决方案(和项目)的 MSVS 创建工作环境。因此,与那里相关的所有内容都与生成的文件有关,就 MSVS 而言,该目录是世界的中心。这就是为什么你应该努力使用绝对路径而不是相对路径。

要实现这一点,CMake 有一堆变量,您使用的 PROJECT_SOURCE_DIR 就是其中之一。但是,有一个似乎更适合您的情况:CMAKE_SOURCE_DIR.

因此,每当您需要使用资源时,请在 CMake 脚本中使用以下路径:"${CMAKE_SOURCE_DIR}/resources/resources.txt"


如果您需要在运行时加载资源,那么它超出了 CMake 及其功能。您应该将这些资源与生成的二进制文件相关联,因为它们在项目中的位置不再重要。 CMake 通过提供 install and file(COPY ...) 来帮助它。前者主要用于应用程序的打包过程,而后者可能用于开发过程以减轻负担。

例如,您可以在项目 (source/CmakeLists.txt) CMake 文件中包含以下内容:

file(COPY "${CMAKE_SOURCE_DIR}/resources" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")

应该将 resources 文件夹放在创建二进制文件的位置。

使用相对路径加载文件时,最终文件名的解析取决于当前工作目录。相对路径附加到该工作目录。当前工作目录不一定与您的应用程序路径相同;它将是启动应用程序的周围环境的路径(或者可以专门为大多数 IDE 中的调试环境设置)。

当您 运行 它 而不是 来自 IDE 时,您没有具体说明 运行 您的程序 - 只是 double-clicking 可能是可执行文件?您也不告诉我们与您的源相关的可执行文件是在哪里构建的?

特别是 运行ning 来自 Visual Studio,您可以在项目属性的“调试”部分中设置工作目录。

对于更灵活的解决方案,我通常做的是确定可执行文件的路径,然后将加载资源的相对路径附加到该路径。 基本上,完整的可执行路径存储在 argv[0] 中(如果您有 int main(int argc, char** argv) {...},即主函数第二个参数的第一个元素)。有关这方面的更多信息,请参阅 the answers to this other question.

示例