Может ли сборка из одного исходного кода выводить функционально разные исполняемые файлы?

Недавно мой коллега сказал что-то в этом роде: «Последовательные APK (исполняемые файлы), созданные сервером сборки из одного и того же исходного кода, могут быть не такими же». Контекст для этого обсуждения заключался в том, относится ли QA к построению X к построению Y, который был выполнен одним и тем же сервером сборки (настроенным таким же образом) из того же исходного кода.

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

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

Мои вопросы:

  1. Верно ли, что последовательные сборки, выполненные одним и тем же сервером сборки из одного и того же исходного кода, могут быть функционально разными?
  2. Если # 1 истинно, эти различия ограничены неправильно синхронизированным многопоточным кодом?
  3. Если № 2 неверно, какие другие части могут измениться?

Ссылки на любые связанные с этим материалы будут оценены.

Solutions Collecting From Web of "Может ли сборка из одного исходного кода выводить функционально разные исполняемые файлы?"

Это, безусловно, возможно в нескольких случаях. Предположим, вы используете Gradle для создания своего Android-приложения.

Случай 1: вы используете зависимую от третьей стороны, которая включена в шаблон подстановки версии, например:

compile somelib.1+

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

Случай 2: вы вводите информацию об окружающей среде в свое приложение, используя Greedle's buildConfigFields. Эти значения будут введены в класс BuildConfig вашего приложения. В зависимости от того, как вы используете эти значения, поведение приложения может варьироваться в зависимости от последовательных сборок.

Случай 3: вы обновляете JDK на своих CI между последовательными сборками. Возможно, хотя я предполагаю, что маловероятно, что поведение вашего приложения может измениться в зависимости от того, как оно скомпилировано. Например, вы можете столкнуться с краем в JDK, который исправляется в более поздней версии, вызывая ранее работавший ранее код, чтобы действовать по-другому.

Я думаю, это отвечает на ваш первый вопрос и второй вопрос.

Редактировать: извините, я думаю, что пропустил какую-то важную информацию из вашего OP. Мой случай 2 является примером вашей eg different timestamp а случай 3 нарушает вашу configured the same way . Однако я оставлю здесь ответ.

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

Некоторые советы: если это возможно, чтобы перестроить его, используйте подробный режим построения инструмента (например, -X в maven) и сравните вывод строки за строкой с некоторой программой diff

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

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

Используя android / gradle, одна из возможных причин привести к другому поведению или ошибкам в целом – это использовать + в файле build.gradle для версий библиотеки. Вот почему вам следует избегать этого, поскольку последовательная сборка может извлекать новую / другую версию, поэтому у вас будет другой исходный код, и, следовательно, он может создать функциональный исполняемый файл.

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

[…] последовательные сборки, выполненные одним и тем же сервером сборки из одного и того же исходного кода, могут быть функционально разными

Нет. Как описано выше, если вы используете одни и те же версии, тот же исходный код, он должен вызывать такое же поведение. Если вы ничего не сделаете неправильно.

[…] Эти различия ограничены неправильно синхронизированным многопоточным кодом?

Это означало бы ошибку с вашим компилятором. Хотя это возможно, это крайне маловероятно.

[…] какие другие части могут измениться?

Помимо отметки времени и номера сборки ничего не изменится, учитывая тот же исходный код и конфигурацию.


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

Они должны быть идентичными, за исключением:

  • В системе сборки есть проблемы с потоком / оптимизацией.

  • Аппаратные сбои Проблемы с CPU / RAM / HDD в среде сборки

  • Время / платформа, связанная с кодом в самой сборке или скрипты сборки

Поэтому, если вы строите точно такой же код на одном и том же HW, используя ту же самую версию системы сборки, то такая же версия ОС и ваш код НЕ ОСОБЕННО ЗАВИСИМА от результата времени сборки должны быть одинаковыми . Они даже должны иметь точные контрольные суммы и размер.

Также результаты одинаковы ТОЛЬКО, если ваш код не зависит от внешних модулей, которые загружаются из Интернета во время сборки, например Gradle / Maven, – вы не можете получать эти библиотеки одинаково из-за того, что они не находятся в управлении версиями. Кроме того, может быть зависимость, если версия модуля указана не точно (например, 2.0. +), Поэтому, если сопровождающий обновил этот модуль, ваша система сборки будет использовать обновленную версию -> так что в основном ваши сборки, созданные из другого исходного кода.

Поскольку кто-то упоминает использование тестов Unit на сервере сборки, это хорошая практика, чтобы убедиться, что ваша сборка стабильна и не содержит явных ошибок.

Хотя этот вопрос касается Java / Android, Джон Скит писал о разных синтаксических анализаторах C #, обрабатывающих некоторые символы Unicode по-разному , в основном из-за изменений в базе данных символов Unicode.

В его примерах Монгольский разделитель гласных (U + 180E) считается либо символом пробела, либо символом, допускаемым внутри идентификатора, что дает разные результаты в назначениях переменных.

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

Представьте шаблон стратегии, который позволяет выбирать между алгоритмами во время выполнения и загружать один алгоритм на основе RNG.