Курс СРС SRS08
до ЛР4 рівень 3 → «5»↔ Лабораторна 4↔ Лекція 4⌨️ команди 6 · 3 нових
Самостійна робота · ~3 год

Екосистема crates.io, Cargo.toml/Cargo.lock і семантичне версіонування залежностей

🌌 Арсенал відмички — Кожен зовнішній crate — інструмент зі складу спільноти: С.І.Д. з теплою прискіпливістю нагадує, що версія інструменту важлива — інакше несумісне оновлення чужого коду підірве відмичку в найневідповідніший момент. А Cargo.lock, гордо показує він, — це точний опис того, який саме інструмент зі складу насправді використовувався.

📚 ТЕОРЕТИЧНІ ВІДОМОСТІ

Cargo, реєстр і два файли конфігурації

Cargo — офіційний менеджер збірки й пакетів Rust. Cargo.toml описує намір: ім'я, версію та діапазон допустимих версій кожної залежності (наприклад, serde = "1" неявно означає «будь-яка сумісна версія від 1.0.0 включно до, але не включаючи, 2.0.0» — це і є семантика оператора ^, застосованого за замовчуванням у Cargo). Cargo.lock, навпаки, фіксує факт: точну версію кожної залежності (і транзитивної залежності залежностей), яку Cargo реально дозволив для цієї збірки, разом із хешем вмісту для перевірки цілісності. Для бібліотек Cargo.lock зазвичай не комітять у git (кінцевий користувач бібліотеки сам вирішує версії), а для бінарних застосунків — навпаки, комітять обов'язково, щоб збірка була однаковою на будь-якій машині й у будь-який день.

Семантичне версіонування (SemVer) — угода MAJOR.MINOR.PATCH, якої дотримується (хоч і не примусово технічно) переважна більшість crates.io: MAJOR зростає при зміні, що ламає зворотну сумісність публічного API (перейменування функції, зміна сигнатури); MINOR — при доданні нової функціональності без поламання наявної; PATCH — при виправленні багів без зміни публічного інтерфейсу. Оператор ^ (неявний за замовчуванням у Cargo.toml) дозволяє Cargo автоматично підбирати найновішу сумісну версію в межах того самого MAJOR (а для версій 0.x.y — у межах того самого MINOR, оскільки в SemVer 0.x вважається нестабільним API).

Команда cargo build використовує вже наявний Cargo.lock, якщо він є й сумісний із поточним Cargo.toml — це гарантує детермінованість щоденної розробки. cargo update навпаки — свідомо перераховує Cargo.lock, підбираючи найновіші версії в межах дозволених діапазонів Cargo.toml, і саме тут може «прилетіти» несумісна поведінка, якщо якась транзитивна залежність порушила SemVer (публікувала зміну, що фактично ламає сумісність, під MINOR- чи навіть PATCH-версією — на жаль, у реальній екосистемі таке трапляється, тож Cargo.lock у застосунках — не формальність, а реальний захист від «зламалося саме по собі»).

Якщо в Cargo.toml явно вказати мажорну версію, несумісну з наявним кодом (наприклад, підняти serde = "2.0", коли реальний API проєкту написаний під 1.x), cargo build спробує підтягнути нову мажорну версію, і якщо її публічний API справді відрізняється — компіляція впаде з помилками невідповідності типів чи відсутніх елементів, які потрібно буде виправляти вручну (це і є суть «ламає сумісність»: інструмент зі складу став іншої форми, і стара відмичка до нього вже не пасує).

Кожна залежність на crates.io має власну сторінку з розділами «Versions» (історія публікацій), «Dependencies» (що вона сама тягне транзитивно) і зазвичай CHANGELOG/примітками до релізу — саме там варто перевіряти, чи оновлення справді PATCH/MINOR за духом, а не лише за номером. Транзитивні залежності (залежності залежностей) теж підпорядковуються SemVer-резолвінгу Cargo, і саме вони найчастіше стають джерелом несподіваних конфліктів версій у великих проєктах — cargo tree показує повне дерево залежностей і допомагає знайти, звідки саме прийшла конкретна версія конфліктного крейта (crate) — зовнішнього пакета Rust.

📖 ОПРАЦЮВАТИ

Переглянути сторінку залежності на crates.io (наприклад, sha2 або serde) і файл Cargo.lock власного проєкту; спробувати змінити версію в Cargo.toml на несумісну (major) і подивитися, що станеться при cargo build і cargo update.

🖥️ ТЕРМІНАЛ — СПРОБУЙ САМ
🎯 ЗАВДАННЯ
  1. Відкрити сторінку будь-якого популярного крейта на crates.io (наприклад, serde чи rand), знайти розділ Versions і виписати три останні версії з поясненням, чи є серед них MAJOR/MINOR/PATCH-стрибок.
  2. У власному проєкті виконати cargo tree і знайти хоча б одну транзитивну залежність (не вказану напряму в Cargo.toml), пояснивши, яка з прямих залежностей її підтягнула.
  3. Свідомо змінити версію однієї залежності в Cargo.toml на завідомо несумісну мажорну (наприклад, з "1" на "2", якщо для крейта існує версія 2.x) і зафіксувати точний текст помилок компіляції, які виникли.
  4. Порівняти Cargo.lock до і після виконання cargo update (зберегти обидві версії файлу) і знайти в diff хоча б одну залежність, версія якої змінилася в межах дозволеного семверу.
  5. Написати короткий регламент (5-7 пунктів) для команди розробників: коли комітити Cargo.lock, коли безпечно виконувати cargo update, і яку перевірку робити перед підняттям мажорної версії критичної залежності.
❓ КОНТРОЛЬНІ ПИТАННЯ
  1. Що саме фіксує Cargo.toml, а що — Cargo.lock, і чому для бінарних застосунків Cargo.lock зазвичай комітять у репозиторій?
  2. Що означають три числа у версії 1.4.2 за семантичним версіонуванням, і яке з них ламає сумісність API?
  3. Який діапазон версій дозволяє запис serde = "1" у Cargo.toml за замовчуванням (оператор ^)?
  4. Чим команда cargo build відрізняється від cargo update щодо роботи з Cargo.lock?
  5. Чому версії 0.x.y в SemVer вважаються особливим випадком, і як це впливає на резолвінг Cargo?
  6. Що покаже команда cargo tree і для якого класу проблем вона корисна?
  7. Що станеться при cargo build, якщо явно піднята мажорна версія залежності справді змінила публічний API, від якого залежить код проєкту?
✅ САМОПЕРЕВІРКА

Що означають три числа у версії 1.4.2 за семантичним версіонуванням (SemVer), і яке з них означає, що зміна ламає сумісність публічного API?

🥚 ПАСХАЛКА
Версія, якою С.І.Д. підписує власні збірки, — 3.10.1 (прочитай цифри поспіль без крапок), і MAJOR він обіцяє не піднімати ніколи: ламати сумісність із ранером — не в його стилі. На crates.io він себе не викладе: Cargo.lock фіксує checksum кожного пакета, а той, хто хоче зникнути в мережі, не лишає хешів, за якими його знайдуть.
⌨️ КОМАНДИ НА ЦІЙ СТОРІНЦІ 6 · 3 нових

Кожна команда терміналу з цієї сторінки — одним реченням. Позначка нове — команда зустрічається в курсі вперше; далі вважаємо її знайомою.

cargo treeнове
Малює дерево залежностей — хто кого тягне і які версії.
cargo
Система збірки й менеджер пакетів Rust: створює проєкт, тягне залежності (крейти), збирає, тестує, запускає.
cargo updateнове
Оновлює версії залежностей у Cargo.lock у межах, дозволених Cargo.toml (cargo update -p serde).
git diffнове
Показує, що саме змінилося у файлах порівняно з останнім комітом (git diff Cargo.lock).
git
Система керування версіями: історія змін, гілки, теги; здача робіт у курсі — через теги submit/labNN.
cargo build
Компілює проєкт у target/debug/; --release — з оптимізаціями у target/release/.

💡 Прочитати README прямо в терміналі: cat README.md (виведе весь файл) або less README.md (посторінково; вихід — клавіша q).
Довідка з будь-якої команди: man curl (повний посібник, вихід — q) або коротко curl --help; для підкоманд — docker run --help, cargo build --help.

← SRS07усі темиSRS09 →