Use cargo add e cargo remove para alterar dependências sem editar cada linha do Cargo.toml à mão; use cargo upgrade quando quiser mudar os requisitos de versão declarados e cargo set-version para atualizar a versão de um pacote ou workspace. Em versões modernas do Rust, cargo add e cargo remove já podem fazer parte do próprio Cargo. O projeto cargo-edit continua relevante por oferecer comandos adicionais e por ter popularizado esse fluxo.
O começo mais comum é:
cargo add serde --features derive
cargo add tokio --features macros,rt-multi-thread
cargo add pretty_assertions --dev
cargo remove pretty_assertions
Depois de qualquer comando, revise dois arquivos: o Cargo.toml, que expressa a política de versões do projeto, e o Cargo.lock, que registra a resolução concreta usada no build. A conveniência da CLI não elimina revisão, testes nem decisões sobre SemVer.
Resposta rápida: qual comando usar
| Objetivo | Comando típico | O que muda |
|---|---|---|
| Adicionar uma crate | cargo add serde | Cargo.toml e normalmente Cargo.lock |
| Habilitar features | cargo add serde --features derive | requisito e lista de features |
| Adicionar dependência de teste | cargo add proptest --dev | seção dev-dependencies |
| Remover uma crate | cargo remove serde | manifesto e resolução do lockfile |
| Atualizar somente o lockfile | cargo update | Cargo.lock, respeitando o manifesto |
| Ampliar requisitos declarados | cargo upgrade | versões no Cargo.toml e resolução |
| Mudar a versão do pacote | cargo set-version 1.4.0 | campo package.version |
| Operar em um membro do workspace | opção --package ou execução no diretório do membro | manifesto selecionado |
Os nomes e opções disponíveis dependem da versão do Cargo e do cargo-edit. Antes de automatizar, confira:
cargo --version
cargo add --help
cargo remove --help
cargo upgrade --help
cargo set-version --help
Se cargo upgrade ou cargo set-version não existir, instale uma versão homologada do cargo-edit e repita a verificação.
Cargo já inclui cargo add e cargo remove?
Sim, em toolchains atuais o cargo add é um comando oficial do Cargo, e o gerenciamento básico também inclui remoção de dependências. Isso gera uma dúvida comum: ainda faz sentido instalar cargo-edit?
A resposta depende do trabalho:
- para apenas adicionar e remover crates, o Cargo da toolchain pode ser suficiente;
- para atualizar requisitos de versões em lote,
cargo upgradecontinua sendo o principal motivo para usarcargo-edit; - para alterar versões de pacotes por comando,
cargo set-versionpode simplificar releases e scripts; - em máquinas antigas, a disponibilidade dos comandos pode variar;
- em CI, a equipe deve fixar toolchain e versão da ferramenta em vez de depender do ambiente do runner.
Não instale uma ferramenta só porque um tutorial antigo mandou. Rode cargo add --help primeiro. Se o comando já existe e cobre o caso, use o que acompanha sua toolchain.
Instalando cargo-edit
Quando você precisa dos subcomandos adicionais:
cargo install cargo-edit --locked
cargo upgrade --help
cargo set-version --help
O --locked pede que a instalação respeite o lockfile publicado pela ferramenta. Para uma estação pessoal isso já melhora previsibilidade. Em CI ou imagens de desenvolvimento, fixe também a versão aprovada:
cargo install cargo-edit --locked --version X.Y.Z
Substitua X.Y.Z pela versão testada pelo time. Não copie um número arbitrário de outro projeto: confirme compatibilidade com a toolchain usada no repositório.
Se a instalação por compilação deixa a pipeline lenta, avalie um instalador de binários apenas quando o projeto oferecer artefatos verificáveis e uma origem confiável. Para uma visão mais ampla das opções disponíveis, consulte as ferramentas essenciais do Cargo.
Como usar cargo add
O comando básico adiciona uma dependência normal:
cargo add anyhow
Um manifesto pode passar a conter:
[dependencies]
anyhow = "1"
A forma exata gravada depende do comando, da versão da ferramenta e das informações disponíveis no registry. O número no manifesto é um requisito SemVer, não necessariamente a versão exata que aparecerá no lockfile.
Adicionar uma versão específica
Quando o projeto precisa de uma linha de versão determinada:
cargo add [email protected]
Não fixe uma versão antiga sem motivo. Por outro lado, também não troque automaticamente para uma nova major sem ler o changelog e o guia de migração. O artigo sobre cargo-semver-checks mostra como autores de bibliotecas podem detectar várias quebras de API; consumidores ainda precisam validar comportamento e integração.
Habilitar features
Muitas crates usam features para selecionar integrações, runtimes ou implementações:
cargo add serde --features derive
cargo add tokio --features macros,rt-multi-thread,signal
cargo add reqwest --no-default-features --features json,rustls-tls
O resultado esperado é semelhante a:
[dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread", "signal"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
Features merecem revisão cuidadosa. default-features = false pode reduzir dependências ou trocar a implementação TLS, mas também pode remover comportamento que o código esperava. Em bibliotecas, features aditivas e independentes tendem a ser mais fáceis de manter. Use cargo-hack quando o contrato exige testar várias combinações.
Dependências de desenvolvimento
Para testes, benchmarks e ferramentas usadas somente no desenvolvimento:
cargo add pretty_assertions --dev
cargo add criterion --dev
cargo add proptest --dev
Elas entram em [dev-dependencies]. Isso evita colocar bibliotecas de teste na árvore normal de quem consome sua crate.
Build dependencies
Crates usadas por build.rs devem ficar na seção própria:
cargo add cc --build
O manifesto recebe uma entrada em [build-dependencies]. Antes de adicionar uma build dependency, avalie o impacto: scripts de build executam durante a compilação, podem exigir ferramentas do sistema e afetam portabilidade, cache e supply chain.
Dependências opcionais
Uma dependência opcional pode ser associada a uma feature:
cargo add tracing-subscriber --optional
Revise o manifesto gerado e dê um nome de feature compreensível quando a API pública precisar expor essa escolha. Para bibliotecas, documente quais APIs ficam disponíveis e quais requisitos de plataforma aparecem quando a feature é ligada.
Dependências Git ou locais
Durante desenvolvimento, você pode apontar para um repositório ou caminho:
cargo add minha-lib --git https://example.invalid/org/minha-lib.git
cargo add minha-lib --path ../minha-lib
Os endereços são ilustrativos. Dependências Git devem preferir uma referência imutável quando reprodutibilidade for importante. Dependências por path funcionam bem em workspaces e desenvolvimento local, mas uma crate publicável normalmente também precisa de requisito version coerente para resolver a dependência fora do monorepo.
Como remover uma dependência
Quando uma crate não é mais usada:
cargo remove anyhow
Em instalações que oferecem o alias correspondente, cargo rm pode funcionar, mas prefira o comando documentado pela sua versão e confirme com --help.
Remover a linha do manifesto não prova que todo vestígio desapareceu. Procure:
rg 'anyhow' src tests benches examples
cargo check --all-targets
cargo test --locked
Em workspaces, confirme se você removeu a dependência do pacote correto. Ela pode continuar presente por meio de outro membro ou como dependência transitiva. Use cargo tree para inspecionar por que uma crate ainda aparece:
cargo tree -i anyhow
Se o objetivo é descobrir dependências declaradas, porém não utilizadas, veja o guia de cargo-machete e cargo-udeps.
cargo update e cargo upgrade não fazem a mesma coisa
Essa é a distinção mais importante do guia.
Considere:
[dependencies]
minha-crate = "1.2"
O requisito aceita versões compatíveis dentro da linha permitida pelo Cargo. O Cargo.lock pode ter resolvido 1.2.3.
cargo update
cargo update -p minha-crate
O comando procura uma resolução mais nova sem sair do requisito escrito no manifesto. Se existir 1.9.0 compatível, o lockfile pode avançar. Se a nova versão for 2.0.0, o requisito atual normalmente impede a mudança.
Use cargo update quando a política declarada continua correta e você quer renovar a resolução concreta.
cargo upgrade
cargo upgrade -p minha-crate
cargo upgrade pode alterar o requisito do Cargo.toml. É a escolha quando o projeto quer adotar uma linha mais nova — inclusive uma major, se a opção e a política usadas permitirem.
Esse diff exige revisão maior porque pode envolver:
- APIs removidas ou renomeadas;
- mudança da versão mínima de Rust, a MSRV;
- novas features default;
- troca de backend TLS;
- dependências nativas adicionais;
- comportamento diferente em runtime;
- novo formato de configuração ou dados.
A regra operacional é simples: cargo update renova a resolução; cargo upgrade muda a política declarada.
Atualizando com segurança
Não execute upgrades em massa e trate um build verde como prova suficiente. Use lotes pequenos e uma sequência observável.
1. Registre a baseline
cargo test --workspace --locked
cargo clippy --workspace --all-targets --all-features -- -D warnings
Se --all-features não representa uma combinação válida, use a matriz real do projeto.
2. Atualize um grupo coerente
Por exemplo, runtime e utilitários Tokio podem precisar avançar juntos. Evite misturar atualização de banco, framework web, serialização e observabilidade na mesma pull request sem necessidade.
3. Revise o diff
git diff -- Cargo.toml Cargo.lock
No lockfile, procure crates novas, remoções, duplicação de versões, dependências nativas e mudanças de fonte. O tamanho do diff não é sinal automático de risco, mas ajuda a escolher testes adicionais.
4. Inspecione a árvore
cargo tree --duplicates
cargo tree -e features
Duplicatas podem ser legítimas durante migrações do ecossistema. Ainda assim, versões paralelas de crates grandes aumentam build, binário e superfície de auditoria.
5. Rode verificações de segurança e licenças
cargo audit
cargo deny check
cargo-audit verifica advisories conhecidos. Já o guia de cargo-deny e SBOM cobre políticas de licenças, fontes, bans e duplicatas.
6. Teste o comportamento real
Para uma API, execute testes de integração e smoke tests. Para uma CLI, rode comandos com fixtures. Para embedded, compile os targets suportados e teste no hardware quando a atualização alcança HALs, drivers ou runtime.
cargo upgrade em workspaces
Workspaces exigem atenção porque uma dependência pode ser declarada em vários lugares:
workspace/
├── Cargo.toml
└── crates/
├── api/Cargo.toml
├── core/Cargo.toml
└── cli/Cargo.toml
Com dependências herdadas:
[workspace.dependencies]
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["macros"] }
E no membro:
[dependencies]
serde.workspace = true
tokio = { workspace = true, features = ["rt-multi-thread"] }
A fonte de verdade está no manifesto raiz para a versão, enquanto o membro pode acrescentar features. Antes de usar comandos em lote, confirme se a versão instalada entende a estrutura de herança adotada.
Uma estratégia segura:
- rode o comando com seleção explícita de pacote ou workspace;
- revise todos os manifestos alterados;
- verifique se features específicas dos membros foram preservadas;
- execute testes do workspace inteiro;
- compile exemplos, benches e targets que não entram no teste padrão.
O guia de Cargo Workspaces explica a organização de membros, dependências compartilhadas e perfis.
Usando cargo set-version
cargo set-version ajuda a atualizar o campo version sem procurar e editar manifestos manualmente:
cargo set-version 1.4.0
Em um workspace, use as opções de seleção disponíveis na versão instalada para alterar o pacote correto ou aplicar a política planejada. Sempre confira:
git diff -- '**/Cargo.toml' Cargo.lock
Mudar o número não constitui um release completo. Ainda faltam changelog, testes, tag, publicação, artefatos e validação. Para automatizar a preparação revisável de versões e changelogs, veja release-plz. Para binários multiplataforma, cargo-dist resolve outra parte do processo.
Automação na CI: proponha, não integre às cegas
Uma pipeline de atualização pode executar periodicamente:
- checkout da branch principal;
- instalação da toolchain e do
cargo-editfixados; cargo upgradecom a política escolhida;- formatação, Clippy e testes;
- auditoria de advisories e licenças;
- criação de uma pull request com o diff.
Evite um job que atualiza dependências e faz push direto para main. Uma dependência pode passar nos testes existentes e mudar comportamento não coberto. A pull request cria um ponto para ler changelogs, observar o lockfile e pedir validações específicas.
Um script conceitual pode ser:
set -euo pipefail
cargo install cargo-edit --locked --version X.Y.Z
cargo upgrade
cargo check --workspace --all-targets
cargo test --workspace --locked
cargo clippy --workspace --all-targets -- -D warnings
cargo audit
git diff --check
git diff -- Cargo.toml Cargo.lock
O exemplo não abre a pull request nem define a política de majors. Adapte ao provedor e nunca disponibilize secrets de escrita para código de pull requests não confiáveis.
Erros frequentes
Confundir requisito com versão resolvida
O Cargo.toml define o intervalo aceito; o Cargo.lock registra a seleção concreta. Leia os dois.
Executar cargo upgrade e commitar sem changelog
Uma nova major pode compilar e ainda alterar comportamento. Leia notas de release e migração.
Habilitar todas as features por conveniência
Features extras aumentam compilação, dependências e superfície de ataque. Ative somente o contrato necessário.
Desabilitar default features sem teste
Isso pode remover TLS, runtime ou integração esperada. Verifique o produto final.
Atualizar o workspace parcialmente
Dependências compartilhadas e features herdadas podem gerar uma combinação inconsistente. Rode checks no workspace inteiro.
Ignorar MSRV
Uma atualização pode exigir Rust mais novo. Se sua biblioteca promete uma MSRV, teste-a explicitamente com cargo-msrv e na matriz da CI.
Instalar cargo-edit sem versão na pipeline
Uma release nova da ferramenta pode mudar o diff gerado. Fixe e atualize conscientemente.
Checklist para alterações de dependências
- Confirmei se o comando já existe no Cargo da toolchain.
- Fixei a versão de
cargo-editna automação. - Usei a seção correta: normal, dev ou build dependency.
- Habilitei somente as features necessárias.
- Revisei
Cargo.tomleCargo.lock. - Entendi se a mudança usa
cargo updateoucargo upgrade. - Li changelogs para majors e dependências críticas.
- Verifiquei MSRV, targets e dependências nativas.
- Rodei testes, Clippy e smoke tests relevantes.
- Inspecionei duplicatas e features com
cargo tree. - Rodei as políticas de segurança e licenças.
- Em workspace, validei todos os membros afetados.
- A atualização será revisada em pull request.
Perguntas frequentes
Para que serve o cargo-edit?
cargo-edit reúne subcomandos para editar dependências e versões nos manifestos. Em toolchains modernas, operações básicas como cargo add e cargo remove podem vir no Cargo; comandos como cargo upgrade e cargo set-version continuam sendo usos importantes da ferramenta adicional.
Como adicionar uma dependência com cargo add?
Execute:
cargo add nome-da-crate
Acrescente --features, --dev, --build ou a seleção de pacote conforme o caso. Revise o manifesto e o lockfile resultantes.
Qual é a diferença entre cargo update e cargo upgrade?
cargo update escolhe versões novas permitidas pelos requisitos atuais e altera principalmente o lockfile. cargo upgrade muda os requisitos no manifesto, podendo adotar outra linha de versão.
cargo add substitui a edição manual?
Não. Ele reduz erros e torna operações comuns rápidas, mas tabelas complexas e políticas específicas ainda podem ser mais claras com edição manual. O diff final é o que importa.
Posso executar cargo upgrade automaticamente na CI?
Sim, para gerar uma proposta e validá-la. Prefira abrir uma pull request em vez de integrar sem revisão. Testes não cobrem toda mudança de comportamento, MSRV, feature ou dependência nativa.
Conclusão
cargo-edit e os comandos modernos do Cargo tornam o gerenciamento de dependências Rust mais explícito e menos sujeito a erros de sintaxe. O fluxo recomendado é simples: use cargo add para declarar a intenção, cargo remove para limpar o manifesto, cargo update para renovar o lockfile dentro da política atual e cargo upgrade quando a própria política de versões precisa mudar.
A parte importante começa depois do comando. Revise features, requisitos SemVer, lockfile, MSRV, dependências nativas e impacto no workspace. Em projetos profissionais, uma atualização de dependência é uma mudança de código: merece testes, auditoria e pull request.
Para praticar esse fluxo em um projeto completo, siga a trilha de aprendizado de Rust, explore o curso de Rust e aplique os comandos em um workspace descartável antes de automatizar o repositório principal.