├── .github └── workflows │ ├── audit-check.yml │ └── ci.yml ├── Cargo.toml ├── README.md ├── LICENSE ├── src └── main.rs └── Cargo.lock /.github/workflows/audit-check.yml: -------------------------------------------------------------------------------- 1 | name: Security audit 2 | on: 3 | schedule: 4 | - cron: '0 0 * * *' 5 | jobs: 6 | audit: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v1 10 | - uses: actions-rs/audit-check@v1 11 | with: 12 | token: ${{ secrets.GITHUB_TOKEN }} 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cargo-strip" 3 | version = "0.2.3" 4 | authors = ["Guillaume Valadon "] 5 | license = "MIT" 6 | readme = "README.md" 7 | repository = "https://github.com/guedou/cargo-strip/" 8 | description = "Strip Rust binaries created with cargo" 9 | edition = "2018" 10 | 11 | [dependencies] 12 | cargo_metadata = "0.10.0" 13 | clap = "2.33.1" 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cargo-strip 2 | 3 | [![crates.io badge](https://img.shields.io/crates/v/cargo-strip.svg)](https://crates.io/crates/cargo-strip) 4 | ![CI](https://github.com/guedou/cargo-strip/workflows/CI/badge.svg) 5 | [![Twitter Follow](https://img.shields.io/twitter/follow/guedou.svg?style=social)](https://twitter.com/intent/follow?screen_name=guedou) 6 | 7 | As of Rust 1.59, the `cargo` command is now able to [strip a binary](https://doc.rust-lang.org/beta/cargo/reference/profiles.html#strip). This can be enabled in your `Cargo.toml` in the following way: 8 | ``` 9 | [package] 10 | # ... 11 | 12 | [profile.release] 13 | strip="debuginfo" 14 | ``` 15 | 16 | --- 17 | 18 | A cargo subcommand that reduces the size of Rust binaries using the `strip` command. 19 | 20 | ## Installation & Usage 21 | 22 | Run the following command: 23 | ``` 24 | cargo install --force cargo-strip 25 | ``` 26 | 27 | Simply strip your binary with: 28 | ``` 29 | cargo strip 30 | ``` 31 | 32 | When cross-compiling, the `--target` could be used to strip the binary, such as: 33 | ``` 34 | cargo strip --target armv7-unknown-linux-gnueabihf 35 | ``` 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Guillaume Valadon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: push 2 | 3 | name: CI 4 | 5 | jobs: 6 | build_native: 7 | name: Build & run 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout the repository 11 | uses: actions/checkout@v2 12 | - name: Build & run cargo-strip 13 | uses: actions-rs/cargo@v1 14 | with: 15 | command: run 16 | build_arm: 17 | name: Build & run on ARM 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout the repository 21 | uses: actions/checkout@v2 22 | - name: Configure the ARM toolchain 23 | uses: actions-rs/toolchain@v1 24 | with: 25 | toolchain: stable 26 | target: armv7-unknown-linux-gnueabihf 27 | override: true 28 | - name: Build cargo-strip for ARM 29 | uses: actions-rs/cargo@v1 30 | with: 31 | use-cross: true 32 | command: build 33 | args: --target armv7-unknown-linux-gnueabihf 34 | - name: Build & run cargo-strip on the ARM binary 35 | uses: actions-rs/cargo@v1 36 | with: 37 | command: run 38 | args: -- strip --target armv7-unknown-linux-gnueabihf 39 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2020 Guillaume Valadon 2 | 3 | use std::fs; 4 | use std::fs::File; 5 | use std::io::ErrorKind; 6 | use std::path::PathBuf; 7 | use std::process::{Command, Stdio}; 8 | 9 | use cargo_metadata::MetadataCommand; 10 | use clap::{crate_version, App, Arg, SubCommand}; 11 | 12 | fn strip_binary(filepath: &mut PathBuf) -> Result<(), String> { 13 | // Retrieve files metadata 14 | filepath.set_extension("cargo-strip_info"); 15 | let strip_info_metadata = fs::metadata(filepath.as_path()); 16 | filepath.set_extension(""); 17 | 18 | let binary_metadata = fs::metadata(filepath.as_path()); 19 | 20 | // Determine if the binary needs to be stripped 21 | let strip_needed = match (binary_metadata, strip_info_metadata) { 22 | (Ok(_), Err(s)) if s.kind() == ErrorKind::NotFound => true, 23 | (Err(_), Err(_)) => false, 24 | (Ok(b), Ok(s)) => { 25 | let s_modified = s 26 | .modified() 27 | .or_else(|_| Err("Modification time unavailable!"))?; 28 | let b_modified = b 29 | .modified() 30 | .or_else(|_| Err("Modification time unavailable!"))?; 31 | s_modified <= b_modified 32 | } 33 | (_, _) => false, 34 | }; 35 | 36 | if !strip_needed { 37 | return Ok(()); 38 | } 39 | 40 | let filesize_before = fs::metadata(&filepath) 41 | .or_else(|_| Err("Cannot get file size!"))? 42 | .len(); 43 | 44 | // Strip the binary 45 | Command::new("strip") 46 | .arg(&filepath) 47 | .stdout(Stdio::null()) 48 | .stderr(Stdio::null()) 49 | .status() 50 | .or_else(|_| Err("Cannot execute strip!"))?; 51 | 52 | let filesize_after = fs::metadata(&filepath) 53 | .or_else(|_| Err("Cannot get file size!"))? 54 | .len(); 55 | 56 | println!( 57 | "{:?} stripped (reduced by {} kB)!", 58 | filepath, 59 | (filesize_before - filesize_after) / 1024 60 | ); 61 | 62 | // Create the .cargo-strip_info file 63 | filepath.set_extension("cargo-strip_info"); 64 | File::create(&filepath).or_else(|_| Err("Cannot create the .cargo-strip_info file!"))?; 65 | filepath.set_extension(""); 66 | 67 | Ok(()) 68 | } 69 | 70 | fn main() -> Result<(), String> { 71 | // Parse command line arguments 72 | let matches = App::new("cargo-strip - reduces the size of binaries using the `strip` command") 73 | .version(&crate_version!()[..]) 74 | // cargo subcommand trick from https://github.com/clap-rs/clap/issues/937 75 | .bin_name("cargo") 76 | .subcommand( 77 | SubCommand::with_name("strip").arg( 78 | Arg::with_name("target") 79 | .short("t") 80 | .long("target") 81 | .takes_value(true) 82 | .help("name of the target to strip"), 83 | ), 84 | ) 85 | .get_matches(); 86 | 87 | // Check if the strip binary is available 88 | Command::new("strip") 89 | .stdout(Stdio::null()) 90 | .stderr(Stdio::null()) 91 | .status() 92 | .or_else(|_| Err("Please install strip!"))?; 93 | 94 | // Retrieve package information 95 | let metadata = MetadataCommand::new() 96 | .manifest_path("./Cargo.toml") 97 | .no_deps() 98 | .exec() 99 | .or_else(|_| Err("Cannot parse Cargo.toml!"))?; 100 | 101 | // Iterate over the target directory 102 | for entry in fs::read_dir(metadata.target_directory) 103 | .or_else(|_| Err("Cannot access the target directory!"))? 104 | { 105 | // Identify directories and continue otherwise 106 | let entry = entry.or_else(|_| Err("IO error!"))?; 107 | if !entry 108 | .file_type() 109 | .or_else(|_| Err("Cannot get file type!"))? 110 | .is_dir() 111 | { 112 | continue; 113 | } 114 | 115 | // Iterate over possible binaries 116 | for binary in metadata 117 | .packages 118 | .iter() 119 | .flat_map(|p| &p.targets) 120 | .filter(|t| t.kind == vec!["bin"]) 121 | .map(|x| &x.name) 122 | { 123 | // Build a path containing the specified target 124 | let mut path = if matches.is_present("target") { 125 | let path = entry.path(); 126 | // Remove the last element from the path 127 | let root_path = path 128 | .ancestors() 129 | .nth(1) 130 | .ok_or("Cannot remove build from path!")?; 131 | 132 | // Add the target & the last element of the path 133 | root_path.join(matches.value_of("target").unwrap()).join( 134 | path.components() 135 | .last() 136 | .ok_or("Cannot extract build from path!")? 137 | .as_os_str(), 138 | ) 139 | } else { 140 | entry.path() 141 | }; 142 | 143 | // Check if the binary exists in the current directory 144 | path.push(binary); 145 | if !path.is_file() { 146 | continue; 147 | } 148 | 149 | strip_binary(&mut path)?; 150 | } 151 | } 152 | 153 | Ok(()) 154 | } 155 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "ansi_term" 5 | version = "0.11.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 9 | ] 10 | 11 | [[package]] 12 | name = "atty" 13 | version = "0.2.14" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | dependencies = [ 16 | "hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 17 | "libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)", 18 | "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", 19 | ] 20 | 21 | [[package]] 22 | name = "bitflags" 23 | version = "1.2.1" 24 | source = "registry+https://github.com/rust-lang/crates.io-index" 25 | 26 | [[package]] 27 | name = "cargo-strip" 28 | version = "0.2.3" 29 | dependencies = [ 30 | "cargo_metadata 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 31 | "clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)", 32 | ] 33 | 34 | [[package]] 35 | name = "cargo_metadata" 36 | version = "0.10.0" 37 | source = "registry+https://github.com/rust-lang/crates.io-index" 38 | dependencies = [ 39 | "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)", 43 | ] 44 | 45 | [[package]] 46 | name = "clap" 47 | version = "2.33.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | dependencies = [ 50 | "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", 55 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 57 | ] 58 | 59 | [[package]] 60 | name = "hermit-abi" 61 | version = "0.1.13" 62 | source = "registry+https://github.com/rust-lang/crates.io-index" 63 | dependencies = [ 64 | "libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)", 65 | ] 66 | 67 | [[package]] 68 | name = "itoa" 69 | version = "0.4.5" 70 | source = "registry+https://github.com/rust-lang/crates.io-index" 71 | 72 | [[package]] 73 | name = "libc" 74 | version = "0.2.70" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | 77 | [[package]] 78 | name = "proc-macro2" 79 | version = "1.0.17" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | dependencies = [ 82 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 83 | ] 84 | 85 | [[package]] 86 | name = "quote" 87 | version = "1.0.6" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | dependencies = [ 90 | "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 91 | ] 92 | 93 | [[package]] 94 | name = "ryu" 95 | version = "1.0.4" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | 98 | [[package]] 99 | name = "semver" 100 | version = "0.9.0" 101 | source = "registry+https://github.com/rust-lang/crates.io-index" 102 | dependencies = [ 103 | "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", 104 | "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", 105 | ] 106 | 107 | [[package]] 108 | name = "semver-parser" 109 | version = "0.7.0" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | 112 | [[package]] 113 | name = "serde" 114 | version = "1.0.110" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | 117 | [[package]] 118 | name = "serde_derive" 119 | version = "1.0.110" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | dependencies = [ 122 | "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 123 | "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 124 | "syn 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", 125 | ] 126 | 127 | [[package]] 128 | name = "serde_json" 129 | version = "1.0.53" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | dependencies = [ 132 | "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", 133 | "ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 134 | "serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)", 135 | ] 136 | 137 | [[package]] 138 | name = "strsim" 139 | version = "0.8.0" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | 142 | [[package]] 143 | name = "syn" 144 | version = "1.0.23" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | dependencies = [ 147 | "proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", 148 | "quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", 149 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 150 | ] 151 | 152 | [[package]] 153 | name = "textwrap" 154 | version = "0.11.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 158 | ] 159 | 160 | [[package]] 161 | name = "unicode-width" 162 | version = "0.1.7" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | 165 | [[package]] 166 | name = "unicode-xid" 167 | version = "0.2.0" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | 170 | [[package]] 171 | name = "vec_map" 172 | version = "0.8.2" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | 175 | [[package]] 176 | name = "winapi" 177 | version = "0.3.8" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | dependencies = [ 180 | "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 181 | "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 182 | ] 183 | 184 | [[package]] 185 | name = "winapi-i686-pc-windows-gnu" 186 | version = "0.4.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | 189 | [[package]] 190 | name = "winapi-x86_64-pc-windows-gnu" 191 | version = "0.4.0" 192 | source = "registry+https://github.com/rust-lang/crates.io-index" 193 | 194 | [metadata] 195 | "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" 196 | "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 197 | "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 198 | "checksum cargo_metadata 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8de60b887edf6d74370fc8eb177040da4847d971d6234c7b13a6da324ef0caf" 199 | "checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129" 200 | "checksum hermit-abi 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" 201 | "checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 202 | "checksum libc 0.2.70 (registry+https://github.com/rust-lang/crates.io-index)" = "3baa92041a6fec78c687fa0cc2b3fae8884f743d672cf551bed1d6dac6988d0f" 203 | "checksum proc-macro2 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "1502d12e458c49a4c9cbff560d0fe0060c252bc29799ed94ca2ed4bb665a0101" 204 | "checksum quote 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "54a21852a652ad6f610c9510194f398ff6f8692e334fd1145fed931f7fbe44ea" 205 | "checksum ryu 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ed3d612bc64430efeb3f7ee6ef26d590dce0c43249217bddc62112540c7941e1" 206 | "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" 207 | "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" 208 | "checksum serde 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "99e7b308464d16b56eba9964e4972a3eee817760ab60d88c3f86e1fecb08204c" 209 | "checksum serde_derive 1.0.110 (registry+https://github.com/rust-lang/crates.io-index)" = "818fbf6bfa9a42d3bfcaca148547aa00c7b915bec71d1757aa2d44ca68771984" 210 | "checksum serde_json 1.0.53 (registry+https://github.com/rust-lang/crates.io-index)" = "993948e75b189211a9b31a7528f950c6adc21f9720b6438ff80a7fa2f864cea2" 211 | "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" 212 | "checksum syn 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "95b5f192649e48a5302a13f2feb224df883b98933222369e4b3b0fe2a5447269" 213 | "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" 214 | "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" 215 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 216 | "checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" 217 | "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 218 | "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 219 | "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 220 | --------------------------------------------------------------------------------