让我们把晦涩的问题变得简单。。。
我们有一个由许多项目组成的解决方案,其中一些项目已经使用第三方的东西设置了自定义构建事件,用于一些黑暗的魔法编译,看起来像这样:
<CustomBuild Include="..foldersomestuff.xyz">
<FileType>Document</FileType>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">C:Tclbintclsh.exe $(APP_PATH)modulesAPPbingenerator.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之前,这一直正常工作,因为在编译过程中,它报告说:CCD_ 1。这或多或少是可以的,但它迫使编译器也重新编译这个项目的依赖项,这开始非常令人讨厌,因为即使没有做任何更改,每次都需要重建几个项目。
我发现问题源于自定义构建的这一行:
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)%(Outputs)</Outputs>
更确切地说,从这一部分来看:%(RelativeDir(%(输出(作为检查同一标记中的.cpp和.h文件不会产生任何问题。所以我删除了对目录的检查。当这段代码被删除时,项目会正确编译,并且不会整天重新编译。
那么,为什么自定义构建的输出检查现在只能正常工作,而文件和目录会产生这种问题呢
是的,检查的目录存在,它指的是现有的正确路径
真正的问题是,由于元数据Outputs
,您的真实项目总是在重建。
特别的一点是,你应该确保Outputs
值的有效性和合法性。
该问题在%(RelativeDir)%(Outputs)
的%(RelativeDir)
下。添加它时,outputs
具有非法的文件夹结构,而不是一个文件,这使得outputs
总是找到丢失的非法文件夹结构,从而导致项目总是重新生成。
让我详细描述一下,
当msbuild读取outputs
proeperty时,当它读取到%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;%(RelativeDir)
时,Project is not up-to-date: build output 'd:projectsprogramappsrcpluginsshared' is missing
0的值为:
..foldersomestuff.cpp;..foldersomestuff.h;..folder
然后,它读取%(Outputs)
(读取自身(,这更像是复制上述值两次:
..foldersomestuff.cpp;..foldersomestuff.h;..folder..foldersomestuff.cpp;..foldersomestuff.h;..folder
你会发现最后一部分..folder
不是一个文件,它是一个文件夹结构,对outputs
来说是非法的。
这就是原因。
而且文件夹结构d:projectsprogramappsrcpluginsshared
丢失更像是您的问题。
建议
因此,您不应该再添加outputs
。
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">%(RelativeDir)%(Filename).cpp;%(RelativeDir)%(Filename).h;</Outputs>