如何在CMake中获取适配不同IDE的目标输出文件目录?
问题
- 在Visual Studio 2022中打开CMake项目,选择x64-Debug配置时,构建目录为
<project_directory>\out\build\x64-Debug,可执行文件及依赖DLL直接存放在该目录下。 - 在Visual Studio Code中,CMake扩展默认在
<project_directory>\build创建构建目录,执行cmake --build后,输出文件存放在<project_directory>\build\Debug。
需要添加自定义目标将源目录中的文件复制到输出目录或其子目录,但遇到以下问题:
- 使用
CMAKE_CURRENT_BINARY_DIR时,在VS2022中正常工作,但在cmake --build构建场景下失效。 - 尝试追加
$<CONFIG>后,cmake --build场景可用,但VS2022中失效。
请问是否存在能通用获取构建输出路径的变量或表达式?
当前CMakeLists.txt代码
cmake_minimum_required(VERSION 3.10) set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake CACHE STRING "Vcpkg toolchain file") # set the project name project(sdl2-gl-project-template) # add the executable add_executable(main "main.cpp" "scene.hpp" "scene.cpp" "io_util.hpp" "shader.hpp" "shader.cpp") find_package(SDL2 CONFIG REQUIRED) find_package(OpenGL REQUIRED) find_package(imgui CONFIG REQUIRED) find_package(gl3w CONFIG REQUIRED) find_package(glm CONFIG REQUIRED) find_package(spdlog CONFIG REQUIRED) find_package(fmt CONFIG REQUIRED) find_package(imguizmo CONFIG REQUIRED) target_link_libraries(main PRIVATE SDL2::SDL2 SDL2::SDL2main OpenGL::GL imgui::imgui imguizmo::imguizmo unofficial::gl3w::gl3w spdlog::spdlog spdlog::spdlog_header_only fmt::fmt fmt::fmt-header-only) target_compile_features(main PRIVATE cxx_std_20) set_property(TARGET main PROPERTY CXX_STANDARD 20) set_property(TARGET main PROPERTY CXX_STANDARD_REQUIRED ON) if (MSVC) # set_property(TARGET main PROPERTY WIN32_EXECUTABLE ON) target_compile_options(main PRIVATE /Zc:__cplusplus) endif() function(compile_shaders) set(oneValueArgs TARGET TARGET) set(multiValueArgs TARGET INPUT) set(oneValueArgs DESTINATION DESTINATION) cmake_parse_arguments(COMPILE_SHADERS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) file(GLOB GLSL_SOURCE_FILES ${COMPILE_SHADERS_INPUT}) add_custom_target(${COMPILE_SHADERS_TARGET} COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_SHADERS_DESTINATION}/" COMMAND ${CMAKE_COMMAND} -E copy ${GLSL_SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/${COMPILE_SHADERS_DESTINATION}/" ) add_dependencies(main ${COMPILE_SHADERS_TARGET}) endfunction() compile_shaders( TARGET CompileBasicShader DESTINATION "shaders/frag" INPUT "shaders/shader.vert" "shaders/shader.frag" )
解决方案
使用CMake的生成器表达式 $<TARGET_FILE_DIR:main>,它能直接获取目标main的可执行文件所在的输出目录,无论你是在VS2022还是VSCode中构建,这个表达式都会自动适配正确的路径。
修改后的compile_shaders函数如下:
function(compile_shaders) set(oneValueArgs TARGET DESTINATION) set(multiValueArgs INPUT) cmake_parse_arguments(COMPILE_SHADERS "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) file(GLOB GLSL_SOURCE_FILES ${COMPILE_SHADERS_INPUT}) # 获取目标可执行文件的输出目录 set(OUTPUT_DIR "$<TARGET_FILE_DIR:main>/${COMPILE_SHADERS_DESTINATION}") add_custom_target(${COMPILE_SHADERS_TARGET} COMMAND ${CMAKE_COMMAND} -E make_directory "${OUTPUT_DIR}" COMMAND ${CMAKE_COMMAND} -E copy ${GLSL_SOURCE_FILES} "${OUTPUT_DIR}" ) add_dependencies(main ${COMPILE_SHADERS_TARGET}) endfunction()
关键说明
$<TARGET_FILE_DIR:main>是CMake生成器表达式,会在构建阶段动态解析为main可执行文件的实际存放目录,完美适配VS2022的<project_directory>\out\build\x64-Debug和VSCode的<project_directory>\build\Debug两种场景。- 同时修复了原函数中
cmake_parse_arguments的参数定义错误(重复定义TARGET参数类型),确保参数解析逻辑正确。
内容的提问来源于stack exchange,提问作者Wutipong Wongsakuldej
相关产品推荐
相关产品推荐

