Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Cargo-työtilat

Luvussa 12 rakensimme paketin, joka sisälsi binääricraten ja kirjastocraten. Projektin kehittyessä kirjastocrate voi kasvaa niin suureksi, että haluatte jakaa pakettinne edelleen useisiin kirjastocrateihin. Cargo tarjoaa ominaisuuden nimeltä työtilat, joka voi auttaa hallitsemaan useita toisiinsa liittyviä paketteja, joita kehitetään rinnakkain.

Työtilan luominen

Työtila on joukko paketteja, jotka jakavat saman Cargo.lock-tiedoston ja tulostushakemiston. Tehdään projekti käyttäen työtilaa—käytämme triviaalia koodia, jotta voimme keskittyä työtilan rakenteeseen. Työtilan voi rakentaa monella tavalla, joten näytämme vain yhden yleisen tavan. Työtilassa on binääri ja kaksi kirjastoa. Binääri, joka tarjoaa päätoiminnallisuuden, riippuu kahdesta kirjastosta. Yksi kirjasto tarjoaa add_one-funktion ja toinen kirjasto add_two-funktion. Nämä kolme cratea ovat osa samaa työtilaa. Aloitamme luomalla uuden hakemiston työtilalle:

$ mkdir add
$ cd add

Seuraavaksi add-hakemistossa luomme Cargo.toml-tiedoston, joka määrittää koko työtilan. Tässä tiedostossa ei ole [package]-osiota. Sen sijaan se alkaa [workspace]-osiolla, jonka avulla voimme lisätä jäseniä työtilaan. Varmistamme myös, että käytämme Cargon uusinta ja parasta resolver-algoritmia työtilassamme asettamalla resolver-asetuksen arvoksi "3":

Tiedostonimi: Cargo.toml

{{#include ../listings/ch14-more-about-cargo/no-listing-01-workspace/add/Cargo.toml}}

Seuraavaksi luomme adder-binääricraten suorittamalla cargo new -komennon add-hakemistossa:

$ cargo new adder
     Created binary (application) `adder` package
      Adding `adder` as member of workspace at `file:///projects/add`

cargo new -komennon suorittaminen työtilan sisällä lisää myös automaattisesti juuri luodun paketin työtilan Cargo.toml-tiedoston [workspace]-määrittelyn members-avaimeen, näin:

{{#include ../listings/ch14-more-about-cargo/output-only-01-adder-crate/add/Cargo.toml}}

Tässä vaiheessa voimme rakentaa työtilan suorittamalla cargo build -komennon. Tiedostot add-hakemistossanne pitäisi näyttää tältä:

├── Cargo.lock
├── Cargo.toml
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target

Työtilalla on yksi target-hakemisto ylätasolla, johon käännetyt artefaktit sijoitetaan; adder-paketilla ei ole omaa target-hakemistoa. Vaikka suorittaisimme cargo build -komennon adder-hakemiston sisältä, käännetyt artefaktit päätyisivät silti hakemistoon add/target eikä add/adder/target. Cargo rakentaa target-hakemiston työtilassa näin, koska työtilan cratet on tarkoitettu riippuvan toisistaan. Jos jokaisella cratella olisi oma target-hakemisto, jokaisen craten täytyisi kääntää uudelleen jokainen työtilan muista crateista sijoittaakseen artefaktit omaan target-hakemistoonsa. Jakamalla yhden target-hakemiston cratet voivat välttää tarpeettoman uudelleenkääntämisen.

Toisen paketin luominen työtilaan

Seuraavaksi luodaan työtilaan toinen jäsenpaketti ja kutsutaan sitä add_one. Luodaan uusi kirjastocrate nimeltä add_one:

$ cargo new add_one --lib
     Created library `add_one` package
      Adding `add_one` as member of workspace at `file:///projects/add`

Ylätason Cargo.toml-tiedosto sisältää nyt add_one-polun members-listassa:

Tiedostonimi: Cargo.toml

{{#include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/Cargo.toml}}

add-hakemistossanne pitäisi nyt olla nämä hakemistot ja tiedostot:

├── Cargo.lock
├── Cargo.toml
├── add_one
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target

Lisätään add_one/src/lib.rs-tiedostoon add_one-funktio:

Tiedostonimi: add_one/src/lib.rs

{{#rustdoc_include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/add_one/src/lib.rs}}

Nyt voimme tehdä adder-paketista, jossa on binäärimme, riippuvaisen add_one-paketista, jossa on kirjastomme. Ensin meidän täytyy lisätä polkuriippuvuus add_one-pakettiin tiedostoon adder/Cargo.toml.

Tiedostonimi: adder/Cargo.toml

{{#include ../listings/ch14-more-about-cargo/no-listing-02-workspace-with-two-crates/add/adder/Cargo.toml:6:7}}

Cargo ei oleta, että työtilan cratet riippuvat toisistaan, joten meidän täytyy määritellä riippuvuussuhteet eksplisiittisesti.

Seuraavaksi käytetään add_one-funktiota (add_one-cratesta) adder-cratessa. Avatkaa adder/src/main.rs-tiedosto ja muuttakaa main-funktiota kutsumaan add_one-funktiota, kuten listauksessa 14-7.

Filename: adder/src/main.rs
{{#rustdoc_include ../listings/ch14-more-about-cargo/listing-14-07/add/adder/src/main.rs}}
Listing 14-7: add_one-kirjastocraten käyttö adder-cratessa

Rakennetaan työtila suorittamalla cargo build -komento ylätason add-hakemistossa!

$ cargo build
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.22s

Suorittaaksemme binääricraten add-hakemistosta voimme määrittää, minkä paketin työtilassa haluamme suorittaa käyttämällä -p-argumenttia ja paketin nimeä komennolla cargo run:

$ cargo run -p adder
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/adder`
Hello, world! 10 plus one is 11!

Tämä suorittaa koodin tiedostossa adder/src/main.rs, joka riippuu add_one-cratesta.

Ulkoisen paketin riippuvuus

Huomaa, että työtilassa on vain yksi Cargo.lock-tiedosto ylätasolla sen sijaan, että jokaisella craten hakemistolla olisi oma Cargo.lock. Tämä varmistaa, että kaikki cratet käyttävät samaa versiota kaikista riippuvuuksista. Jos lisäämme rand-paketin tiedostoihin adder/Cargo.toml ja add_one/Cargo.toml, Cargo ratkaisee molemmat yhdeksi rand-versioksi ja tallentaa sen yhteen Cargo.lock-tiedostoon. Kaikkien työtilan cratejen saman riippuvuuksien käyttö tarkoittaa, että cratet ovat aina yhteensopivia toistensa kanssa. Lisätään rand-crate [dependencies]-osioon tiedostoon add_one/Cargo.toml voidaksemme käyttää rand-cratea add_one-cratessa:

Tiedostonimi: add_one/Cargo.toml

{{#include ../listings/ch14-more-about-cargo/no-listing-03-workspace-with-external-dependency/add/add_one/Cargo.toml:6:7}}

Voimme nyt lisätä use rand; tiedostoon add_one/src/lib.rs ja rakentaa koko työtilan suorittamalla cargo build -komennon add-hakemistossa, mikä tuo mukaan ja kääntää rand-craten. Saamme yhden varoituksen, koska emme viittaa näkyviin tuomaamme rand-crateen:

$ cargo build
    Updating crates.io index
  Downloaded rand v0.10.1
   --snip--
   Compiling rand v0.10.1
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
warning: unused import: `rand`
 --> add_one/src/lib.rs:1:5
  |
1 | use rand;
  |     ^^^^
  |
  = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default

warning: `add_one` (lib) generated 1 warning (run `cargo fix --lib -p add_one` to apply 1 suggestion)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.95s

Ylätason Cargo.lock sisältää nyt tietoa add_one-craten riippuvuudesta rand-crateen. Vaikka rand-cratea käytetään jossain työtilassa, emme voi käyttää sitä muissa työtilan crateissa, ellemme lisää rand-cratea myös niiden Cargo.toml-tiedostoihin. Esimerkiksi jos lisäämme use rand; tiedostoon adder/src/main.rs adder-paketille, saamme virheen:

$ cargo build
  --snip--
   Compiling adder v0.1.0 (file:///projects/add/adder)
error[E0432]: unresolved import `rand`
 --> adder/src/main.rs:2:5
  |
2 | use rand;
  |     ^^^^ no external crate `rand`

Korjataksemme tämän muokkaa adder-paketin Cargo.toml-tiedostoa ja ilmoittakaa, että rand on riippuvuus myös sille. adder-paketin rakentaminen lisää rand-craten adder-paketin riippuvuuksien listaan tiedostossa Cargo.lock, mutta yhtään lisäkopiota rand-cratesta ei ladata. Cargo varmistaa, että jokainen crate jokaisessa työtilan paketissa, joka käyttää rand-pakettia, käyttää samaa versiota niin kauan kuin ne määrittävät yhteensopivia versioita rand-cratesta, säästäen tilaa ja varmistaen, että työtilan cratet ovat yhteensopivia toistensa kanssa.

Jos työtilan cratet määrittävät yhteensopimattomia versioita samasta riippuvuudesta, Cargo ratkaisee jokaisen niistä, mutta yrittää silti ratkaista mahdollisimman vähän versioita.

Testin lisääminen työtilaan

Lisäparannuksena lisätään testi add_one::add_one-funktiolle add_one-cratessa:

Tiedostonimi: add_one/src/lib.rs

{{#rustdoc_include ../listings/ch14-more-about-cargo/no-listing-04-workspace-with-tests/add/add_one/src/lib.rs}}

Suorittakaa nyt cargo test ylätason add-hakemistossa. cargo test -komennon suorittaminen tällaisessa työtilassa suorittaa testit kaikille työtilan crateille:

$ cargo test
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.20s
     Running unittests src/lib.rs (target/debug/deps/add_one-93c49ee75dc46543)

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running unittests src/main.rs (target/debug/deps/adder-3a47283c568d2b6a)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests add_one

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Tulosteen ensimmäinen osa osoittaa, että add_one-craten it_works-testi läpäisi. Seuraava osa osoittaa, että adder-cratessa ei löytynyt testejä, ja viimeinen osa osoittaa, että add_one-cratessa ei löytynyt dokumentaatiotestejä.

Voimme myös suorittaa testit yhdelle tietylle cratelle työtilassa ylätason hakemistosta käyttämällä -p-lippua ja määrittämällä craten nimen, jota haluamme testata:

$ cargo test -p add_one
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests src/lib.rs (target/debug/deps/add_one-93c49ee75dc46543)

running 1 test
test tests::it_works ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

   Doc-tests add_one

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

Tämä tuloste osoittaa, että cargo test suoritti vain add_one-craten testit eikä suorittanut adder-craten testejä.

Jos julkaisette työtilan cratet crates.io -palveluun, jokainen työtilan crate on julkaistava erikseen. Kuten cargo test, voimme julkaista tietyn craten työtilastamme käyttämällä -p-lippua ja määrittämällä craten nimen, jonka haluamme julkaista.

Lisäharjoitukseksi lisätkää tähän työtilaan add_two-crate samalla tavalla kuin add_one-crate!

Kun projektinne kasvaa, harkitkaa työtilan käyttämistä: on helpompi ymmärtää pienempiä yksittäisiä komponentteja kuin yhtä suurta koodipalaa. Lisäksi cratet työtilassa helpottavat cratejen välistä koordinointia, jos niitä muutetaan usein samaan aikaan.