Используется ли семантическое управление версиями для совместимости с исходными или двоичными файлами?
Этот вопрос относится к любому языку, который написан на одном языке ( "источник" ), например. C или Java, и распределяется в другом ( "двоичном" ), например. машинный код или байт-код Java, используя динамическое связывание.
Предположим, что пользователь уже использует версию A моей библиотеки. Я выпускаю новую версию B.
Если он может скомпилировать свой код без изменений против B и правильно запустить с B, изменение от A до B называется совместимым с исходным кодом.
Если он может скомпилировать свой код против A и правильно запустить с B, изменение от A до B называется совместимым с двоичными файлами. Эта ситуация является общей при использовании транзитивных графиков зависимостей без загрузки изолированных модулей (например, OSGI). X скомпилирован против некоторых версий Y и Z, а Y был скомпилирован против другой определенной версии Z. Во время выполнения Y-вызовы в Z могут быть неправильными и могут выходить из строя.
Возможно, что изменения совместимы с исходным кодом, но двоичные несовместимы. Также возможно, что изменения несовместимы с источником и совместимы с бинарными.
Какую совместимость я использую для семантического управления версиями? Использую ли я исходную совместимость для различения основных и второстепенных/патч-обновлений, или я использую бинарную совместимость для различения обновлений основных и второстепенных/патчей?
Моя текущая мотивация - это библиотека Scala. Scala двоичная совместимость может быть очень сложной для анализа и требует хорошего понимания деталей компилятора. Совместимость источников и двоичная несовместимость очень распространены.
Это не какой-то причудливый краевой случай; эта проблема может появиться на большинстве компилируемых динамически связанных языков.
Ответы
Ответ 1
Несколько месяцев спустя, я думаю, у меня есть хороший вывод.
Семантическое управление версиями должно учитывать и то, и другое "наиболее измененное".
- Разрыв исходной компиляции - это несовместимое изменение для пользователей библиотеки.
- Нарушение исполнения во время выполнения - это несовместимое изменение для пользователей библиотеки.
Если совместимость с исходным кодом или бинарной совместимостью, она должна - в соответствии с семантическим версированием - стать новой основной версией.
В моем случае для Scala бинарную совместимость иногда бывает довольно сложно определить. Существует несколько различных инструментов JAR API, например. JDiff.
Ответ 2
Чтобы ответить на этот вопрос, притворитесь, что вы являетесь пользователем, который также не является программистом. С их точки зрения, исходный код бесполезен; они не понимают этого, и это им бессмысленно. С другой стороны, у них есть файл, содержащий объектный код, и они знают, что ему нужно куда-то идти. Для них важна только версия двоичного кода.
Это, однако, не конец истории. Ваш вопрос неявно содержит ядро гораздо лучшего ответа. Существует два вида совместимости, поэтому должны быть две последовательности версий. Сам вопрос содержит дисфункциональное предположение, а именно, что должна быть только одна последовательность версий.
Теперь, если у вас есть две последовательности версий и, кроме того, создать автоматический путь в конце пользователя для преобразования версий, совместимых с версиями, в объектно-совместимые версии, вы облегчили свою проблему. Чтобы сделать это, необходимо явно указать, как вы выполняете преобразование, например такие, как версия компилятора, версия интерпретатора, аргументы командной строки и т.д.
Короче говоря, лучший ответ на поставленный вопрос заключается в том, что он применяется к обоим им.