自定义构建的 <Outputs> 标签检查目录的规则在 Visual Studio 2019 年更改了吗?
Rules for Custom build's <Outputs> tag check for directories changed in Visual Studio 2019?
让晦涩难懂的问题变得简单...
我们有一个由许多项目组成的解决方案,其中一些项目使用 3rd 方的东西设置了自定义构建事件以进行一些黑魔法编译,看起来类似于:
<CustomBuild Include="..\folder\somestuff.xyz">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Tcl\bin\tclsh.exe $(APP_PATH)\modules\APP\bin\generator.tcl -o %(RelativeDir)%(Filename) %(RelativeDir)%(Filename).xyz</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">APPGEN %(RelativeDir)%(Filename)</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
</CustomBuild>
在我们从 VS2015 切换到 VS2019 之前,它一直正常工作,因为现在在编译期间它报告说:
Project is not up-to-date: build output 'd:\projects\program\app\src\plugins\shared\' is missing
。这或多或少没问题,但它会强制编译器重新编译该项目的依赖项,这开始变得非常烦人,因为即使没有进行任何更改,您每次都需要重建多个项目。
我发现问题出在自定义构建的这一行:
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
从这部分更准确地说:%(RelativeDir)%(Outputs) 作为 .cpp 和 [=29= 的检查.h 文件在同一个标签中不会产生任何问题。所以我删除了这个目录检查。删除这段代码后,项目将正确编译,并且不会整天重新编译。
那么,为什么自定义构建的输出检查现在可以正常工作,只是文件和目录会产生此类问题?
是的,检查的目录存在,它指的是现有的正确路径。
真正的问题是,由于元数据 Outputs
。
,您的真实项目总是重建
特别的一点是你要确定Outputs
的值的有效性和合法性。
问题出在 %(RelativeDir)%(Outputs)
的 %(RelativeDir)
下。当你添加它时,outputs
有一个非法的文件夹结构而不是一个文件,这使得 outputs
总是找到丢失的非法文件夹结构,从而导致项目总是重建。
我详细描述一下,
当msbuild读取outputs
属性时,当读取到%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)
时,Outputs
的值是这样的:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
然后,它读作%(Outputs)
(读自己),更像是将上面的值复制两次:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
你会发现最后一部分 ..\folder\
不是一个文件,它是一个文件夹结构,对于 outputs
是非法的。
就是这个原因。
和更像是你的问题,文件夹结构d:\projects\program\app\src\plugins\shared\
丢失了。
建议
所以你不应该再添加outputs
。
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;</Outputs>
让晦涩难懂的问题变得简单...
我们有一个由许多项目组成的解决方案,其中一些项目使用 3rd 方的东西设置了自定义构建事件以进行一些黑魔法编译,看起来类似于:
<CustomBuild Include="..\folder\somestuff.xyz">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:\Tcl\bin\tclsh.exe $(APP_PATH)\modules\APP\bin\generator.tcl -o %(RelativeDir)%(Filename) %(RelativeDir)%(Filename).xyz</Command>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">APPGEN %(RelativeDir)%(Filename)</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
</CustomBuild>
在我们从 VS2015 切换到 VS2019 之前,它一直正常工作,因为现在在编译期间它报告说:
Project is not up-to-date: build output 'd:\projects\program\app\src\plugins\shared\' is missing
。这或多或少没问题,但它会强制编译器重新编译该项目的依赖项,这开始变得非常烦人,因为即使没有进行任何更改,您每次都需要重建多个项目。
我发现问题出在自定义构建的这一行:
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
从这部分更准确地说:%(RelativeDir)%(Outputs) 作为 .cpp 和 [=29= 的检查.h 文件在同一个标签中不会产生任何问题。所以我删除了这个目录检查。删除这段代码后,项目将正确编译,并且不会整天重新编译。
那么,为什么自定义构建的输出检查现在可以正常工作,只是文件和目录会产生此类问题?
是的,检查的目录存在,它指的是现有的正确路径。
真正的问题是,由于元数据 Outputs
。
特别的一点是你要确定Outputs
的值的有效性和合法性。
问题出在 %(RelativeDir)%(Outputs)
的 %(RelativeDir)
下。当你添加它时,outputs
有一个非法的文件夹结构而不是一个文件,这使得 outputs
总是找到丢失的非法文件夹结构,从而导致项目总是重建。
我详细描述一下,
当msbuild读取outputs
属性时,当读取到%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)
时,Outputs
的值是这样的:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
然后,它读作%(Outputs)
(读自己),更像是将上面的值复制两次:
..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\..\folder\somestuff.cpp;..\folder\somestuff.h;..\folder\
你会发现最后一部分 ..\folder\
不是一个文件,它是一个文件夹结构,对于 outputs
是非法的。
就是这个原因。
和更像是你的问题,文件夹结构d:\projects\program\app\src\plugins\shared\
丢失了。
建议
所以你不应该再添加outputs
。
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;</Outputs>