You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual Studio自定义构建工具每次仅生成一个SVG转头文件

问题:VS自定义构建工具每次仅处理一个SVG文件,多次构建才能完成转换

问题背景

编写了一个批处理文件svg_header.bat,用于将SVG文件转换为C++头文件,代码如下:

echo %1 -> %2
@(
    echo const char *%~n1_svg = R"***(
    type %~1
    echo ^)***";
) > %~2

执行示例:svg_header.bat images\normal.svg images\normal_svg.h,生成的头文件可通过#include "images\\normal_svg.h"在C++代码中引用。

在Visual Studio项目中添加了3个SVG文件,并为它们配置了Custom Build Tool,但出现异常:每次构建项目时仅能成功处理一个文件,第一次构建输出如下:

Build started...
1>------ Build started: Project: mic_muter, Configuration: Debug x64 ------
1>SVG to Header microphone_mute
1>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(247,5): warning MSB8065: Custom build for item "images\microphone_normal.svg" succeeded, but specified output "u:\dev\hid_kbd\mic_muter\mic_muter\images\microphone_normal_svg.h" has not been created. This may cause incremental build to work incorrectly.
1>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets(247,5): warning MSB8065: Custom build for item "images\microphone_base.svg" succeeded, but specified output "u:\dev\hid_kbd\mic_muter\mic_muter\images\microphone_base_svg.h" has not been created. This may cause incremental build to work incorrectly.
1>mic_muter.cpp
1>U:\dev\hid_kbd\mic_muter\mic_muter\mic_muter.cpp(5,10): fatal  error C1083: Cannot open include file: 'images/microphone_normal_svg.h': No such file or directory
1>Done building project "mic_muter.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========

再次构建会处理下一个文件,第三次构建才能完成所有文件转换,项目构建成功。

每个SVG文件在.vcxproj中的配置段基本一致(仅源文件名不同):

<CustomBuild Include="images\microphone_mute.svg">
      <FileType>Document</FileType>
      <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</DeploymentContent>
      <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</DeploymentContent>
      <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</DeploymentContent>
      <DeploymentContent Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</DeploymentContent>
      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">SVG to Header %(Filename)</Message>
      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">SVG to Header %(Filename)</Message>
      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">SVG to Header %(Filename)</Message>
      <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SVG to Header %(Filename)</Message>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)images\%(Filename)_svg.h</Outputs>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)images\%(Filename)_svg.h</Outputs>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)images\%(Filename)_svg.h</Outputs>
      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)images\%(Filename)_svg.h</Outputs>
      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)svg_to_header.bat %(FullPath) $(ProjectDir)images\%(Filename)_svg.h</Command>
      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)svg_to_header.bat %(FullPath) $(ProjectDir)images\%(Filename)_svg.h</Command>
      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)svg_to_header.bat %(FullPath) $(ProjectDir)images\%(Filename)_svg.h</Command>
      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)svg_to_header.bat %(FullPath) $(ProjectDir)images\%(Filename)_svg.h</Command>
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(ProjectDir)svg_to_header.bat</AdditionalInputs>
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(ProjectDir)svg_to_header.bat</AdditionalInputs>
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(ProjectDir)svg_to_header.bat</AdditionalInputs>
      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(ProjectDir)svg_to_header.bat</AdditionalInputs>
      <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</LinkObjects>
      <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkObjects>
      <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">false</LinkObjects>
      <LinkObjects Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkObjects>
      <OutputItemType Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">ClInclude</OutputItemType>
      <OutputItemType Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">ClInclude</OutputItemType>
      <OutputItemType Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">ClInclude</OutputItemType>
      <OutputItemType Condition="'$(Configuration)|$(Platform)'=='Release|x64'">ClInclude</OutputItemType>
      <VerifyInputsAndOutputsExist Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</VerifyInputsAndOutputsExist>
      <VerifyInputsAndOutputsExist Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</VerifyInputsAndOutputsExist>
      <VerifyInputsAndOutputsExist Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</VerifyInputsAndOutputsExist>
      <VerifyInputsAndOutputsExist Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</VerifyInputsAndOutputsExist>
    </CustomBuild>

原因分析

  1. MSBuild并行构建冲突:Visual Studio默认启用并行构建,多个Custom Build任务会同时执行,批处理文件在写入输出文件时可能遭遇文件系统竞争条件(如临时文件锁定、输出流混乱),导致部分文件写入失败,但批处理进程返回的退出码仍为0,MSBuild误认为任务成功,仅在下次构建时重试。
  2. 批处理文件路径未加引号:批处理中重定向目标路径未用引号包裹,若路径包含空格或特殊字符(即使当前路径无空格,也可能因MSBuild传递参数的方式触发问题),会导致文件写入失败。
  3. 批处理文件名不一致(可能笔误):问题描述中批处理文件名为svg_header.bat,但项目配置中命令调用的是svg_to_header.bat,若实际文件未重命名,会导致部分任务无法找到脚本,输出文件无法生成。

解决方案

1. 修复批处理文件

修改svg_header.bat,添加引号包裹路径,避免路径解析错误,并关闭多余输出:

@echo off
echo %1 -> %2
@(
    echo const char *%~n1_svg = R"***(
    type "%~1"
    echo ^)***";
) > "%~2"

2. 禁用并行构建

在项目文件.vcxproj的<PropertyGroup>节点中添加以下配置,强制MSBuild串行处理自定义构建任务:

<DisableParallelBuilds>true</DisableParallelBuilds>

或针对单个CustomBuild项添加:

<DisableParallelBuilds>true</DisableParallelBuilds>

3. 修正批处理文件名(若存在笔误)

确保项目配置中Command节点调用的批处理文件名与实际文件名一致,比如将配置中的svg_to_header.bat改为svg_header.bat。

验证

修改后执行一次完整构建,所有SVG文件应被一次性转换为对应的头文件,项目构建成功,无MSB8065警告及文件找不到错误。

内容的提问来源于stack exchange,提问作者Charlie Skilbeck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:41:31