Ninja: смешивание абсолютных путей depfile с относительными путями манифеста прерывает перестроение

Созданный на 24 февр. 2017  ·  70Комментарии  ·  Источник: ninja-build/ninja

Руководство ниндзя предостерегает от такой смеси, но это стало серьезным ограничением.

Проблема в том, что люди хотят, чтобы их системы сборки вызывали компилятор с абсолютным путем к исходному файлу. Это дает лучший результат для IDE, чтобы сопоставить сообщения об ошибках и вернуться к исходным файлам. Это также может повлиять на пути, записанные в отладочной информации. Однако это противоречит предпочтениям ниндзя относительных путей в манифесте сборки.

Вот скрипт, демонстрирующий проблему: ninja-bug.bash.txt

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

Я действительно не думаю, что решение должно заключаться в том, чтобы «обойти это во всех других инструментах».

1924 демонстрирует полное рабочее исправление с тестами, основанное на подходе ninja_workdir . Генератор, использующий это, может решить все вышеперечисленные проблемы.

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

Копия: @nico @chaoren

В CMake есть соответствующее обсуждение в issue 16675 , issue 13894 и MR 520 .

В качестве обходного пути вы можете явно указать каталог вывода объекта, даже "." или "..", но также работает и абсолютный путь.
ниндзяцт.bash.txt

@zlolik IIUC, вы предлагаете размещать абсолютные пути в узлах графа манифеста сборки ( build.ninja ). Конечно, это работает (и это то, что CMake делает в сборках вне исходного кода), но я хочу сказать, что Ninja не одобряет использование абсолютных путей, и все же IDE требуют их в выводе.

Также гипотетически возможно, что компилятор, получивший -c foo.c , все равно может сгенерировать абсолютный путь в файле depfile. Если это произойдет, Ninja не распознает зависимость из-за той же проблемы, описанной здесь.

Исправление этого потребует, чтобы Ninja мог распознавать, когда относительный путь и абсолютный путь являются одним и тем же файлом и имеют только один внутренний узел графа вместо двух. Выполнение этого только для обработки depfile может быть достаточным, так как разумно попросить генераторы build.ninja последовательно именовать пути в манифесте сборки.

@bradking Во-первых, я согласен с вами, что у нас есть проблема с ниндзя, и я только предлагаю обходной путь.
Я думаю, что есть 3 связанных вопроса:

  1. Логика ввода абсолютного/относительного пути, подробнее в #1152.
  2. Логика принудительного вывода абсолютного/относительного пути. Проблема с компиляторами - единственный способ сказать компилятору, что вы хотите иметь абсолютный путь в выводе, - это использовать абсолютный путь в командной строке. Проблема не ниндзя, а наша.
  3. Логика для анализа абсолютного/относительного пути к depfile. Эта проблема.

Я использую 2 обходных пути:

  1. Используйте префиксы $p и $o в пути генератора build.ninja для решения первых двух задач. В моем случае $p и $o не являются абсолютными, а относительными относительно текущего каталога, в котором был запущен генератор build.ninja .
  2. Используйте какой-нибудь скрипт для преобразования файла depfile в путь, совместимый с ниндзя. Некоторым компиляторам даже требуется отдельный вызов для создания depfile. Но пока нет проблемы с абсолютным путем.

Для справки: я создал тему в списке рассылки ninja-build с предлагаемым решением.

Еще одна проблема, связанная с отладочной информацией и информацией о покрытии: использование команд с относительными путями также создает файлы отладочной информации с относительными путями. Проблема в том, что файлы отладки обычно располагаются рядом с объектными файлами, а не с исходными файлами, поэтому относительные пути там ссылаются на несуществующие файлы.

Есть новости по этому поводу? В ветке рассылки не было ответов...

Всем привет,

Также гипотетически возможно, что компилятор, получивший -c foo.c , все равно может сгенерировать абсолютный путь в файле depfile.

Файлы зависимостей IAR v8 содержат только абсолютные пути.

Мы столкнулись с этой проблемой при выполнении сборок вне исходного кода с помощью CMake/Ninja/IAR: сгенерированные файлы, которые попадают в двоичный каталог CMake, являются относительными в манифесте Ninja, deps, выводимые IAR, являются абсолютными.

Для меня это явно проблема ниндзя: у него не должно быть двух узлов для одного и того же файла, несмотря ни на что.

Я прочитал предложение @bradking , но я не очень понимаю часть о символических ссылках и почему нельзя использовать getcwd() . Не могли бы вы уточнить?

Я не очень понимаю часть символических ссылок и почему нельзя использовать getcwd()

@sebknzl проблема в том, что абсолютные пути, записанные генератором в build.ninja , могут содержать символические ссылки, которые намеренно не разрешены по той или иной причине. getcwd() обычно возвращает путь с разрешенными символическими ссылками. Если бы Ninja интерпретировал относительный путь в манифесте сборки или depfile относительно getcwd() , тогда абсолютный путь, который он создает, может не совпадать с тем, что использовал генератор манифеста сборки, и мы все равно получили бы два узла.

ninja_workdir , которые я предлагаю в теме, на которую вы ссылаетесь, в основном сообщает Ninja, что генератор использовал в качестве основы для относительных путей. На практике realpath(ninja_workdir) == realpath(getcwd()) всегда должно быть истинным, но это не означает ninja_workdir == getcwd() . Другой альтернативой может быть то, что Ninja будет realpath всего перед созданием узлов, но это будет означать, что $in не расширится до того, что задумал генератор.

@jhasse, пожалуйста, ознакомьтесь с этой проблемой и моим предложением по ее решению.

Почему бы не сгенерировать _build.ninja_ с абсолютными путями, управляемыми CMAKE_NINJA_GENERATOR_OPTION_ ?

то есть так, что работает:

Claus-MBP:build clausklein$ cat build.ninja 

# project dir
p = /Users/clausklein/Downloads
# object dir
o = /Users/clausklein/Downloads/.ninjatst.build

rule cp
  command = cp $in $out

rule cc
  depfile = $out.d
  deps = gcc
  command = cc -I$o -c $in -o $out -MD -MT $out -MF $out.d

# All absolute paths works
build all: phony $o/foo.o

# All absolute paths works
build $o/foo.h: cp $p/foo.h.in
  IN = $p/foo.h.in

# All absolute paths works
build $o/foo.o: cc $p/foo.c || $o/foo.h
  IN = "$p/foo.c"

default all

Claus-MBP:build clausklein$ 

сгенерировано с помощью ninjatst.bash.txt

@ClausKlein мы пытались научить CMake использовать абсолютные пути. См. обсуждения, на которые я ссылался в https://github.com/ninja-build/ninja/issues/1251#issuecomment -282322776. Я бы предпочел не добавлять вариант, который говорит: «Делайте что-то по-другому, чтобы исправить одни случаи и сломать другие».

Нам действительно нужна функция Ninja в предложении, на которое я ссылался в https://github.com/ninja-build/ninja/issues/1251#issuecomment -487618865, чтобы исправить это должным образом.

Хорошо

Тогда это исправление для системы mesonbuild тоже будет доступно ;-)

Am 12.03.2020 um 12:56 schrieb Брэд Кинг[email protected] :

@ClausKlein https://github.com/ClausKlein мы пытались научить CMake использовать абсолютные пути. См. обсуждения, на которые я ссылался в #1251 (комментарий) https://github.com/ninja-build/ninja/issues/1251#issuecomment-282322776 . Я бы предпочел не добавлять вариант, который говорит: «Делайте что-то по-другому, чтобы исправить одни случаи и сломать другие».

Нам действительно нужна функция Ninja в предложении, на которое я ссылался в #1251 (комментарий) https://github.com/ninja-build/ninja/issues/1251#issuecomment-487618865 , чтобы исправить это должным образом.


Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub https://github.com/ninja-build/ninja/issues/1251#issuecomment-598146822 или отмените подписку https://github.com/notifications/unsubscribe-auth/AAN7QWWEDHMDA45DQVPLOUDRHDEVDANCNFSM4DBNL6GA .

Допустим, Ninja будет использовать ninja_workdir для сопоставления информации о depfile, и у нас есть ситуация, когда ninja_workdir != getcwd() из-за символической ссылки. Что, если теперь компилятор печатает абсолютные пути, используя getcwd() ?

Компилятор не должен использовать getcwd() для чего-либо, если только эти вещи не были переданы как относительные пути, и в этом случае генератор системы сборки, вероятно, должен взять на себя ответственность.

Или мы можем попытаться нормализовать как ninja_workdir , так и getcwd() .

Ну, компилятор также не должен возвращать абсолютный путь в файле dep, если заданы относительные пути;)

@ClausKlein мы пытались научить CMake использовать абсолютные пути. См. обсуждения, на которые я ссылался в #1251 (комментарий). Я бы предпочел не добавлять вариант, который говорит: «Делайте что-то по-другому, чтобы исправить одни случаи и сломать другие».

Что именно сломалось, когда вы использовали абсолютные пути, предложенные @ClausKlein?

Если компилятору заданы абсолютные пути, то генерируемый им depfile имеет абсолютные пути, и они не согласованы с относительными путями к заголовкам в манифесте сборки, например, для сгенерированных заголовков. См. ссылку ninja-bug.bash.txt в моем первом сообщении вверху этого выпуска. Он показывает пошаговый пример того, что происходит, и выражается исключительно с точки зрения Ninja, а не CMake.

Я это читал, но почему бы не использовать https://github.com/ninja-build/ninja/issues/1251#issuecomment -284533599? Просто потому, что ниндзя «не одобряет» абсолютные пути? Если да, то речь идет об изменении документации?

Файлы build.ninja намного меньше, без повторения абсолютных путей везде, и это делает их быстрее. Кроме того, они лучше выглядят, их легче отлаживать и они больше подходят для завершения табуляцией имен целей сборки в оболочках. ИМО, это хорошая рекомендация для ниндзя. Ниндзя просто нужно немного больше информации, чтобы примирить этот случай, и это то, что я предлагаю.

Относительные пути @bradking не всегда могут быть короткими:

build jsoncpp@sha/src_lib_json_json_reader.cpp.o: cpp_COMPILER ../../../../../Users/clausklein/Workspace/cpp/jsoncpp/src/lib_json/json_reader.cpp
 DEPFILE = jsoncpp@sha/src_lib_json_json_reader.cpp.o.d
 ARGS = -Ijsoncpp<strong i="7">@sha</strong> -I. -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/include -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/dir1 -I../../../../../Users/clausklein/Workspace/cpp/jsoncpp/dir2 -fdiagnostics-color=always -pipe -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++17 -O3

мой пример https://github.com/ninja-build/ninja/issues/1251#issuecomment -597877775 выглядит лучше!

У генераторов CMake есть правило не использовать последовательности ../ , покидающие дерево сборки. В сборках полностью вне исходного кода мы используем абсолютные пути к дереву исходного кода и относительные пути внутри дерева сборки. Последние никогда не начинаются с ../ , потому что они находятся в дереве сборки.

Я знаю, он был сгенерирован с помощью _mesonbuild_ . ;-)

Но чем, почему бы не запретить генерацию в исходное дерево?

Мы можем вечно спорить о достоинствах относительных и абсолютных путей. Ниндзя не должен быть самоуверенным по этому поводу. Проблема здесь заключается в согласовании случаев, когда оба используются в одной сборке. Генератор системы сборки не всегда может контролировать, что инструменты будут делать с путями. Ninja должен поддерживать смешанные абсолютные и относительные пути к одному и тому же файлу и может сделать это с помощью простого подхода, который я изложил в своем предложении. Для мотивирующего варианта использования изменения изолированы от разбора depfile.

Ninja должен поддерживать смешанные абсолютные и относительные пути к одному и тому же файлу.

Я согласен!

Спасибо за все разъяснения, я начинаю понимать.

Что, если Ninja (при встрече с абсолютным путем в файле depfile) будет использовать realpath как для cwd, так и для найденного пути? Затем он удалит cwd с реальным путем из пути к depfile-path с реальным путем, чтобы относительный путь соответствовал сгенерированному заголовку. Будет ли это работать?

getcwd() всегда является реальным путем, поэтому этот шаг не нужен. Если бы Ninja использовал realpath() , абсолютный путь, предоставленный файлом depfile, и проверил наличие префикса cwd, который мог бы работать. Однако realpath() — это, возможно, дорогостоящий системный вызов, в то время как мой предложенный ninja_workdir может согласовывать пути исключительно в памяти посредством обработки строк.

Смешивание в другом направлении также должно быть разрешено: абсолютный путь в манифесте сборки, но относительный путь в depfile. Я не думаю, что Ninja должен realpath() каждый абсолютный путь при разборе build.ninja . Наверное, это было бы медленно.

Мы могли бы использовать результат для определения рабочего каталога. Например:

getcwd(): /var/xyz/build
Запись в defile: /home/foo/build/bar.h
реальный путь (запись в депфайле): /var/xyz/build/bar.h
относительный реальный путь: bar.h
удалите это из записи depfile: /home/foo/build -> ninja_workdir

Таким образом, нам нужно вызвать realpath только один раз.

Я не думаю, что автоматическое получение ninja_workdir вообще возможно. Как узнать, сколько логических компонентов исходного логического пути, содержащего символическую ссылку, соответствует рабочему каталогу? Мы могли бы сделать это, взяв один компонент за раз, пока его реальный путь не совпадет с cwd, но это кажется хакерским и подверженным ошибкам. Рискованно доверять первой символической ссылке, которая выглядит так. Также нам пришлось бы запускать realpath() для каждого абсолютного пути, с которым мы сталкиваемся, пока один из них не разрешится таким образом.

Генератор системы сборки точно знает, какой логический путь к рабочему каталогу он использовал при создании абсолютных путей в операторах сборки и командных строках в build.ninja . Таким образом, это самый надежный источник информации для пути workdir. Нам просто нужен способ передать эту информацию Ниндзя, поэтому я предложил связывание ninja_workdir .

Я не уверен, что понимаю, извините. Можете ли вы привести пример, когда моя логика обнаружения не сработает?

Это может сломаться, если генератор системы сборки поместит символическую ссылку внутри дерева сборки (указывающую на другое место в дереве сборки или вообще за ее пределы):

getcwd(): /var/xyz/build
Запись в defile: /home/foo/build/subdir-link/bar.h
реальный путь (запись в депфайле): /var/xyz/build/subdir-real/bar.h
относительный реальный путь: subdir-real/bar.h
удалите это из записи depfile: ???

CMake этого не делает, но в целом генератор системы сборки может.

Даже если мы готовы сказать, что не поддерживается, обнаружение все равно может столкнуться:

getcwd(): /var/xyz/build
1000 записей depfile: /home/foo/ext-lib/bar{1,2,...}.h
1000 реальных путей (записей в депфайле): /var/xyz/ext-lib/bar{1,2,...}.h
1000 относительных реальных путей: ни одного под cwd

Теперь представьте, что это появляется в depfile 1000 исходников, и нет ни одного попадания. Это 1 миллион вызовов realpath() без соответствия этой эвристике. И это повторяется каждый раз, когда исходный код перестраивается и повторно анализируется его depfile.

символическая ссылка внутри дерева сборки -> да, мы не можем это поддерживать, в любом случае это приведет к всевозможным другим проблемам (без использования реальных путей повсюду).

Второй пример звучит несколько искусственно. Обычно depfiles начинаются с локальных зависимостей, а не с системных заголовков.

Если это действительно проблема с производительностью, мы могли бы кэшировать рабочий каталог в .ninja_deps ?

В сборке вне исходного кода очень немногие записи в depfile даже указывают на дерево сборки. Это будет очень часто:

getcwd(): /var/xyz/build
1000 записей depfile: /home/foo/project-source/bar{1,2,...}.h
1000 реальный путь (записи файла): /var/xyz/project-source/bar{1,2,...}.h
1000 относительных реальных путей: ни одного под cwd

Ниндзя должен будет вызвать realpath() для всех из них на всякий случай или вести какую-то таблицу результатов, чтобы избежать реальных системных вызовов. Он не может знать заранее, когда он встретит путь символической ссылки, который разрешается в cwd, и даже не знает, найдет ли он его.

Учитывая, что смешивание абсолютных и реальных путей в depfile в настоящее время не работает, я не понимаю, как это может быть «очень распространенным» ??

depfiles формы в моем примере уже очень распространены, даже если не используются символические ссылки или смешанные пути. У меня есть они в большинстве моих деревьев сборки. Ninja не может знать заранее, нужна ли эвристика, поэтому на всякий случай ему придется блокировать системные вызовы realpath() .

Возможно, я неправильно понял ваш пример. Вы имеете в виду один depfile с 3000 записями или это были 3 отдельных примера для depfiles с 1000 записями в каждом?

Я имел в виду 1000 записей depfile, распределенных по любому количеству depfile. Это может быть один. Это может быть много. В проекте может быть 10000 записей. Их пути могут указывать в любом месте файловой системы и могут фактически указывать или не указывать на дерево сборки.

Можете ли вы привести пример CMakeLists.txt , который приводит к такой смеси путей (не обязательно должно быть 1000, только по одному пути каждого)?

Это трудно показать в файле CMakeLists.txt , потому что CMake в настоящее время старается избегать смешивания путей в большинстве случаев. Однако в средстве отслеживания проблем CMake есть проблемы, которые нельзя исправить, если Ninja не исправит это в первую очередь. См., например , CMake Issue 13894 . Пользователи хотят иметь возможность задавать компилятору абсолютные пути даже для источников (и, возможно, включать каталоги) в дереве сборки или при выполнении сборок в исходном коде. Это прекрасно работает с генератором Makefile CMake. Если мы сделаем это с Ninja, то depfiles вернутся с абсолютными путями, и они не совпадают с относительными путями в build.ninja . Возможно, мы могли бы переключиться на абсолютные пути для всего, но, как обсуждалось выше, нам не нужно этого делать.

Возможно, вы можете попробовать это для тестов https://github.com/ClausKlein/build-performance/commit/8013836486e3a459474eb374f6c3da5e20983443.

Показанная здесь проблема основана на https://github.com/ninja-build/ninja/issues/1251#issue -210080507.
Он генерирует столько целей, сколько вы хотите. т.е. 2 подчиненных, каждый с 2 ​​исходными файлами:

PWD=/Users/clausklein/Workspace/build-performance/build

rule cp
  command = cp $in $out

rule cc
  depfile = $out.d
  deps = gcc
  command = gcc -c -I$PWD $IN -o $out $FLAGS -MMD -MT $out -MF $out.d

rule link
  command = gcc -o $out $in $LINK_PATH $LINK_LIBRARIES

build foo: phony foo.h
build foo.h: cp foo.h.in

build bin/main0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir0/main.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir0/main.c
build /Users/clausklein/Workspace/build-performance/build/subdir0/file0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir0/file0.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir0/file0.c

build bin/main1.o: cc /Users/clausklein/Workspace/build-performance/build/subdir1/main.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir1/main.c
build /Users/clausklein/Workspace/build-performance/build/subdir1/file0.o: cc /Users/clausklein/Workspace/build-performance/build/subdir1/file0.c || foo.h
  IN = /Users/clausklein/Workspace/build-performance/build/subdir1/file0.c

build bin/main0: link bin/main0.o /Users/clausklein/Workspace/build-performance/build/subdir0/file0.o 
build bin/main1: link bin/main1.o /Users/clausklein/Workspace/build-performance/build/subdir1/file0.o 

build all: phony foo bin/main0 bin/main1 
default all

Это прекрасно работает с генератором Makefile CMake.

Как Make решает проблему с символическими ссылками?

Как Make решает проблему с символическими ссылками?

Генератор Makefile в настоящее время не использует depfiles и выполняет собственное приблизительное сканирование. Это, вероятно, будет обновлено как часть добавления поддержки модулей C++20 в генератор Makefile, после чего интерпретация путей к depfile должна быть согласована аналогично тому, что предлагается здесь.

Один из вариантов — пока пропустить ninja_workdir и хотя бы научить ниндзя согласовывать смешанные пути, предполагая, что getcwd() является вершиной. Таким образом, по крайней мере, смешанные пути будут работать в обычном случае без символической ссылки. Затем можно добавить ninja_workdir для поддержки более сложных случаев позже.

Пожалуйста, кто-нибудь исправьте это. Я так раздражен из-за этого.

Я использую ARM-GCC с CMake и VSCode. Когда я использую сборку в исходном коде, пути относятся к каталогу «сборка» (а не к корневому каталогу), что приводит к тому, что VSCode больше не может разрешать пути, а это означает, что вы не можете просто щелкнуть пути в окне командной строки, вместо этого вы должны найти каждый файл самостоятельно. Когда я использую сборку CMake вне дерева, она нарушает «IntelliSense» Eclipse и создает проблемы с подпроектами CMake. Мое решение на данный момент — использовать MakeFiles, потому что по умолчанию он использует абсолютные пути. Но Ninja лучше, он создает более читаемые файлы (rules.ninja...) и вывод сборки в командной строке лучше. У Make есть проблемы с выводом предупреждений в командную строку в многопоточном контексте, то есть несколько предупреждений чередуются. Это заставляет меня создавать однопоточный код, что опять же очень раздражает.

Пожалуйста, кто-нибудь исправьте это. Я так раздражен из-за этого.

Я использую ARM-GCC с CMake и VSCode. Когда я использую сборку из исходного кода, пути относятся к каталогу сборки...

Существует обходной путь: выберите каталог сборки вне исходного дерева! т.е. _$TMPDIR/..._

Спасибо, ClausKlein, но обходной путь — это сборка из исходного кода, но мне нужны файлы внутри моего дерева, потому что на него ссылаются другие скрипты. Также это нестандартное требование сборки.

Мое решение на данный момент состоит в том, чтобы изменить CMake, чтобы всегда использовать абсолютные пути. Я не понимаю, почему нет такой возможности. Однако, если это кому-то еще нужно, вот патч CMake v3.18.1:

@@ -241,7 +241,7 @@ void cmNinjaTargetGenerator::AddIncludeFlags(std::string& languageFlags,
   // Add include directory flags.
   std::string includeFlags = this->LocalGenerator->GetIncludeFlags(
     includes, this->GeneratorTarget, language,
-    language == "RC", // full include paths for RC needed by cmcldeps
+    true, // full include paths for RC needed by cmcldeps
     false, config);
   if (this->GetGlobalGenerator()->IsGCCOnWindows()) {
     std::replace(includeFlags.begin(), includeFlags.end(), '\\', '/');
@@ -1133,8 +1133,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
   const std::string& fileConfig, bool firstForConfig)
 {
   std::string const language = source->GetLanguage();
-  std::string const sourceFileName =
-    language == "RC" ? source->GetFullPath() : this->GetSourceFilePath(source);
+  std::string const sourceFileName = source->GetFullPath();
   std::string const objectDir = this->ConvertToNinjaPath(
     cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
              this->GetGlobalGenerator()->ConfigDirectory(config)));

Внимание , был патч для cmake, но смотрите https://github.com/ninja-build/ninja/issues/1251

Нужен патч для Ninja!

В моем последнем комментарии я показал патч для CMake, который использует абсолютные пути вместо относительных. Оказывается, это плохая идея, потому что она нарушает пользовательские зависимости заголовков CMake с Ninja (например, сгенерированный файл заголовка зависит от файла .json). Думаю, эта проблема связана с этой проблемой здесь, которую я был слишком глуп, чтобы понять.

Если кому-то это интересно, я сейчас использую Ninja с относительными путями. Я создал расширение для VSCode, чтобы иметь возможность щелкать относительные пути внутри встроенного терминала. расширение

@GrandChris Отлично! Есть ли шанс заставить его работать и на вкладке Output ?

@weliveindetail Не стесняйтесь создавать новую проблему на https://github.com/GrandChris/TerminalRelativePath/issues и подробно описывать свой вариант использования. Но вкладка вывода в VSCode ведет себя иначе, чем встроенный терминал, и я не думаю, что есть API для расширения поведения в этом отношении.

Хорошо спасибо. В конце концов, интерактивные относительные пути, вероятно, должны быть решены в VSCode или расширении CMake. Будет пинг на их стороне.

Для справки, это снова появилось в CMake Issue 21865 . Это еще один пример случая, когда непросто (возможно?) заставить обнаруженные в depfile зависимости использовать то же самое представление пути, что и build.ninja .

1917 добавляет предложенную выше привязку ninja_workdir как функцию, полезную саму по себе. Как только это будет объединено, я смогу исправить эту проблему.

@jhasse Я хотел бы найти приемлемое решение, чтобы исправить это в восходящем направлении. ninja_workdir решает проблему. Я аргументировал свой случай выше. Какую другую альтернативу вы предлагаете?

Как вы указали, проблема (смешение абсолютных путей файла depfile с относительными путями манифеста прерывает перестроение) задумана. Я думаю, что мы должны создать более конкретные вопросы, потому что мы затронули несколько вопросов в обсуждении (например, символическая ссылка на каталог сборки).

Для двух вариантов использования в начальном комментарии моими альтернативами были бы:

Это дает лучший результат для IDE, чтобы сопоставить сообщения об ошибках и вернуться к исходным файлам.

Либо исправьте IDE, либо передайте компилятору /FC или -fabs-path-diagnostics .

Это также может повлиять на пути, записанные в отладочной информации.

Это также должно быть исправлено компилятором. Я бы предложил взглянуть на -fdebug-prefix-map , но я не уверен, в чем именно проблема.

Вот скрипт, демонстрирующий проблему: ninja-bug.bash.txt

Не совсем, это демонстрирует текущее поведение Ниндзя. Две проблемы

  1. "Моя IDE не может сопоставить вывод компилятора с правильным файлом"
  2. «Мне нужны абсолютные пути в отладочной информации»

нуждаются в дальнейшем объяснении. В противном случае для меня это выглядит как проблема XY (X - это «смешение абсолютных и относительных путей», а Y - либо 1, либо 2).

Я действительно не думаю, что решение должно заключаться в том, чтобы «обойти это во всех других инструментах».

1924 демонстрирует полное рабочее исправление с тестами, основанное на подходе ninja_workdir . Генератор, использующий это, может решить все вышеперечисленные проблемы.

Я тоже, потому что не вижу в этом обходных путей.

Это НЕ опции GNU gcc!

Am 05.03.2021 гм 16:58 шриб Ян Никлас Хассе уведомления@github.com :

Либо исправьте IDE, либо передайте /FC https://docs.microsoft.com/de-de/cpp/build/reference/fc-full-path-of-source-code-file-in-diagnostics или -fabs- диагностика пути https://reviews.llvm.org/D23816 к компилятору.

Это также может повлиять на пути, записанные в отладочной информации.

Вот скрипт, демонстрирующий проблему: ninja-bug.bash.txt

Не совсем, это демонстрирует текущее поведение Ниндзя.

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

Два вопроса ... (1) ... (2) ... нуждаются в дальнейшем объяснении.

Это только два примера проблем, решение которых облегчается
передача абсолютных путей к инструментам. Абсолютные пути не являются необоснованными
просто потому, что другие решения доступны в конкретных случаях таких
проблемы (используя специфические особенности инструментария некоторых производителей).
Абсолютные пути помогают решить большой класс этих проблем без обновлений.
к остальной части экосистемы. Как я писал ранее :

Мы можем вечно спорить о достоинствах относительных и абсолютных путей. Ниндзя должен
не быть категоричным по этому поводу. Проблема здесь заключается в согласовании случаев, когда
оба используются в рамках одной сборки. Генератор системы сборки не всегда может
управлять тем, что инструменты будут делать с путями.

В сложных реальных системах сборки может быть произвольное количество слоев.
скриптов, оберток, инструментов и т. д. (от всех видов поставщиков) между
пути, записанные в build.ninja генератором файла сборки, и фактические пути
встречается Ninja в depfile. Иногда на данный файл может ссылаться
depfile из инструмента, которому не был напрямую указан путь от build.ninja .
Для того, чтобы depfiles работали с текущим дизайном Ninja, весь инструментарий
стеку нужно точно указать, как генератор build.ninja выбирает для выражения
эти пути в операторах сборки, и функции сохраняют их или преобразуют
их таким же образом. Это не лечится в общем.

Ninja может решить эту проблему небольшим изменением дизайна:
абсолютный путь в depfile с относительным путем в build.ninja (и наоборот
наоборот). Я не прошу согласовать произвольные пути к одному и тому же файлу, только чтобы
признать, что /path/to/some/file в depfile — это то же самое, что some/file в
файл сборки /path/to/build.ninja .

Есть прецедент для таких обновлений дизайна. Когда ниндзя только начинал, надежда
заключалась в том, что пути всегда будут встречаться ninja в одном и том же
побайтовое представление, которое генератор файла сборки записал в
build.ninja . Запустите git blame -M -C -w -- src/util.cc и посмотрите историю
из CanonicalizePath , чтобы увидеть ряд случаев, когда это
философия дизайна должна была быть смягчена. Это другой класс таких случаев.

Дело в том, что я не согласен с

Ниндзя не должен быть самоуверенным по этому поводу.

на первом месте.

Это не лечится в общем.

Так в чем конкретно проблема? Извините, я немного запутался.

Я не согласен с тем, что «Ниндзя не должен высказывать свое мнение по этому поводу» в первую очередь… Так в чем же конкретно проблема?

Речь идет не о какой-то одной конкретной проблеме, а о целом классе проблем, которые гораздо проще решить с помощью абсолютных путей. Не должно иметь значения, почему разработчики хотят передавать абсолютные пути своим инструментам, важно только то, что они хотят использовать абсолютные пути по любым причинам, применимым к их конкретному случаю. Системы сборки существуют, чтобы обслуживать своих пользователей, а не диктовать политику. Предполагается, что Ninja является языком ассемблера для систем сборки, но пока не имеет возможности выражать системы сборки, используя пути смешанного стиля.

Политика Ninja в отношении апстримных изменений заключается в том, что проблемы должны решаться генераторами файлов сборки, а не ниндзя апстримом, если их можно решить без потери эффективности . В этом случае единственный способ обеспечить согласование путей общего назначения в стиле ninja_workdir для файлов depfile из генератора файла сборки — это вводить после каждой команды, создающей файл dep, дополнительную команду для проверки путей в файле dep, чтобы они соответствовали файл сборки до того, как ниндзя загрузит его. Эта дополнительная команда будет иметь свою собственную стоимость выполнения, которая намного выше, чем у # 1924 (небольшое количество дополнительных операций поиска в памяти внутри процесса ninja ). Следовательно, согласование общего назначения более эффективно обеспечивать в восходящем потоке Ninja, и поэтому оно является кандидатом на включение.

Даже если вы используете абсолютные пути для всего, а не смешиваете абсолютные и относительные пути, возникает раздражающая проблема с эргономикой. Если пользователь просит ninja восстановить конкретный выходной файл, а не фальшивую цель, например, ninja out/my_executable или ninja out/foo/bar.o , он должен не забыть передать абсолютный путь, иначе ниндзя потерпит неудачу с запутанной ошибкой «неизвестная цель». Существует и противоположная проблема: пользователь может попросить ninja восстановить абсолютный путь, когда в файле build.ninja используются относительные пути.

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

По общему признанию, это не совсем та же проблема, что и с depfiles, но это говорит о том, что Ninja должен больше знать об эквивалентности абсолютного и относительного пути в целом.

@comex Спасибо, это серьезная проблема. Можете ли вы открыть новую тему для этого?

Неважно, почему разработчики хотят передавать абсолютные пути к своим инструментам [...]

Я не согласен.

В этом случае единственный способ обеспечить универсальное согласование путей файлов depfile в стиле ninja_workdir [...]

Зачем вообще нужно примирение в стиле ninja_workdir ?

Зачем вообще нужно согласование в стиле ninja_workdir?

Это позволяет разработчикам использовать относительные пути в build.ninja , в то же время обрабатывая абсолютные пути, сгенерированные в depfiles с помощью инструментов, которые они не контролируют. В противном случае они могут быть вынуждены использовать абсолютные пути в build.ninja , чтобы приспособить такие инструменты в сочетании с ограничениями по дизайну ниндзя. Мое предложение не препятствует использованию относительных путей. Это позволяет больше использовать их.

Я открыл #1925 для реализации того же согласования, что и #1924, но без привязки ninja_workdir . Это отделяет решение о согласовании путей к depfile от решения о поддержке логических путей workdir с символическими ссылками.

[...] абсолютные пути, сгенерированные в depfile инструментами, которые они не контролируют.

Есть ли пример такой оснастки?

Мы не можем предсказать поведение всех инструментов, используемых всеми в мире. Даже для инструментов, которыми мы управляем, мы уже обсуждали выше несколько случаев, которые легко решить с помощью абсолютных путей, но требуют специальных опций инструмента и большой осторожности для решения с относительными путями. CMake предпочитает абсолютные пути в некоторых случаях по тем же причинам. У меня есть несколько отчетов об ошибках, в которых генератор Ninja не делает этого, в то время как все остальные генераторы делают это. Я несколько раз тратил часы на отслеживание проблемы с зависимостями только для того, чтобы обнаружить, что это еще один пример путей depfile, не согласованных с путями манифеста сборки. Инструменты предоставляют информацию, необходимую Ninja для захвата зависимостей, но Ninja игнорирует ее.

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

Мое предложение добавляет небольшое количество инфраструктуры в Ninja. Что это больно? Отсутствие этого экстернализует гораздо большие затраты.

Да это правда!

А с абсолютными путями cmake может устранить повторяющиеся пути включения компилятора.
Это снова сократит время сборки.

Am 09.03.2021 гм 19:20 schrieb Брэд Кинг уведомления[email protected] :

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

Я установил проблему CMake в отношении проблемы, с которой мы столкнулись, когда компилятор Qt Quick сгенерировал файлы cpp и включил сборку единства. Мои местные исследования показали, что ниндзя — самая быстрая система сборки, но в этом созвездии она ненадежна. Теперь я столкнулся с проблемой, как найти обходной путь или оправдать увеличение времени сборки.

CMake только что столкнулся с проблемой циклических зависимостей, которая до недавнего времени была замаскирована этой проблемой Ninja. Если бы эта проблема была исправлена, мы бы обнаружили проблему CMake намного раньше.

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