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