Find potential unused enabled feature flags and prune them.

Overview

Donate Latest Version MIT docs

Potential unused, enabled feature flag finder and pruner.

This cargo tool allows you to find and prune enabled, but, potentially unused feature flags from your project.

Use unused-features --help to fetch more details about available subcommands and their configurations.

1. How to use

Run cargo install cargo-unused-features or download the library and build it yourself.

  1. Step Analyzing enabled unused features.

You can control the compilation by supplying --bin, --lib, --examples, --benches, --tests flags. By default, libraries and binaries are compiled. If you want tests, examples, benches, be compiled in the analysis, make sure to supply the corresponding tags.

cd C:/some_path/
unused-features analyze

After it finished running, check the report.json in the project directory and use this for the next two steps.

  1. Generating a HTML report. (optional)

You can generate a simple HTML report from the json to make it easier to inspect results.

unused-features build-report --input "C:/some_path/report.json"

After it finished running, check the report.html in the project directory. You can choose to manually fix your dependencies or use the command in the next step.

  1. Applying suggested removals of feature flags.

It is possible to auto-apply the findings of the first command. But keep in mind the disclaimers.

unused-features prune --input "C:/some_path/report.json"

2. How it Works

This library works for both workspaces and individual crates. In the context of a workspace it will just iterate each crate in the workspace-definition and run the same process it does for a single crate.

For a single crate it removes a feature of a dependency and then compiles the project to see if it still compiles. If it does, the feature flag can possibly be removed, but it can be a false-positve (disclaimers.). Yes, recompiling for every feature-flag implies some overhead. However, this is a one-time thing and if you have a large project, just let it run for a while. I personally have ran it on a project with over 50 crates and it finished within an hour. The compiler will not perform a complete clean rebuild which is in our favor.

Furthermore, This library uses cargo_toml to remove or add features. It loads a TOML file into memory, modifies the dependency features, serializes the Manifest, and writes it back to the toml-file. Then it starts compiling, and after it finishes running, the original content is written back as if nothing had happened.

But before doing all of that, we need to know which features to remove in the first case. This library uses cargo-metadata to collect all enabled features from the dependencies. Features can be enabled in several ways. Manually by features = ['x', 'y'] tag, or by the default-features=false/true tag. Also, features can enable 0-n other features e.g default=[x,y]. So, this library collects all enabled features, whether they are implicitly or explicitly enabled. After it collects all enabled features for a dependency, it will remove them one-by-one and compile the project as described above.

During the process, a json report is updated for each crate to ensure that if it crashes the progress is not lost. Use the cargo unused-features build-report command to visualize this report.

Finally, this library also has the option to apply all suggestions automatically by running cargo unused-features prune command. For this task, toml-edit is used because it doesn't mess with formatting, comments, and spaces, in the TOML-file.

3. Some things to keep in mind

  • Sometimes feature flags can turn logic on and off without breaking the compilation and therefore this tool can mark a feature flag as removable, but essentially it would change the internal logic of a library. For this reason, this library offers 3 phases. Analyze, automatically apply suggestions, and generate a report. If you want to be more carefully inspect the HTML report to see more clearly what suggestions are given and manually update the dependencies yourself.
  • Given crate A and B, B depends on A and uses logic from a dependency of A that is hidden behind a feature flag enabled in A, but A itself does not use this code. In this scenario, the feature flag can be removed for A but not for B. So this can result in a false positive. I would recommend going through the suggestions on a crate by crate basis, or just running it on the full workspace, and fixing the compilation errors by adding the removed features.
  • Feature flags may only be used for a certain target-os. This project does not compile for each target, but instead, you can specify the target with --target x to the cargo unused-features command.

4. Report Bug

This tool is very new, and one can expect problems. If you have problems, please do the following:

  1. Open an issue with the problematic Cargo.toml file.
  2. Provide the --log debug flag to the cargo-unused-features command and post the logs in the issue as well.

Future

Would be nice to find ways to be more certain about when a feature can be removed. Potentially we would need to do some regex matches with features in the dependency code base and see how the feature is used. And with that get a more precise assumption. If you have an idea, feel free to open an issue or reach out to me!

Comments
  • Supporting workspace versioning

    Supporting workspace versioning

    Describe the bug Does this crate support workspace versioning? I'm getting an error when attempting to run it on prql-compiler. Here's the issue template:

    • The Cargo.toml file of your project https://github.com/prql/prql/blob/ca2e79f4b27787f5ec5b3fa2edd92790684421cf/Cargo.toml
    • The debug level logs (e.g cargo analyze --log-level debug) — I get error: no such subcommand: analyze, but with unused-features:
    ❯ unused-features analyze --log-level debug
    [2022-12-09T00:21:11Z INFO  unused_features::subcommands::analyze] /Users/maximilian/workspace/prql/prql-compiler
    [2022-12-09T00:21:11Z DEBUG unused_features::cargo_project] Loading '/Users/maximilian/workspace/prql/prql-compiler/Cargo.toml' ...
    [2022-12-09T00:21:11Z DEBUG unused_features::cargo_project] Successfully read the toml file.
    [2022-12-09T00:21:11Z DEBUG unused_features::cargo_project] Parsing toml definition ...
    [2022-12-09T00:21:11Z ERROR unused_features::subcommands::analyze] Failed to load '/Users/maximilian/workspace/prql/prql-compiler/Cargo.toml' crate. invalid type: map, expected a string for key `package.version` at line 8 column 21
    [2022-12-09T00:21:11Z INFO  unused_features] Finished the process
    
    • The target-os and architecture used for building — MacOS, arm64
    • Any optional specified CLI configuration flags.

    Thank you!

    opened by max-sixty 3
  • WIP: Support workspace inheritance

    WIP: Support workspace inheritance

    Closes https://github.com/TimonPost/cargo-unused-features/issues/7

    only did enough to get it working - the new stubbed blocks may need to be implemented yet.

    Tests are also a problem. c.f. https://github.com/TimonPost/cargo-unused-features/issues/9

    opened by jayvdb 2
  • Failing to prune from `report.json`

    Failing to prune from `report.json`

    Describe the bug Unable to prune from report.json

    ❯ unused-features prune --input report.json
    A
    B
    [2022-10-28T09:30:29Z INFO  unused_features::subcommands::prune] Executing prune command.
    [2022-10-28T09:30:29Z INFO  unused_features::report] Loading report from report.json.
    [2022-10-28T09:30:29Z ERROR unused_features] Failed to deserialize report from report.json, maybe an old report? Current version is 0, make sure this is the same one in the report.
    

    Only change I have made to the report.json file is removing from reqwest's successfully_remove_features the features rustls-tls and rustls-tls-webpki-roots

    Provide the following information Cargo.toml

    [dependencies]
    clap = { version = "4.0.15", features = ["derive"] }
    regex = "1.5"
    serde = { version = "1.0", features = ["derive"] }
    serde_json = "1.0"
    reqwest = { version = "0.11", default-features = false, features = ["stream", "rustls-tls"] }
    tokio = { version = "1.16.1", features = ["full"] }
    anyhow = "1.0.52"
    indicatif = "0.16.2"
    futures-util = "0.3.14"
    dirs = "4.0.0"
    cfg-if = "1.0"
    tracing = "0.1"
    tracing-subscriber = "0.2"
    yansi = "0.5.1"
    
    • The debug level logs: the default ones, didnt specify anything
    • The target-os and architecture used for building: Arch linux x86
    opened by MordechaiHadad 2
  • invalid type: map, expected a string for key `package.version`

    invalid type: map, expected a string for key `package.version`

    I'm using this code in Cargo.toml:

    [package]
    name = "app"
    version.workspace = true
    edition.workspace = true
    publish.workspace = true
    

    but when I run unused-features analyze it errors with:

    A
    B
    [2022-12-16T17:08:45Z INFO  unused_features::subcommands::analyze] C:\projects\app
    [2022-12-16T17:08:45Z ERROR unused_features::subcommands::analyze] Failed to load 'C:\projects\app/bin/app' crate. invalid type: map, expected a string for key `package.version` at line 3 column 21
    

    Windows 10, rustc 1.65.0 (897e37553 2022-11-02), cargo 1.65.0 (4bc8f24d3 2022-10-20)

    opened by frederikhors 2
  • Empty reports with rust-toolchain.toml

    Empty reports with rust-toolchain.toml

    Describe the bug unused-features analyze on https://github.com/helix-editor/helix/ gives near-empty results in report.json.

    {
      "version": 0,
      "root_name": "Workspace",
      "workspace_crates": {}
    }
    

    Removing rust-toolchain.toml gets it to work again.

    opened by g2p 0
  • Running on binary project gives wrong results [fixed]

    Running on binary project gives wrong results [fixed]

    From reddit.

    Probably not a minimal example, but this fails for me:

    cargo new bug
    cd ./bug/
    cargo add async-std
    echo "fn main() { let _ = async_std::task::yield_now(); }" > ./src/main.rs
    unused-features analyze
    unused-features prune --input .\report.json
    cargo check
    
    opened by TimonPost 4
Owner
Timon
Hakuna Matata!
Timon
fas stand for Find all stuff and it's a go app that simplify the find command and allow you to easily search everything you nedd

fas fas stands for Find all stuff and it's a rust app that simplify the find command and allow you to easily search everything you need. Note: current

M4jrT0m 1 Dec 24, 2021
fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find

fd is a program to find entries in your filesystem. It is a simple, fast and user-friendly alternative to find. While it does not aim to support all of find's powerful functionality, it provides sensible (opinionated) defaults for a majority of use cases.

David Peter 25.9k Jan 9, 2023
Pulls the C/C++ library linking flags from Conan dependencies

conan2-rs Introduction conan2-rs is a Cargo build script wrapper of the Conan C/C++ package manager (version 2.0 only). It automatically pulls the C/C

Sergey Kvachonok 5 Oct 17, 2023
Save cli commands and fuzzy find them later

crow - cli command memorizer What is crow? | Installation | Usage | FAQ What is crow? crow (command row) is a CLI tool to help you memorize CLI comman

sandstorm 7 Feb 17, 2022
Help Skelly to find bones, combine them to build his body back

Bones Collector Help Skelly to find bones, combine them to build his body back! Game made for the bevy Jam#2. Play it here in your browser: itch.io! R

Thomas 2 Nov 15, 2022
A lightweight but incredibly powerful and feature-rich BitTorrent tracker. Supports UDP + HTTP(S) and a private tracker mode.

Torrust Tracker Project Description Torrust Tracker is a lightweight but incredibly powerful and feature-rich BitTorrent tracker made using Rust. Feat

Torrust 162 Dec 31, 2022
A library that creates a terminal-like window with feature-packed drawing of text and easy input handling. MIRROR.

BearLibTerminal provides a pseudoterminal window with a grid of character cells and a simple yet powerful API for flexible textual output and uncompli

Tommy Ettinger 43 Oct 31, 2022
🖥 A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/S3

?? A feature rich terminal UI file transfer and explorer with support for SCP/SFTP/FTP/S3

Christian Visintin 574 Jan 5, 2023
Firefox used to have this feature a while back (from Firefox 11 to 46) and it is so good, that I feel it needs revival.

3D WebPage Inspector By: Seanpm2001, Et; Al. Top README.md Read this article in a different language Sorted by: A-Z Sorting options unavailable ( af A

Sean P. Myrick V19.1.7.2 3 Nov 10, 2022
An abstract, safe, and concise color conversion library for rust nightly This requires the feature adt_const_params

colortypes A type safe color conversion library This crate provides many methods for converting between color types. Everything is implemented abstrac

Jacob 13 Dec 7, 2022
A beautiful and feature-packed Apple Music CLI

am A beautiful and feature-packed Apple Music CLI! Written in Rust. Installation Nix (recommended) This GitHub repository contains a flake. Add github

Ryan Cao 5 Sep 21, 2023
An feature packed Google Tasks CLI written purely in Rust

rChore A feature packed unofficial Google Tasks CLI to boost your producitvity, written purely in Rust. ?? What is rChore? rChore is an unofficial Goo

Hemanth Krishna 41 Dec 24, 2022
Native cross-platform full feature terminal-based sequence editor for git interactive rebase.

Native cross-platform full feature terminal-based sequence editor for git interactive rebase.

Tim Oram 1.2k Jan 2, 2023
Terminal based, feature rich, interactive SQL tool

datafusion-tui (dft) DataFusion-tui provides a feature rich terminal application, built with tui-rs, for using DataFusion (and eventually Ballista). I

null 49 Dec 24, 2022
Fast, minimal, feature-rich, extended formatting syntax for Rust!

Formatting Tools Fast, minimal, feature-rich, extended formatting syntax for Rust! Features include: Arbitrary expressions inside the formatting brace

Casper 58 Dec 26, 2022
Use asynchronous api requests in conjunction with yew's suspense feature

Yew API Hook Use asynchronous api requests in conjunction with yew's suspense feature Usage #[function_component] fn App() -> Html { html! {

Mara Schulke 3 Jan 15, 2023
Captures packets and streams them to other devices. Built for home network analysis and A&D CTFs.

?? shiny-donut shiny-donut is a packet capture app that supports streaming packets from a remote system to another device. The main use for this is to

Justin Perez 3 Nov 30, 2022
Uses the cardano mini-protocols to receive every block and transaction, and save them to a configurable destination

cardano-slurp Connects to one or more cardano-node's, streams all available transactions, and saves them to disk (or to S3) in raw cbor format. Usage

Pi Lanningham 16 Jan 31, 2023
A visual canvas and virtual machine for writing assembly to build cool things. Create machines and connect them together.

Visual Assembly Canvas A highly visual assembly editor, infinite canvas for wiring blocks and machines together, bytecode virtual machine runnable nat

Phoomparin Mano 31 Oct 11, 2023