Подтвердить что ты не робот

Почему двоичный вывод не равен при компиляции снова?

Я использую сборку script для компиляции нескольких проектов С#. Бинарный вывод копируется в папку результатов, перезаписывает предыдущую версию файлов, а затем добавляется/передается в подрывную деятельность.

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

Я не намеренно использую какие-либо специальные временные метки в любом месте, но компилятор (Microsoft, тот, который входит в .NET 4.0), возможно, сам добавляет метки времени?

Причина, по которой я спрашиваю, это то, что я делаю вывод в subversion, и из-за того, как работает наш сервер сборки, проверенные изменения вызывают перестройку, в результате чего еще раз измененные двоичные файлы проверяются в круге.

4b9b3361

Ответ 1

ДРУГОЕ ОБНОВЛЕНИЕ:

С 2015 года команда компилятора прилагает усилия, чтобы получить источники недетерминизма из инструментальной цепочки компилятора, так что идентичные входы действительно дают идентичные результаты. Более подробную информацию см. В теге "Концепт-детерминизм" в github Roslyn.


UPDATE: Этот вопрос был предметом моего блога в мае 2012 года. Спасибо за отличный вопрос!


Как это возможно?

Очень легко.

Разве бинарный результат не должен быть точно равным для одного и того же входа?

Абсолютно нет.. Каждый раз, когда вы запускаете компилятор, вы должны получать другой результат. В противном случае, как вы могли бы узнать, что вы перекомпилировали?

Компилятор С# объединяет только что созданный GUID в сборке на каждой компиляции, тем самым гарантируя, что никакие две компиляции не дают точно такой же результат.

Более того - даже без GUID компилятор не дает никаких гарантий, что две "идентичные" компиляции будут давать одинаковые результаты.

В частности, порядок заполнения таблиц метаданных сильно зависит от деталей файловой системы; компилятор С# начинает генерировать метаданные в том порядке, в котором ему даны файлы, и которые могут быть тонко изменены различными факторами.

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

Я бы исправил это, если бы я был вами.

Ответ 2

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

(Обратите внимание, что если источник уже находится в Subversion, я вообще избегаю добавления двоичных файлов. Обычно я включаю только релизы сторонних библиотек. Это зависит от того, что вы делая хотя.)

Ответ 3

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

Параметры командной строки Roslyn

/детерминированный Произвести детерминированную сборку (включая модуль GUID версии и временная метка)

Подробнее об этой функции https://github.com/dotnet/roslyn/blob/master/docs/compilers/Deterministic%20Inputs.md

Ответ 4

Насколько я знаю, на каждой компиляции разные бинарные файлы MS различны. Около 20 лет назад это было не так. После каждого компиляции двоичные файлы MS были одинаковыми (при условии, что исходный код был тем же).