Adicionar e usar uma dependência de crate

RustBeginner
Pratique Agora

Introdução

Programas reais em Rust frequentemente reutilizam bibliotecas específicas em vez de implementar cada recurso do zero. Uma biblioteca Rust publicada é chamada de crate, e um crate usado pelo seu pacote é uma dependência. Escolher e adicionar uma dependência com segurança faz parte do desenvolvimento normal em Rust.

Neste laboratório, você adicionará o analisador de linha de comando clap a um programa de saudação preparado. Você fará duas pequenas alterações no código-fonte, observará a ajuda e a validação geradas automaticamente e aprenderá as diferentes funções de Cargo.toml e Cargo.lock. A dependência já foi baixada durante a configuração para manter rápida a primeira compilação, mas adicioná-la ao projeto continua sendo sua tarefa.

Adicionar a dependência com o Cargo

Nesta etapa, você adicionará clap ao pacote preparado e verificará a alteração que o Cargo fará no manifesto.

O projeto está em /home/labex/project/hello-cli. Entre nesse diretório antes de executar comandos do Cargo:

cd /home/labex/project/hello-cli

Abra o manifesto do pacote com o nano:

nano Cargo.toml

Cargo.toml descreve o pacote e suas dependências diretas. A tabela [dependencies] vazia significa que o projeto atualmente usa apenas a biblioteca padrão do Rust. Pressione Ctrl+X para sair do nano sem alterar o arquivo.

O comando cargo add atualiza a tabela de dependências com segurança. Adicione o clap na versão 4.6.7 e habilite sua feature derive:

cargo add clap@4.6.7 --features derive

Uma feature habilita uma parte opcional de um crate. Neste caso, derive habilita as macros que transformam structs e enums do Rust em analisadores de linha de comando. O Cargo exibe as features habilitadas com + e as desabilitadas com -; features desabilitadas não são erros.

Abra o manifesto novamente:

nano Cargo.toml

A tabela de dependências agora contém uma linha semelhante a esta:

clap = { version = "4.6.7", features = ["derive"] }

A versão é um requisito de compatibilidade. O Cargo pode selecionar uma versão 4.x compatível mais recente, enquanto as versões exatas selecionadas são registradas separadamente em Cargo.lock. Pressione Ctrl+X para fechar o nano.

Derivar um analisador de linha de comando

Nesta etapa, você conectará a struct Cli ao clap usando uma macro derive e metadados do comando.

Abra o arquivo-fonte preparado:

nano src/main.rs

Você já usou #[derive(Debug)] no curso para iniciantes. Uma macro derive solicita que um crate gere a implementação de uma trait a partir da estrutura de um tipo. Substitua o primeiro comentário TODO, acima de struct Cli, por estas duas linhas:

#[derive(Parser)]
#[command(version, about = "Create a friendly greeting")]

#[derive(Parser)] gera o comportamento de análise dos argumentos. O atributo #[command(...)] fornece informações sobre o comando inteiro: version lê a versão do pacote em Cargo.toml, e about fornece uma descrição curta.

Salve com Ctrl+O, pressione Enter e saia com Ctrl+X. Verifique o programa sem executá-lo:

cargo check

A primeira verificação compila clap e seus crates de suporte, portanto pode exibir várias linhas Compiling e Checking. Uma linha final iniciada por Finished significa que a dependência e o analisador gerado foram compilados em conjunto.

Agora peça ajuda ao programa. O separador -- diferencia as opções do Cargo dos argumentos destinados ao seu programa:

cargo run --quiet -- --help

A saída inclui a descrição, um valor obrigatório <NAME> e as opções de ajuda e versão geradas automaticamente:

Create a friendly greeting

Usage: hello-cli <NAME>
...

Você definiu a estrutura dos dados; o clap gerou uma ajuda consistente e a validação dos argumentos a partir dela.

Adicionar uma flag opcional de repetição

Nesta etapa, você adicionará uma opção tipada e usará o valor analisado em um pequeno loop.

Primeiro, execute o comando com um nome posicional:

cargo run --quiet -- Ada
Hello, Ada!

name: String torna-se um valor posicional obrigatório porque não possui um atributo #[arg(...)]. Abra o código-fonte novamente:

nano src/main.rs

Substitua o segundo comentário TODO dentro de Cli por:

    /// Number of greetings to print
    #[arg(short, long, default_value_t = 1)]
    times: u8,

O comentário da documentação torna-se o texto da ajuda. short cria -t, long cria --times e default_value_t = 1 fornece um valor padrão tipado quando a opção não é informada. Como o campo é u8, o clap também rejeita valores que não sejam inteiros de 8 bits sem sinal válidos.

Substitua o comentário TODO final e a única linha println! por:

    for _ in 0..cli.times {
        println!("Hello, {}!", cli.name);
    }

O sublinhado significa que a contagem do loop não será usada de propósito. Salve e saia do nano; em seguida, execute três saudações:

cargo run --quiet -- Ada --times 3
Hello, Ada!
Hello, Ada!
Hello, Ada!

Teste também um valor inválido:

cargo run --quiet -- Ada --times many

Esse comando deve falhar. O clap exibirá um erro explicando que many não é um u8 válido e sairá com um código diferente de zero antes que main use um valor inválido.

Inspecionar e reutilizar o grafo de dependências bloqueado

Nesta etapa, você inspecionará o grafo de dependências resolvido pelo Cargo e confirmará que o arquivo de lock pode reproduzi-lo sem acesso à rede.

clap é sua dependência direta, mas ele próprio usa crates de suporte. Exiba o primeiro nível do grafo resolvido:

cargo tree --depth 1

A versão exata do patch pode ser mais recente que o requisito compatível em Cargo.toml. O formato importante é:

hello-cli v0.1.0 (...)
└── clap v4...

Abra o arquivo de lock gerado:

nano Cargo.lock

Cargo.lock contém dados gerados, portanto normalmente você não deve editá-lo manualmente. Ele registra as versões e os checksums exatos que o Cargo selecionou para todo o grafo. Em uma aplicação como esta CLI, mantenha o arquivo de lock junto com o projeto para que os colegas e as compilações automatizadas possam reutilizar a mesma resolução. Pressione Ctrl+X para fechar o nano.

Agora exija o lock existente e o cache local de crates:

cargo check --locked --offline

--locked recusa alterações em Cargo.lock. --offline impede o acesso à rede. Uma linha final Finished confirma que o projeto pode ser verificado usando o grafo de dependências já baixado, sem resolver silenciosamente versões diferentes.

Resumo

Você adicionou uma dependência direta de crate com o Cargo, habilitou uma feature opcional, derivou um analisador clap tipado e observou a ajuda e a validação automáticas. Você também distinguiu o requisito compatível em Cargo.toml do grafo exato de dependências em Cargo.lock e confirmou que o grafo bloqueado funciona offline.