在中文版本的Visual Studio 2010中使用忍者构建铬时,控制台窗口会输出大量的包含文件通知,从而极大地减慢了构建过程。 通知就像:
注意:包含文件:include文件路径
英文等效为:
注意:包括文件:.....
也许忍者只是基于英文单词来删除收录通知。
在英语安装中,“注意:包括文件:%s%s \ n”作为资源出现在VC \ bin \ 1033 \ clui.dll中的字符串表中。
1033是“英语(美国)”的语言环境标识符。
我不知道有任何命令行选项可以强制将cl强制为1033语言环境。 我假设如果安装了多个语言环境,它将使用系统设置来确定要使用的语言环境。
因此,我想我们必须在/ showIncludes解析器的前缀搜索中添加各种语言。 :/
我认为cmcldeps(此输出的CMake解析器)使用正则表达式(例如“ [^:] +:[^:] +:(。*)”)来捕获所有看起来像showincludes输出的输出行。 我没有太认真地看过代码,因为我最终想实现类似的东西,而且我不想侵犯任何版权。 :)
棘手的部分是不会将showincludes输出与警告混淆。 sfcheng,显示警告或错误消息时,您可以粘贴Visual Studio cl.exe的中文输出吗?
它看起来像:不是ascii 58,所以可能会增加皱纹。 可能会出错的行号“(\ d +)”可能是有用的信号。
我不知道有任何命令行选项可以强制将cl强制为1033语言环境。
不幸的是,没有(干净的)方法可以做到这一点。 VS的外语版本将具有不同数量的其他语言环境资源(例如JA的1041)。
我们学到的知识:始终安装VS的EN版本,然后根据需要安装语言包:(
但是幸运的是,“错误Cnnnn”和“警告Cnnnn”从未被本地化。 因此,我们可以将它们用作密钥。 但是正如@sgraham所说,行号看起来更有希望,因为它还可以过滤掉“ note:”输出。
我不确定:不是ascii58。在日语版中,这些肯定是ascii 58。
FWIW,日语输出如下所示:
C:\cygwin\home\oku>type main.c
#include <stdio.h>
int nah(void){}; /* Trigger "function must return a value */
main(){return nah();}
C:\cygwin\home\oku>cl /showIncludes main.c
Microsoft(R) C/C++ Optimizing Compiler Version 16.00.40219.01 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
main.c
メモ: インクルード ファイル: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\stdio.h
メモ: インクルード ファイル: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\crtdefs.h
メモ: インクルード ファイル: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\sal.h
メモ: インクルード ファイル: c:\program files (x86)\microsoft visual studio10.0\vc\include\codeanalysis\sourceannotations.h
メモ: インクルード ファイル: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\vadefs.h
メモ: インクルード ファイル: C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\INCLUDE\swprintf.inl
c:\cygwin\home\oku\main.c(2) : warning C4716: 'nah' : 値を返さなければいけません
相关技术: https ://bugzilla.mozilla.org/show_bug.cgi?id=587372(那里的方法:从环境变量中读取前缀,进行自动配置检查以验证/ showIncludes解析工作。不是很好。)
类似于mozilla bug的想法:可能有一个顶级var msvs_includes_prefix
,并且生成器可以通过使用/ showIncludes编译一个虚拟#include "knownheader.h"
文件并写入“ knownheader.h”之前的内容来编写该代码cl.exe输出中的“”转换为该顶级变量。 然后,Ninja将使用msvs_includes_prefix作为/ showIncludes前缀。
在配置CMake时,将从一个虚拟版本中读取include前缀,
https://github.com/Kitware/CMake/blob/master/Modules/CMakeClDeps.cmake
使用正则表达式的地方,稍后在前缀上将其作为参数传递给工具,
https://github.com/Kitware/CMake/blob/master/Source/cmcldeps.cxx
和std :: string :: substr用于处理cl.exe输出。
我认为忍者还需要接受一个额外的(全局)参数。
(如建议的nico)
CMake还使用cmcldeps生成.rc文件的依赖关系,方法是首先使用cl编译.rc文件,生成依赖文件,然后使用rc工具对其进行处理。
不确定是否或如何将其集成到忍者中。
https://github.com/martine/ninja/pull/665
这对非Ascii前缀有效吗?
对于法国本地人,忍者1.8.2和CMake 3.10.2,这仍然会发生...
@nico我在CMake中看到引用它的
仍在Visual Studio社区15.9.7中发生...
记录下来,使用以下配置对我来说仍然在发生这种情况:
CMake的3.14
Ninja 1.8.2(Visual Studio 2019附带的一个)
法国语言环境。
编辑:更好的解决方法:在环境中设置VSLANG=1033
强制CL输出英语消息。
旧的解决方法:
对于也遇到此问题的用户,我的解决方法是在$CMAKE_PATH\share\cmake-3.14\Modules\Platform\Windows-MSVC.cmake
注释掉以下行:
#set(CMAKE_NINJA_DEPTYPE_${lang} msvc)
(我的第368行)
不幸的是,这导致CMake生成deps = gcc
而不是仅仅删除deps行,但这似乎并没有破坏我的构建。 YMMV。 这是一种解决方法。
如果不同时设置depfile
,则设置deps = gcc
可能是有益的。
@DrFrankenstein在将此PR应用于忍者代码库后,您愿意尝试重现吗? https://github.com/ninja-build/ninja/pull/1671
这周我会试一试!
不幸的是,这并没有解决。
我从该分支构建了忍者,然后再次使用该版本的忍者进行了构建,但仍然将包含消息泄漏到终端。
在我看来,这里的问题可能与MSVC包含处理程序有关。
语法不能正确识别cl.exe的输出吗?
出色地...
看来这是硬编码英语的问题。
https://github.com/ninja-build/ninja/blob/master/src/clparser.cc
string CLParser::FilterShowIncludes(const string& line,
const string& deps_prefix) {
const string kDepsPrefixEnglish = "Note: including file: ";
const char* in = line.c_str();
const char* end = in + line.size();
const string& prefix = deps_prefix.empty() ? kDepsPrefixEnglish : deps_prefix;
if (end - in > (int)prefix.size() &&
memcmp(in, prefix.c_str(), (int)prefix.size()) == 0) {
in += prefix.size();
while (*in == ' ')
++in;
return line.substr(in - line.c_str());
}
return "";
}
@弗兰肯斯坦博士
您是否想弄乱函数顶部的英文前缀以查看它是否更好?
哈! 我实际上打算明天去那里。 好像您在我没有机会之前就抓住了它。
我只是晚上关掉电脑。 明天我会再给你的!
但是,值得注意的是, deps_prefix
应该包含rules.ninja文件中设置的本地化字符串(通常由CMake检测并设置)。 如果不存在,它仅使用硬编码的一个。
我怀疑逻辑可能只是真正的罪魁祸首。 但是正如我所说,明天我将进行适当的调查/调试会议。
编码不匹配。 deps_prefix
使用Latin-1(冒号之前的NBSP为0xA0),而line
由于某种原因位于CP437中(NBSP = 0xFF)。
我认为CL本身正在输出CP437,但是CMake生成的rules.ninja是Latin-1。 我猜想在CMake方面发生了一些转换,但这需要更多的挖掘工作。
编辑:似乎CL将以任何控制台的代码页输出。 (来源1 ,来源2 )。 我不确定如何迫使它成为其他产品。
也许我们可以通过将它们都转换为通用编码(例如UTF-8(或Ninja更喜欢使用的任何一种))将它们组合在一起,例如,在CL输出上调用MultiByteToWideChar(CP_OEMCP, ...)
,然后调用MultiByteToWideChar(1252, ...)
在来自rules.ninja的字符串上。
回想一下...这可能是CMake的错。 在Windows上, execute_process
命令似乎在内部将命令的输出转换为UTF-8(并接受可选的ENCODING
参数来指定输出的编码)。 因此,它将它以UTF-8格式写回到rules.ninja文件中(其中NBSP是0xA0而不是0xFF)。
我尝试将CMAKE_DETERMINE_MSVC_SHOWINCLUDES_PREFIX
更改为使用ENCODING NONE
(不执行任何转换),但它似乎破坏了CMake中的所有功能。
所以我现在遇到的问题是... ninja的msvc_deps_prefix
是编译器输出的按位匹配,还是应该采用预期的文件编码,在这种情况下应该是Ninja的从编译器输出执行正确的转换的工作?
@bradking在这里对编码和前缀检测
从历史上看,忍者一直在编码不可知论词(只要编码对'/'使用与ASCII相同的字节)。 但是,Windows可能会增加难度。
Ninja的CLParser::FilterShowIncludes
正在使用memcmp
将msvc_deps_prefix
与MSVC输出中的行进行比较,因此该值实际上需要按位匹配。 CMake可能需要一些工作来保存它。 CMake当前在内部转换为UTF-8,因此也许在将值写入build.ninja
时所缺少的只是转换回代码页的编码。
IIRC,MSVC的输出编码可能会受到环境变量和/或标志的影响。 这意味着我们最终可能会获得与Ninja在其中操作并用来解释build.ninja
字符串的代码页不同的编码方式的编译器输出。 此类案件可能需要忍者提供额外的支持才能进行处理,但仍需要进一步调查。
我找不到任何影响CL使用的代码页的环境变量。 我认为它只是使用与该进程关联的代码页(它是基于系统的区域设置,或者如果该进程在其中运行,则取决于控制台设置)。
但是,_is_是一个环境变量,用于设置CL使用的语言VSLANG
,对于受此错误影响的用户,此变量可以用作解决方法。 在生成忍者文件之前设置VSLANG=1033
可以防止该错误的发生。
只是用不同的词来重申我的上述评论:Ninja将其输入文件视为(无编码)字节,并对字符串进行无编码编码的字节比较,以试图规避这些问题。 您需要在build.ninja文件中显示的字节与ninja从进程stdout读取的字节匹配,但是ninja不在乎编码。
在CMake生成所有构建文件之后,我将rules.ninja
手动转换msvc_deps_prefix = 注意: 包含文件:
,然后问题解决了。 (该文件以前是GB2312编码的,对应于默认代码页936。)我想可以对CMake进行更改,以便它始终将rules.ninja
为UTF-8?
我没有在代码页936或65001之外的语言环境上工作的经验,因此我不知道上面的解决方案是否是通用解决方案。
同样的问题,并在CMAKE_CXX_FLAGS中使用添加/ W2而不是/ W3来擦除此输出
这与#1766有关
最有用的评论
对于法国本地人,忍者1.8.2和CMake 3.10.2,这仍然会发生...