Ninja: 使用中文版本的Visual Studio 2010进行构建时会包含大量的包含文件通知

创建于 2013-07-05  ·  32评论  ·  资料来源: ninja-build/ninja

在中文版本的Visual Studio 2010中使用忍者构建铬时,控制台窗口会输出大量的包含文件通知,从而极大地减慢了构建过程。 通知就像:

注意:包含文件:include文件路径

英文等效为:
注意:包括文件:.....

也许忍者只是基于英文单词来删除收录通知。

bug windows

最有用的评论

对于法国本地人,忍者1.8.2和CMake 3.10.2,这仍然会发生...

所有32条评论

在英语安装中,“注意:包括文件:%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前缀有效吗?

665被合并。 不过,我们可能仍需要对编码问题进行迭代,因此请保持打开状态直到经过验证可以正常工作为止。

对于法国本地人,忍者1.8.2和CMake 3.10.2,这仍然会发生...

665添加了msvc_deps_prefix。 cmake设置了吗? @syntheticpp @mathstuf

@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

这周我会试一试!

不幸的是,这并没有解决。

我从该分支构建了忍者,然后再次使用该版本的忍者进行了构建,但仍然将包含消息泄漏到终端。
image

在我看来,这里的问题可能与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)。
image

我认为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正在使用memcmpmsvc_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有关

此页面是否有帮助?
0 / 5 - 0 等级