Ninja: Тонны уведомлений о включенных файлах при сборке с китайской версией Visual Studio 2010

Созданный на 5 июл. 2013  ·  32Комментарии  ·  Источник: ninja-build/ninja

При сборке Chrome с помощью ninja с китайской версией Visual Studio 2010 окно консоли выводит множество уведомлений о включаемых файлах, что значительно замедляет процесс сборки. Уведомление выглядит так:

注意 : 包含 文件 : включить путь к файлу

Английский эквивалент :
Примечание: включая файл: .....

Возможно, ниндзя удаляет уведомления о включении только на основе английских слов.

bug windows

Самый полезный комментарий

С французским локальным, ninja 1.8.2 и CMake 3.10.2 это все еще происходит ...

Все 32 Комментарий

При установке на английском языке «Примечание: включая файл:% s% s \ n» отображается как ресурс в таблице строк в VC \ bin \ 1033 \ clui.dll.

1033 - это идентификатор локали для английского языка (США).

К сожалению, я не знаю ни одной опции командной строки для принудительного использования cl в локали 1033. Я предполагаю, что если установлено несколько локалей, он использует системные настройки, чтобы определить, какой из них использовать.

Итак, я думаю, нам нужно было бы добавить различные языки к поиску префиксов в парсере / showIncludes. : /

Я думаю, что cmcldeps (синтаксический анализатор CMake этого вывода) использует регулярное выражение, что-то вроде «[^:] +: [^:] +: (. *)», Чтобы захватить все выходные строки, которые выглядят как showincludes output. Я не слишком внимательно смотрел на код, потому что в конечном итоге я хотел бы реализовать что-то подобное, и я не хочу нарушать авторские права. :)

Сложная часть не сбивает с толку, showincludes вывод с предупреждениями. sfcheng, не могли бы вы вставить китайский вывод Visual Studio cl.exe при отображении предупреждения или сообщения об ошибке?

Похоже, что это не ascii 58, так что может добавить морщинку. Возможно, номер строки "(\ d +)", в которой будут ошибки, может быть полезным сигналом.

К сожалению, я не знаю ни одной опции командной строки для принудительного использования cl в локали 1033.

К сожалению, нет (чистого) способа сделать это. Версии VS на иностранных языках будут иметь другие ресурсы локали под другим номером (например, 1041 для JA).
Что мы узнали: всегда устанавливайте EN-версию VS, затем при необходимости устанавливайте языковой пакет :(

Но, к счастью, «ошибка Cnnnn» и «предупреждение Cnnnn» никогда не локализуются. Так что мы можем использовать их как ключевые. Но, как сказал @sgraham , номера строк выглядят более многообещающими, потому что они также позволят отфильтровать вывод 'note:'.

Я не уверен, действительно ли: это не ascii 58. В японской версии это определенно 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 (подход там: чтение префикса из env var, проверка autoconf для проверки / showIncludes работы синтаксического анализа. Не очень хорошо.)

Идея похожа на ошибку mozilla: может быть верхний уровень var msvs_includes_prefix , и генераторы могут записать это, скомпилировав фиктивный файл #include "knownheader.h" с / showIncludes и записав все, что находится перед "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.

Я предполагаю, что ниндзя также должен принять дополнительный (глобальный) аргумент.
(как предложил Нико)

CMake также использует cmcldeps для генерации зависимостей для файлов .rc, сначала «компилируя» файл .rc с помощью cl, который генерирует файл зависимостей, а затем обрабатывает его с помощью инструмента rc.
Не уверен, можно ли и как это можно интегрировать в ниндзя.

https://github.com/martine/ninja/pull/665

Это работает с префиксами, отличными от Ascii?

665 объединены. Возможно, нам придется еще немного поработать над проблемами кодирования, поэтому оставьте это открытым до тех пор, пока не будет подтверждено, что это работает.

С французским локальным, ninja 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. Это обходной путь.

Установка deps = gcc , вероятно, не представляет опасности без установки depfile .

Я попробую на этой неделе!

К сожалению, это не помогло.

Я построил ниндзя из этой ветки, затем использовал эту версию ниндзя, чтобы построить себя снова, и он по-прежнему передавал сообщения включения в терминал.
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 "";
}

@DrFrankenstein

Не хотите ли вы возиться с этим английским префиксом в верхней части функции, чтобы узнать, работает ли он лучше?

Ха! Я действительно собирался заглянуть туда завтра. Похоже, ты поймал это раньше, чем я успел.

Я просто выключил свой компьютер на ночь. Я вернусь к вам завтра!

Однако стоит отметить, что deps_prefix должен содержать локализованную строку, как установлено в файле rules.ninja (обычно обнаруживается и устанавливается CMake). Он использует только жестко запрограммированный, если он отсутствует.

Я подозреваю, что причиной может быть логика сразу после того, как она была виновата. Но, как я уже сказал, завтра я проведу надлежащее расследование / отладку.

Кодировки не совпадают. deps_prefix находится в Latin-1 (где NBSP перед двоеточиями - 0xA0), а line по какой-то причине находится в CP437 (NBSP = 0xFF).
image

Я думаю, что сама CL выводит CP437, но правила, сгенерированные CMake. Ninja находятся в Latin-1. Я предполагаю, что на стороне CMake произошла некоторая конверсия, но это потребует дополнительных усилий.

РЕДАКТИРОВАТЬ: похоже, что CL будет выводить любую кодовую страницу консоли. ( Источник 1 , Источник 2 ). Я не уверен, как мы можем заставить это быть чем-то другим.

Возможно, мы сможем объединить их, преобразовав их в общую кодировку, такую ​​как UTF-8 (или что-то еще, что предпочитает использовать Ninja), например, вызвав MultiByteToWideChar(CP_OEMCP, ...) на выходе CL и 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.

Итак, вопрос, который у меня сейчас возникает, заключается в следующем: должен ли ниндзя msvc_deps_prefix быть побитовым совпадением с выводом компилятора или он должен быть в любой кодировке файла, и в этом случае это будет Ниндзя работа по правильному преобразованию выходных данных компилятора?

@bradking Мысли по поводу кодировки и определения префикса здесь?

Исторически ниндзя кодировал агностик (до тех пор, пока в кодировке использовался тот же байт, что и ASCII для '/'). Однако Windows может сделать это трудным.

CLParser::FilterShowIncludes Ninja использует memcmp для сравнения msvc_deps_prefix со строками в выводе MSVC, поэтому значение действительно должно быть побитовым совпадением. CMake может потребоваться некоторая работа, чтобы сохранить это. CMake в настоящее время преобразуется в UTF-8 внутренне, поэтому, возможно, все, что отсутствует, - это преобразование обратно в кодировку кодовой страницы при записи значения в build.ninja .

IIRC, кодировка вывода MSVC может зависеть от переменных и / или флагов среды. Это означает, что мы можем получить вывод компилятора в кодировке, отличной от кодовой страницы, в которой работает Ninja и которая используется для интерпретации строк в build.ninja . В таких случаях может потребоваться дополнительная поддержка со стороны Ninja, но потребуется дальнейшее расследование.

Я не смог найти ни одной переменной среды, влияющей на кодовую страницу, используемую CL. Я думаю, что он просто использует кодовую страницу, связанную с процессом (которая основана на региональных настройках системы или настройках консоли, если процесс выполняется в одном).

Однако есть _is_ переменная среды, которая устанавливает язык, используемый CL, VSLANG , что может быть полезно в качестве обходного пути для пользователей, затронутых этой ошибкой. Установка VSLANG=1033 перед созданием файлов ниндзя предотвратит появление ошибки.

Просто чтобы переформулировать мой вышеупомянутый комментарий другими словами: Ninja обрабатывает свои входные файлы как байты (без кодирования) и выполняет сравнение строк без кодирования байтов, чтобы попытаться избежать этих проблем. Вам нужны байты, которые появляются в файле build.ninja, чтобы соответствовать байтам, которые ниндзя читает из процесса stdout, но ниндзя не заботятся о кодировках.

После того, как CMake сгенерировал все файлы сборки, я вручную преобразовал rules.ninja в UTF-8, который содержит строку msvc_deps_prefix = 注意: 包含文件: , а затем все было исправлено. (Этот файл раньше был в кодировке GB2312, что соответствует кодовой странице по умолчанию 936.) Я предполагаю, что в CMake можно внести изменения, чтобы он всегда преобразовывал rules.ninja в UTF-8?

У меня нет опыта работы с языковыми стандартами, кроме кодовой страницы 936 или 65001, поэтому я понятия не имею, является ли приведенное выше решение универсальным исправлением.

Та же проблема, и удалось стереть этот вывод с помощью add / W2 вместо / W3 в CMAKE_CXX_FLAGS

Это связано с # 1766.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги