如何在 CMake 生成的解决方案中使用相对路径打开源代码中的文件

How to use relative paths to open files in source code in CMake generated solution

我正在使用 CMake 生成一个可执行文件和几个库。我已将可执行文件和所有库的输出文件夹指定到一个公共 "bin" 文件夹。

使用:

set_target_properties (${PROJ} 
   PROPERTIES
   ARCHIVE_OUTPUT_DIRECTORY_DEBUG "${BIN_DIR}"
   ARCHIVE_OUTPUT_DIRECTORY_RELEASE "${BIN_DIR}"
   RUNTIME_OUTPUT_DIRECTORY_DEBUG "${BIN_DIR}"
   RUNTIME_OUTPUT_DIRECTORY_RELEASE "${BIN_DIR}"
   LIBRARY_OUTPUT_DIRECTORY_DEBUG "${BIN_DIR}"
   LIBRARY_OUTPUT_DIRECTORY_RELEASE "${BIN_DIR}"
)

在其中一个库中,我正在使用相对路径打开一个资源文件。此路径相对于 "bin" 文件夹 .//Resources//file.jpg(因为 Resources 文件夹位于 bin 文件夹中)。

当我 运行 来自 visual studio 调试器的 exe 时,我看到它正确 运行s 来自 bin 文件夹的 exe 但当它试图打开 file.jpg,它在相对于 CMAKE_BINARY_DIR 的路径中查找。所以,CMAKE_BINARY_DIR/Resources/file.jpg。因此,我收到 运行 次错误,提示未找到文件。

解决这个问题的最佳方法是什么?我不想复制 CMAKE_BINARY_DIR 中的所有资源。似乎应该有更好的方法。

提前感谢您的帮助。

要解决您的问题,您需要在 Visual Studio 项目属性中设置正确的调试工作目录。它应该是 $(TargetDir) 而不是默认的 $(ProjectDir).


为避免每次生成干净的解决方案时都必须手动修改设置,您可以使用 CONFIGURE_FILE 预先生成默认的 .user 文件。

例如,我将以下模板用于我的 VS 2013 项目设置:

  • 当运行调试器中的应用
  • 时使用的默认命令行参数
  • 要使用的工作目录(所有配置共享一个)
  • 调整 PATH 以包含具有所有预构建依赖项和符号的目录

文件${ROOT}/build/template/executable_vs12.vcxproj.user:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|Win32'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='MinSizeRel|x64'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
    <LocalDebuggerCommandArguments>-D20</LocalDebuggerCommandArguments>
    <LocalDebuggerWorkingDirectory>$(TargetDir)\..\..\common\</LocalDebuggerWorkingDirectory>
    <LocalDebuggerEnvironment>PATH=$(SolutionDir)..\deps\bin;$(Path)
$(LocalDebuggerEnvironment)</LocalDebuggerEnvironment>
    <DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
  </PropertyGroup>
</Project>

接下来,我有一个简单的 .cmake 文件,可以包含它并包装配置步骤。

文件${ROOT}/build/debugger_config.cmake

IF(NOT COMMON_BUILD_DEBUGGER_CONFIG_INCLUDED)
SET(COMMON_BUILD_DEBUGGER_CONFIG_INCLUDED TRUE)
# =============================================================================
FUNCTION(CONFIGURE_DEBUGGER TARGET_NAME)
  CONFIGURE_FILE(${ROOT}/build/template/executable_vs12.vcxproj.user
    ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}.vcxproj.user
    @ONLY
    )
ENDFUNCTION(CONFIGURE_DEBUGGER)
# =============================================================================
ENDIF(NOT COMMON_BUILD_DEBUGGER_CONFIG_INCLUDED)

最后,我在每个可执行目标定义之后调用此函数:

# This can go in top-level CMakeLists.txt
INCLUDE(${ROOT}/build/debugger_config.cmake)

# ...

ADD_EXECUTABLE(foo
  ${FOO_FILES}
)
CONFIGURE_DEBUGGER(foo)