惹人嫌的warning MSB8028

今天在等编译过程中,抽空了解了下一直出现的MSB8028(这个警告其实出现了应该有几年了orz),有点意思…
从表现上来说非常简单,就是编译项目的时候有几个工程(后来发现其实是名字要长…)很容易报这个warning

4>C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppBuild.targets(517,5): warning MSB8028: The intermediate directory (xxx\Engine\Intermediate\Build\Obj\x64\Hybrid\NvBlastExtSerialization\) contains files shared from another project (NvBlastExtSerialization.vcxproj).  This can lead to incorrect clean and rebuild behavior.

根据报错信息,最直白的理解就是临时目录中混入了其它工程的文件…特意找一个小工程的开了下发现里面非常干净,就几个obj也能清楚的对应上没问题。
网上搜了下这个报错常出现于工程重命名之后,但是项目的VS工程是脚本生成的,名字非常稳定来着。

突然灵光一闪,在intermediate directory里发现两个奇怪的文件夹: NvBlastE.0A96BFB9.tlogNvBlastE.4F1C48EC.tlog,和其它同级目录对比了下(譬如NvBlastTk.tlog)发现盲点: 这串看上去随机的HEX字符串是怎么回事?

在网上搜了下找到了Build generates multiple tlog folders #741解释的很清楚:

LastBuildState is written to TLogLocation, which is defined in C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.BuildSteps.Targets:

<!-- TLogLocation requires trailing slash. -->
<TLogLocation Condition="'$(TLogLocation)' == '' and '$(ProjectName)' != '' and '$(ProjectGuid)' != '' and '$(ProjectName.Length)' > '16'">$(IntDir)$(ProjectName.Substring(0,8)).$(ProjectGuid.Substring(1,8)).tlog\</TLogLocation>
<TLogLocation Condition="'$(TLogLocation)' == ''">$(IntDir)$(ProjectName).tlog\</TLogLocation>

原来这是MSBuild默认的行为: 当项目名字长度超过16位的时候就自动阶段并拼接上GUID。
而在生成项目VS工程的时候虽然会尽可能保证GUID不变,但是并不是打包票的。当触发GUID变化时,tlog输出路径就会产生变化,导致增量编译的时候触发MSB8028…

ps. 这个其实也解释了为什么网上很多博客说的是修改工程名字之后,不clean build会出这个问题…

到这里解决方法就肥肠简单了: 直接在Property Sheet里合适的位子加一行<TLogLocation>$(IntDir)$(ProjectName).tlog\</TLogLocation>,使得统统走完整的项目名字、不要引入GUID就妥了orz