如何在 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)
我正在使用 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)