我一直在为我们的软件堆栈开发一个跨平台的构建系统。具体来说,我正在研究构建系统的 Windows 组件。
我们有许多项目,每个项目都有一个手工编码的 .vcxproj。一些项目相互依赖,一些依赖Qt。
到目前为止,我的 .vcxproj 文件在我尝试的五个项目中的三个都可以正常工作,但在另外两个项目中却以一种非常有趣的方式失败了:
project\dir> msbuild /p:Configuration=Release /p:PropertyA=C:\path\to\project\root\ /p:Platform=x64 obj\project.vcxproj
Microsoft (R) Build Engine version 4.0.30319.17929
[Microsoft .NET Framework, version 4.0.30319.18047]
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 16.07.2013 11:13:43.
Project "C:\path\to\project\root\obj\project.vcxproj" on node 1 (default targets).
PrepareForBuild:
Creating directory "C:\path\to\project\root\obj\x64_Int\Release_DLL_Int\".
InitializeBuildStatus:
Creating "C:\path\to\project\root\obj\x64_Int\Release_DLL_Int\project.unsuccessfulbuild" because "AlwaysCreate" was specified.
ClCompile:
C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\AMD64\CL.exe /c /I"include path A" /I"include path B" /Zi /nologo /W3 /WX- /sdl /O2 /Oi /D NDEBUG /D _CRT_SECURE_NO_WARNINGS /D QT_CORE_LIB /D _WINDLL /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"C:\path\to\project\root\obj\x64_Int\Release_DLL_Int\\" /Fd"C:\path\to\project\root\obj\x64\\project.pdb" /Gd /TP /errorReport:queue
/nologo
src\main\cpp\source_a.cpp src\main\cpp\source_b.cpp src\main\cpp\source_c.cpp ...
????????????????????????????????????
c1xx : fatal error C1083: Cannot open source file: '????????????????????????????????????': No such file or directory [C:\path\to\project\root\obj\project.vcxproj]
????????????????????????????????
c1xx : fatal error C1083: Cannot open source file: '????????????????????????????????': No such file or directory [C:\path\to\project\root\obj\project.vcxproj]
...
对于每个源文件,使用这些问号字符串之一,源文件路径中的每个字符一个问号。
那是在命令行上,但如果我在 Visual Studio (2012) 中打开项目,我可以看到它们真正的字符:
error C1083: Cannot open source file: '猀爀挀尀洀愀椀渀尀挀瀀瀀尀...⸀挀瀀瀀': No such file or directory
error C1083: Cannot open source file: '猀爀挀尀洀愀椀渀尀挀瀀瀀尀...⸀挀瀀瀀': No such file or directory
...
(我已经省略了真实的文件名,抱歉。)
文件名中的每个字符都已[一致地]替换为中文字符。这是一个 1:1 的替换,在罗马字符和中文字符之间具有一致的关系,即\
->尀
和cpp
-> 挀瀀瀀
。
我已经以诊断冗长的方式运行了 msbuild,并且在这些错误消息之前的 12000 多行输出中没有任何地方出现中文字符——它在失败之前多次正确列出了源文件。
通过历史悠久的调试技术“随机注释掉东西”,我发现如果我手动编辑以某些方式失败的 vcxproj 文件,问题就会消失,但链接会失败,因为我已经注释掉了库路径或源文件。
在两个失败的项目中删除 4-6 个源文件(随机,尽管注释掉相同的四个文件将始终工作或不工作是一致的)将修复它。在依赖于 Qt 的那个中,删除 $(QT5DIR)/include/QtCore 的路径将解决问题,但无法链接,因为它找不到 Qt。
源文件都是 ASCII 编码的,并且在删除时解决问题的文件中似乎没有任何一致的格式。
我已经在三台不同的计算机、两台 Windows 7 机器和一个 8.1 预览版上进行了尝试。它在 8.1 上运行良好,但在两台 Win 7 机器上都失败了。
它似乎与项目中的文件数量无关,因为其中一个工作的项目比任何一个不工作的项目具有更多的文件。
这似乎不是依赖问题,因为只有一个非工作的依赖于 Qt,而工作和非工作之间的共性似乎排除了项目间的依赖。
我意识到这很不错,任何微软大师都知道发生了什么?
问题1:我做错了什么?什么可能导致这种行为?
问题 2:关于我可以做些什么来继续追踪问题的任何想法?
更新:
- 如果我自己运行 ClCompile 行,它实际上会尝试编译所有内容,但找不到标准库。我认为这意味着在这种情况下不会发生这个问题。
- 我在这里找到了我认为是一种解决方法:c1xx:致命错误 C1083:无法打开源文件 - 使用一些中文或爪哇语,但我仍然希望有人能用真正的解决方案来回答。为什么会这样?为什么删除 .vcxproj 看似随机的部分可以解决此问题?是否存在误解我的路径的编码检测启发式?