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.


