cargo-edit em Rust: add, remove e upgrade | Rust Brasil

Gerencie dependências Rust com cargo add, remove, upgrade e set-version. Guia de cargo-edit para features, versões, workspaces, CI e revisão segura.

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

ObjetivoComando típicoO que muda
Adicionar uma cratecargo add serdeCargo.toml e normalmente Cargo.lock
Habilitar featurescargo add serde --features deriverequisito e lista de features
Adicionar dependência de testecargo add proptest --devseção dev-dependencies
Remover uma cratecargo remove serdemanifesto e resolução do lockfile
Atualizar somente o lockfilecargo updateCargo.lock, respeitando o manifesto
Ampliar requisitos declaradoscargo upgradeversões no Cargo.toml e resolução
Mudar a versão do pacotecargo set-version 1.4.0campo package.version
Operar em um membro do workspaceopção --package ou execução no diretório do membromanifesto 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 upgrade continua sendo o principal motivo para usar cargo-edit;
  • para alterar versões de pacotes por comando, cargo set-version pode 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:

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:

  1. rode o comando com seleção explícita de pacote ou workspace;
  2. revise todos os manifestos alterados;
  3. verifique se features específicas dos membros foram preservadas;
  4. execute testes do workspace inteiro;
  5. 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:

  1. checkout da branch principal;
  2. instalação da toolchain e do cargo-edit fixados;
  3. cargo upgrade com a política escolhida;
  4. formatação, Clippy e testes;
  5. auditoria de advisories e licenças;
  6. 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-edit na automação.
  • Usei a seção correta: normal, dev ou build dependency.
  • Habilitei somente as features necessárias.
  • Revisei Cargo.toml e Cargo.lock.
  • Entendi se a mudança usa cargo update ou cargo 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.