Если бы я должен был скомпилировать программу в один двоичный файл, создать контрольную сумму, а затем перекомпилировать ее на той же машине с теми же настройками компилятора и компилятора и контрольной суммой перекомпилированной программы, провалилась бы контрольная сумма?
Если так, то почему? Если нет, то будет ли иметь другой процессор результат в неидентичном двоичном файле?
Ответы:
Скомпилируйте ту же программу с теми же настройками на той же машине:
Хотя окончательный ответ «это зависит», разумно ожидать, что большинство компиляторов будет детерминистическим большую часть времени, и что создаваемые двоичные файлы должны быть идентичными. Действительно, некоторые системы контроля версий зависят от этого. Тем не менее, всегда есть исключения; вполне возможно, что какой- то компилятор решит вставить метку времени или что-то подобное (например, iirc, Delphi). Или сам процесс сборки может сделать это; Я видел make-файлы для программ на C, которые устанавливают макрос препроцессора на текущую метку времени. (Я думаю, это будет считаться другой настройкой компилятора.)
Также имейте в виду, что если вы статически связываете двоичный файл, то вы фактически включаете состояние всех соответствующих библиотек на своем компьютере, и любое изменение в любой из них также повлияет на ваш двоичный файл. Таким образом, важны не только настройки компилятора.
Скомпилируйте ту же программу на другом компьютере с другим процессором.
Здесь все ставки сняты. Большинство современных компиляторов способны выполнять целевые оптимизации; если эта опция включена, то двоичные файлы, вероятно, будут отличаться, если процессоры не похожи (и даже тогда, это возможно). Также см. Примечание о статической компоновке: среда конфигурации выходит далеко за пределы настроек компилятора. Если у вас нет очень строгого контроля конфигурации, очень вероятно, что что-то отличается между двумя машинами.
источник
gcc -c
вполне могут быть идентичными, но связанные версии отличаются. Кроме того, это не просто-march
; есть также-mtune/-mcpu
и-mfpmatch
(и, возможно, другие). Некоторые из них могут иметь разные значения по умолчанию в разных установках, поэтому вам может потребоваться явно указать наихудший вариант для ваших машин; это может значительно снизить производительность, особенно если вы вернетесь к i386 без sse. И, конечно, если один из ваших процессоров - ARM, а другой - i686 ...То, что вы спрашиваете, это « детерминирован ли выход ». Если вы скомпилировали программу один раз, сразу же скомпилировали ее снова, вы, вероятно, получили бы тот же выходной файл. Однако, если что-то изменилось - даже небольшое изменение - особенно в компоненте, который использует скомпилированная программа, то выходные данные компилятора также могут измениться.
источник
-frandom-seed=string
.Для всех компиляторов? Нет. Компилятору C #, по крайней мере, не разрешено.
У Эрика Липперта очень подробное объяснение, почему вывод компилятора не является детерминированным .
Хотя это специфично для версии компилятора C #, многие пункты в статье могут быть применены к любому компилятору.
источник
-frandom-seed=123
контролирует некоторую внутреннюю случайность GCC.man gcc
говорит:__FILE__
: поместите источник в фиксированную папку (например/tmp/build
)__DATE__
,__TIME__
,__TIMESTAMP__
:-D
-Wdate-time
или-Werror=date-time
: предупреждение или ошибка, если либо используется__TIME__
,__DATE__
либо__TIMESTAMP__
используются. Ядро Linux 4.4 использует его по умолчанию.D
флагar
или используйте https://github.com/nh2/ar-timestamp-wiper/tree/master чтобы стереть штампы-fno-guess-branch-probability
: старые версии руководства говорят, что это источник недетерминизма, но не больше . Не уверен, что это покрыто-frandom-seed
или нет.Debian Reproducible строит проект, пытаясь стандартизировать пакеты Debian побайтово, и недавно получил грант Linux Foundation . Это включает в себя больше, чем просто компиляция, но она должна представлять интерес.
У Buildroot есть
BR2_REPRODUCIBLE
опция, которая может дать некоторые идеи на уровне пакета, но на данный момент она далека от завершения.Связанные темы:
источник
Проект https://reproducible-builds.org/ - это все об этом, и он изо всех сил старается ответить на ваш вопрос «нет, они не будут различаться» в максимально возможном количестве мест. Сейчас NixOS и Debian воспроизводят свои пакеты более чем на 90%.
Если вы скомпилируете двоичный файл, а я скомпилировал двоичный файл, и они по битам идентичны, то я могу быть уверен, что исходный код и инструменты определяют выход, и что в некоторых случаях вы не крались Троянский код по пути.
Если мы совмещаем воспроизводимость с загрузкой из читаемого человеком источника, как работает http://bootstrappable.org/ , мы получаем систему, определяемую с нуля читаемым человеком источником, и только тогда мы находимся в точке, где мы можем верить, что знаем, что делает система.
источник
Я бы сказал, НЕТ, это не на 100% детерминировано. Ранее я работал с версией GCC, которая генерирует целевые двоичные файлы для процессора Hitachi H8.
Это не проблема с отметкой времени. Даже если проблема с отметкой времени игнорируется, конкретная архитектура процессора может позволять кодировать одну и ту же инструкцию 2 слегка отличающимися способами, где некоторые биты могут быть 1 или 0. Мой предыдущий опыт показывает, что сгенерированные двоичные файлы были одинаковыми MOST времени но иногда gcc генерирует двоичные файлы одинакового размера, но некоторые байты отличаются только на 1 бит, например, 0XE0 становится 0XE1.
источник
В общем нет. Наиболее разумно сложные компиляторы будут включать время компиляции в объектный модуль. Даже если бы вам пришлось сбрасывать часы, вы должны были бы быть очень точными в отношении того, когда вы запускали компиляцию (и затем надеяться, что обращения к диску и т. Д. Будут такими же, как и раньше).
источник