Здравствуйте, ·, Вы писали:
·>А компоненты всегда в исходниках что-ли распространяются? ·>Бардак в зависимостях может быть в каких-то либах между собой, а не в твоём проекте. Например, какой-нибудь фреймворк для логгирования может использоваться всеми либами. И каждая из них может быть скомпилена с разной версией логгера.
Ну тогда, вроде, будет у вас в проекте сразу 10 разных либ логгера. Тут еще вопрос — как их инициализировать и смогут ли они одновременно писать в один и тот же файл без конфликтов.
Здравствуйте, Shmj, Вы писали:
S>·>А компоненты всегда в исходниках что-ли распространяются? S>·>Бардак в зависимостях может быть в каких-то либах между собой, а не в твоём проекте. Например, какой-нибудь фреймворк для логгирования может использоваться всеми либами. И каждая из них может быть скомпилена с разной версией логгера. S>Ну тогда, вроде, будет у вас в проекте сразу 10 разных либ логгера. Тут еще вопрос — как их инициализировать и смогут ли они одновременно писать в один и тот же файл без конфликтов.
Именно. Это и есть главный вопрос, это и есть проблема ада зависимостей. Когда множество модулей, к исходникам которых у тебя нет доступа, используют разные версии зависимостей и их совместная становится невозможной. А показывать ошибки компиляции в твоём исходнике — хрень какая-то.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Shmj, Вы писали:
S>Вроде пишут что в Rust решили:
S>
S>В Rust с помощью Cargo можно одновременно использовать несколько версий одной и той же зависимости — без проблем и без танцев с бубном.
Кстати, нашел аналогию для подобных систем — это сказка о золотом петушке! Подобные системы — это и есть тот самый золотой петушок. Кто не читал и не смотрел — посмотрите мультик!
Правда, к линуксу это меньше относится, потому что есть отечественные дистрибутивы. Может быть, к maven из мира java тоже меньше относится, потому что там репозиториев много, да и большая часть кода давно выкачана в те же интранеты каждой отдельной крупной компании.
Здравствуйте, ·, Вы писали:
·>А компоненты всегда в исходниках что-ли распространяются?
Ну в таком случае, конечно, придется контролировать самому, т.к. C ABI не подразумевает каких-либо метаданных. Тем не менее, несколько версий все равно можно подключить.
Хотя в расте бинарные зависимости это очень нишевая вещь, встречаются редко.
·>Бардак в зависимостях может быть в каких-то либах между собой, а не в твоём проекте. Например, какой-нибудь фреймворк для логгирования может использоваться всеми либами. И каждая из них может быть скомпилена с разной версией логгера.
И что это меняет? Если это сорцы, компилятор точно так же проконтролирует. Если это скомпилированная либа, то бардак на совести того кто ее компилировал.
Здравствуйте, Manticore, Вы писали:
M>·>А компоненты всегда в исходниках что-ли распространяются? M>Ну в таком случае, конечно, придется контролировать самому, т.к. C ABI не подразумевает каких-либо метаданных. Тем не менее, несколько версий все равно можно подключить.
Неясно тогда какой же конкретно сабж решается. Несколько версий — ну фигня же. Статическая линковка уж пол века существует. В java — несколько класслоадеров и вперёд, тому же OSGi уже четверть века. Вот только ад это не решает, а лишь добавляет ещё один круг с ошибками вида expected "X", but found "X".
M>Хотя в расте бинарные зависимости это очень нишевая вещь, встречаются редко.
Я имею в виду обычные зависимости — crates. Они же не компилируются все каждый раз, верно?
Да и хуже того, ну обнаружил компилятор проблему, нарисовал тебе ошибку. Теперь тебе придётся разбираться что с чем не совместимо и как же это теперь решать и как собственно убедиться, что решение будет работать. И так при каждом минорном обновлении каждой зависимости.
M>·>Бардак в зависимостях может быть в каких-то либах между собой, а не в твоём проекте. Например, какой-нибудь фреймворк для логгирования может использоваться всеми либами. И каждая из них может быть скомпилена с разной версией логгера. M>И что это меняет? Если это сорцы, компилятор точно так же проконтролирует.
Проконтролирует что именно? Каждая либа компилируется отдельно, в разное время, разными командами, деплоится. Потом у себя в проекте ты подключаешь несколько либ — и упс.
M>Если это скомпилированная либа, то бардак на совести того кто ее компилировал.
Именно. Т.е. никакого сабжа нет.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, Shmj, Вы писали:
S>Вроде пишут что в Rust решили:
S>
S>В Rust с помощью Cargo можно одновременно использовать несколько версий одной и той же зависимости — без проблем и без танцев с бубном.
Это еще не вся проблема, есть еще количество зависимостей.
Тут хорошо про ад зависимостей: Дорога в ад JavaScript-зависимостей Вообще когда этим пользовался, то у меня возникло ощущение(наверно ошибочное), что многие добавляют в свои пакеты зависимости на другие пакеты, даже если без них можно обойтись, с той целью что это как-то поможет в поисковой выдаче. Т.е. как-то это связано с продвижением своего творений.
Здравствуйте, ·, Вы писали:
M>>Ну в таком случае, конечно, придется контролировать самому, т.к. C ABI не подразумевает каких-либо метаданных. Тем не менее, несколько версий все равно можно подключить. ·>Неясно тогда какой же конкретно сабж решается.
Я отвечаю в рамках вопроса в корне этого подтреда. О точном определении "ада зависимостей" — к ТС.
M>>Хотя в расте бинарные зависимости это очень нишевая вещь, встречаются редко. ·>Я имею в виду обычные зависимости — crates. Они же не компилируются все каждый раз, верно?
Нет, не каждый раз, но полностью статическими библиотеками они от этого не становятся, т.к. компилятор генерирует дополнительную метадату. Которую можно, в частности, использовать для контроля версий крейтов из которых пришли типы.
·>Да и хуже того, ну обнаружил компилятор проблему, нарисовал тебе ошибку. Теперь тебе придётся разбираться что с чем не совместимо и как же это теперь решать и как собственно убедиться, что решение будет работать. И так при каждом минорном обновлении каждой зависимости.
Нет. Подзависимости с версиями, например, 1.1 и 1.2 будут объединены в одну зависимость с версией как минимум 1.2. Если подзависимости требуют точные версии (=1.1 и =1.2), то резолвер выдаст ошибку (поэтому пинить версии в нормальных релизах считается дурным тоном и практически никогда не делается). Несколько копий зависимостей может быть только если их мажорные версии различаются. См. https://doc.rust-lang.org/cargo/reference/resolver.html
M>>И что это меняет? Если это сорцы, компилятор точно так же проконтролирует. ·>Проконтролирует что именно? Каждая либа компилируется отдельно, в разное время, разными командами, деплоится. Потом у себя в проекте ты подключаешь несколько либ — и упс.
Если это сорцы, то все компилируется в одно и то же время.
M>>Если это скомпилированная либа, то бардак на совести того кто ее компилировал. ·>Именно. Т.е. никакого сабжа нет.
Если ты подключаешь несколько разных версий одной бинарной либы, конвертирование между ее публичными типами это твоя забота, и никто за тебя ее не решит. Формат статических либ не подразумевает информации о версиях, так что компилятор тут бессилен. В расте практически все зависимости в сорцах, так что такой проблемы обычно не возникает.
Если же либа использует какой-то глобальный ресурс и не может синхронизировать это использование даже не с другими либами, а с самой собой, только лишь другой версии — ну тогда надо разработчиков этой либы пинать.
Здравствуйте, Manticore, Вы писали:
M>И что это меняет? Если это сорцы, компилятор точно так же проконтролирует. Если это скомпилированная либа, то бардак на совести того кто ее компилировал.
Здравствуйте, Manticore, Вы писали:
M>>Чем это отличается от плюсов, не очень понятно
M>Не знаю, я на плюсах последний раз писал лет пятнадцать назад. Туда уже менеджер зависимостей завезли?
Нет конечно, но компилятор обычно и без менеджера зависимостей тебя пошлёт, если будешь миксить разные версии одной либы
Здравствуйте, Marty, Вы писали:
M>Нет конечно, но компилятор обычно и без менеджера зависимостей тебя пошлёт, если будешь миксить разные версии одной либы
Если нет понятия версионированных зависимостей, нет и ада зависимостей, и решать нечего.
Здравствуйте, Manticore, Вы писали:
M>>>Ну в таком случае, конечно, придется контролировать самому, т.к. C ABI не подразумевает каких-либо метаданных. Тем не менее, несколько версий все равно можно подключить. M>·>Неясно тогда какой же конкретно сабж решается. M>Я отвечаю в рамках вопроса в корне этого подтреда.
Ну в том вопросе было про библиотеки и компоненты. Я вот до сих пор не понял как же компилятор ругается, если компоненты подключаются как зависимости. Вот конкретный пример. Допустим ты разрабатываешь rest-сервис. Тебе надо http-компонент и ssl-компонент. Компоненты разрабатываются и распространяются хрен знает когда и кем через какой-то публичный репо. Для твоего сервиса требуется http-3.1.4 (зависит от logger-1.0) и ssl-2.7.1 (зависит от logger-2.0). В твоём коде вообще ничего с logger нет, ты про него ничего не знаешь и знать не хочешь. Т.е. никакого "подключаешь несколько разных версий одной бинарной либы" у тебя нет. Несколько версий приходят транзитивно по зависимостям, у себя ты просто подключаешь соответствующие компоненты... и? В каком конкретно месте ругнётся компилятор?
Допустим компилятор даже ругнулся. Как ты будешь делать "конвертирование между ее публичными типами"? В каком месте? Тебе придётся брать и изучать исходники чужих компонент, про которые ты ничего не знаешь и вообще не копенгаген и пытаться их совместить, пересобрать и передиплоить в свой приватный репо, в публичный — у тебя пермиссий нет. Собственно это и есть ад.
А ещё потом ты захочешь отдать свой наконец-то хоть как-то работающий компонент другой команде и... следующий круг ада, когда они захотят в своём приложении совместить несколько rest-сервисов.
M>О точном определении "ада зависимостей" — к ТС.
Ну я бы хотел просто понять какой же конкретно ад зависимостей по твоему пониманию был решён в rust?
M>>>Хотя в расте бинарные зависимости это очень нишевая вещь, встречаются редко. M>·>Я имею в виду обычные зависимости — crates. Они же не компилируются все каждый раз, верно? M>Нет, не каждый раз, но полностью статическими библиотеками они от этого не становятся, т.к. компилятор генерирует дополнительную метадату. Которую можно, в частности, использовать для контроля версий крейтов из которых пришли типы.
Всё равно не понимаю причём тут компилятор. Обычно этим занимается package manager или project management tool. Т.к. работа идёт не на уровне сорцов, а на уровне пакетов/crates/dll/jar/etc. Во многих системах уже много лет есть механизмы описания и валидации графа зависимостей на совместимость... Что нового появилось в rust?
M>·>Да и хуже того, ну обнаружил компилятор проблему, нарисовал тебе ошибку. Теперь тебе придётся разбираться что с чем не совместимо и как же это теперь решать и как собственно убедиться, что решение будет работать. И так при каждом минорном обновлении каждой зависимости. M>Нет. Подзависимости с версиями, например, 1.1 и 1.2 будут объединены в одну зависимость с версией как минимум 1.2. Если подзависимости требуют точные версии (=1.1 и =1.2), то резолвер выдаст ошибку (поэтому пинить версии в нормальных релизах считается дурным тоном и практически никогда не делается). Несколько копий зависимостей может быть только если их мажорные версии различаются. См. https://doc.rust-lang.org/cargo/reference/resolver.html
cargo — это вроде как не компилятор.
M>>>И что это меняет? Если это сорцы, компилятор точно так же проконтролирует. M>·>Проконтролирует что именно? Каждая либа компилируется отдельно, в разное время, разными командами, деплоится. Потом у себя в проекте ты подключаешь несколько либ — и упс. M>Если это сорцы, то все компилируется в одно и то же время.
Сорцы чего? Я не понял. Возвращаюсь к примеру выше. Компилируя свой rest-сервис откуда возьмутся сорцы http/ssl/logger? Они все одновременно будут компилится?! Если так, то что тебе, как разработчику rest-сервиса дадут 100500 ошибок компиляции в тоннах кода http и ssl компонент? Дальше-то что?
M>>>Если это скомпилированная либа, то бардак на совести того кто ее компилировал. M>·>Именно. Т.е. никакого сабжа нет. M>Если ты подключаешь несколько разных версий одной бинарной либы, конвертирование между ее публичными типами это твоя забота, и никто за тебя ее не решит. Формат статических либ не подразумевает информации о версиях, так что компилятор тут бессилен. В расте практически все зависимости в сорцах, так что такой проблемы обычно не возникает. M>Если же либа использует какой-то глобальный ресурс и не может синхронизировать это использование даже не с другими либами, а с самой собой, только лишь другой версии — ну тогда надо разработчиков этой либы пинать.
Ну т.е. все должны делать всё правильно, тогда ада не будет. Хм, гениально! кто бы мог подумать...
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Здравствуйте, ·, Вы писали:
·>Ну в том вопросе было про библиотеки и компоненты. Я вот до сих пор не понял как же компилятор ругается, если компоненты подключаются как зависимости. Вот конкретный пример. Допустим ты разрабатываешь rest-сервис. Тебе надо http-компонент и ssl-компонент. Компоненты разрабатываются и распространяются хрен знает когда и кем через какой-то публичный репо. Для твоего сервиса требуется http-3.1.4 (зависит от logger-1.0) и ssl-2.7.1 (зависит от logger-2.0). В твоём коде вообще ничего с logger нет, ты про него ничего не знаешь и знать не хочешь. Т.е. никакого "подключаешь несколько разных версий одной бинарной либы" у тебя нет. Несколько версий приходят транзитивно по зависимостям, у себя ты просто подключаешь соответствующие компоненты... и? В каком конкретно месте ругнётся компилятор?
Если типы logger не видны в публичном API http и ssl, то ни в каком. Если logger-2.0 не умеет уживаться в одном процессе с logger-1.0, это баг logger-2.0.
·>Допустим компилятор даже ругнулся. Как ты будешь делать "конвертирование между ее публичными типами"? В каком месте?
Там где они используются совместно. Если одна зависимость возвращает тип из подзависимости, и это значение надо передать в другую зависимость которая использует подзависимость другой версии.
·>Тебе придётся брать и изучать исходники чужих компонент, про которые ты ничего не знаешь и вообще не копенгаген и пытаться их совместить, пересобрать и передиплоить в свой приватный репо, в публичный — у тебя пермиссий нет. Собственно это и есть ад.
В 99.9% случаев достаточно чтения документации. Например, я использую в одной своей либе crypto-bigint 0.6 и 0.7-pre. Библиотека эллиптических кривых возвращает мне порядок кривой в виде типа crypto_bigint::Uint из 0.6, а мне надо передать это значение в другую библиотеку которая использует 0.7-pre. Я смотрю в документацию, crypto_bigint::Uint можно конвертировать в указатель на массив цифр, можно сериализовать. Соответственно, в 0.7 можно восстановить из этого.
Насчет "пересобрать и передиплоить в свой приватный репо" я, если честно, вообще не понял о чем ты.
M>>О точном определении "ада зависимостей" — к ТС. ·>Ну я бы хотел просто понять какой же конкретно ад зависимостей по твоему пониманию был решён в rust?
Конфликт между совместимыми по API зависимостями. Т.к. в Расте уважают semver, любая более поздняя но совместимая по семверу либа может без проблем заменить более раннюю. Так что можно существенно облегчить граф зависимостей. Возможно, ТС имел в виду именно это.
·>Всё равно не понимаю причём тут компилятор. Обычно этим занимается package manager или project management tool. Т.к. работа идёт не на уровне сорцов, а на уровне пакетов/crates/dll/jar/etc. Во многих системах уже много лет есть механизмы описания и валидации графа зависимостей на совместимость... Что нового появилось в rust?
См. выше. Но, повторю, это лишь моя версия, я знаю что в Питоне граф зависимостей плоский, так что подход Раста по сравнению с ним — это шаг вперед. Но в JS зависимости в виде дерева, так что может там тоже зависимости объединяют. Что там есть "во многих системах" я не знаю, приводи конкретные примеры, сравним.
M>>·>Да и хуже того, ну обнаружил компилятор проблему, нарисовал тебе ошибку. Теперь тебе придётся разбираться что с чем не совместимо и как же это теперь решать и как собственно убедиться, что решение будет работать. И так при каждом минорном обновлении каждой зависимости. M>>Нет. Подзависимости с версиями, например, 1.1 и 1.2 будут объединены в одну зависимость с версией как минимум 1.2. Если подзависимости требуют точные версии (=1.1 и =1.2), то резолвер выдаст ошибку (поэтому пинить версии в нормальных релизах считается дурным тоном и практически никогда не делается). Несколько копий зависимостей может быть только если их мажорные версии различаются. См. https://doc.rust-lang.org/cargo/reference/resolver.html ·>cargo — это вроде как не компилятор.
Нет, не компилятор, но объединение зависимостей в cargo убирает большинство "несовместимостей", так что компилятор ругается только на то что автоматически не исправить. "что с чем не совместимо" очевидно из ошибки компилятора, "как же это теперь решать" в большинстве случаев очевидно из документации, "как собственно убедиться, что решение будет работать" — для этого пишут тесты.
·>Сорцы чего? Я не понял. Возвращаюсь к примеру выше. Компилируя свой rest-сервис откуда возьмутся сорцы http/ssl/logger? Они все одновременно будут компилится?!
В Расте, да.
·>Если так, то что тебе, как разработчику rest-сервиса дадут 100500 ошибок компиляции в тоннах кода http и ssl компонент?
Откуда ошибки-то? Если подзависимости используются внутри зависимостей это их внутреннее дело, пока они не светят их типы в публичном API. И даже тогда ошибка будет только если ты тип из одной версии попытаешься передать куда-то где нужен тип из другой. Я регулярно вижу в дереве зависимостей один и тот же крейт разных версий. Проблем это не создает, кроме времени компиляции.
Здравствуйте, Manticore, Вы писали:
M>·>Ну в том вопросе было про библиотеки и компоненты. Я вот до сих пор не понял как же компилятор ругается, если компоненты подключаются как зависимости. Вот конкретный пример. Допустим ты разрабатываешь rest-сервис. Тебе надо http-компонент и ssl-компонент. Компоненты разрабатываются и распространяются хрен знает когда и кем через какой-то публичный репо. Для твоего сервиса требуется http-3.1.4 (зависит от logger-1.0) и ssl-2.7.1 (зависит от logger-2.0). В твоём коде вообще ничего с logger нет, ты про него ничего не знаешь и знать не хочешь. Т.е. никакого "подключаешь несколько разных версий одной бинарной либы" у тебя нет. Несколько версий приходят транзитивно по зависимостям, у себя ты просто подключаешь соответствующие компоненты... и? В каком конкретно месте ругнётся компилятор? M>Если типы logger не видны в публичном API http и ssl, то ни в каком. Если logger-2.0 не умеет уживаться в одном процессе с logger-1.0, это баг logger-2.0.
Ну дык, а ты думаешь в рай попал, где багов нет? В этом-то и есть суть ада зависимостей.
M>·>Допустим компилятор даже ругнулся. Как ты будешь делать "конвертирование между ее публичными типами"? В каком месте? M>Там где они используются совместно. Если одна зависимость возвращает тип из подзависимости, и это значение надо передать в другую зависимость которая использует подзависимость другой версии.
Представь себе у тебя 5 зависимостей и все они друг-другу что-то передают. Например прокидывают объекты через одну очередь. Тебе придётся писать 2^5 конверсий из каждой версии в каждую, даже если они все совместимы по типам/сигнатурам?
M>·>Тебе придётся брать и изучать исходники чужих компонент, про которые ты ничего не знаешь и вообще не копенгаген и пытаться их совместить, пересобрать и передиплоить в свой приватный репо, в публичный — у тебя пермиссий нет. Собственно это и есть ад. M>В 99.9% случаев достаточно чтения документации. Например, я использую в одной своей либе crypto-bigint 0.6 и 0.7-pre. Библиотека эллиптических кривых возвращает мне порядок кривой в виде типа crypto_bigint::Uint из 0.6, а мне надо передать это значение в другую библиотеку которая использует 0.7-pre. Я смотрю в документацию, crypto_bigint::Uint можно конвертировать в указатель на массив цифр, можно сериализовать. Соответственно, в 0.7 можно восстановить из этого.
Эээээ. А как это согласуется с "Расте уважают semver"? Почему ВНЕЗАПНО просто нельзя использовать 0.7?
M>Насчет "пересобрать и передиплоить в свой приватный репо" я, если честно, вообще не понял о чем ты.
Чтобы код для адаптации версий между собой реюзать из разных мест. В моём примере выше — создать "http-3.1.4_withLogger2", т.е. адаптированный http-3.1.4 для совместимости с logger-2.0.
M>>>О точном определении "ада зависимостей" — к ТС. M>·>Ну я бы хотел просто понять какой же конкретно ад зависимостей по твоему пониманию был решён в rust? M>Конфликт между совместимыми по API зависимостями. Т.к. в Расте уважают semver, любая более поздняя но совместимая по семверу либа может без проблем заменить более раннюю. Так что можно существенно облегчить граф зависимостей. Возможно, ТС имел в виду именно это.
Ну так и semver не в расте придумали. Конечно, подход "всё умеет уживаться друг с другом" — это и есть сабж. Но баги это не отменяет. Да и усложняет сильно всё. Что надо полный backward compatibility иметь, что раздувает код всякими "конвертировать в указатель на массив цифр, можно сериализовать".
M>·>Всё равно не понимаю причём тут компилятор. Обычно этим занимается package manager или project management tool. Т.к. работа идёт не на уровне сорцов, а на уровне пакетов/crates/dll/jar/etc. Во многих системах уже много лет есть механизмы описания и валидации графа зависимостей на совместимость... Что нового появилось в rust? M>См. выше. Но, повторю, это лишь моя версия, я знаю что в Питоне граф зависимостей плоский, так что подход Раста по сравнению с ним — это шаг вперед. Но в JS зависимости в виде дерева, так что может там тоже зависимости объединяют. Что там есть "во многих системах" я не знаю, приводи конкретные примеры, сравним.
Ну все эти pinned-версии, range-версии, и т.п. есть в большинстве pm тулзов.
M>>>Нет. Подзависимости с версиями, например, 1.1 и 1.2 будут объединены в одну зависимость с версией как минимум 1.2. Если подзависимости требуют точные версии (=1.1 и =1.2), то резолвер выдаст ошибку (поэтому пинить версии в нормальных релизах считается дурным тоном и практически никогда не делается). Несколько копий зависимостей может быть только если их мажорные версии различаются. См. https://doc.rust-lang.org/cargo/reference/resolver.html M>·>cargo — это вроде как не компилятор. M>Нет, не компилятор, но объединение зависимостей в cargo убирает большинство "несовместимостей", так что компилятор ругается только на то что автоматически не исправить. "что с чем не совместимо" очевидно из ошибки компилятора, "как же это теперь решать" в большинстве случаев очевидно из документации, "как собственно убедиться, что решение будет работать" — для этого пишут тесты.
Ну вроде про автоматическое исправление это и есть совместимость по типам-сигнатурам. Неясно причём тут номера версий.
M>·>Сорцы чего? Я не понял. Возвращаюсь к примеру выше. Компилируя свой rest-сервис откуда возьмутся сорцы http/ssl/logger? Они все одновременно будут компилится?! M>В Расте, да.
Это ж сколько оно компилируется... И главное зачем..
M>·>Если так, то что тебе, как разработчику rest-сервиса дадут 100500 ошибок компиляции в тоннах кода http и ssl компонент? M>Откуда ошибки-то? Если подзависимости используются внутри зависимостей это их внутреннее дело, пока они не светят их типы в публичном API. И даже тогда ошибка будет только если ты тип из одной версии попытаешься передать куда-то где нужен тип из другой. Я регулярно вижу в дереве зависимостей один и тот же крейт разных версий. Проблем это не создает, кроме времени компиляции.
А вот такое не создаёт проблем? В зависимости где какие версии — количество инстансов одной переменной разное.
The final rustc invocation by cargo will only add the shared dependency once. If you use two different incompatible versions of the shared dependency, then it will be added "twice".
Как вообще с таким справляться?
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай