cargo-equip
A Cargo subcommand to bundle your code into one .rs file for competitive programming.
Recent updates
See CHANGELOG.md or Releases for recent updates.
Features
cargo-equip can
- bundle multiple crates,
- bundle only used crates,
- exclude certain crates (
--exclude-{atcoder, codingame}-crates), - expand procedural macros,
- preserve scopes for
#[macro_export]ed macros, - resolve
#[cfg(..)], - remove comments and doc comments (
--remove), - minify code (
--minify), - and check the output.
Example
[]
= "library-checker"
= "0.0.0"
= "2018"
[]
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "0.4.3", = ["derive"] }
= { = "https://github.com/qryxip/competitive-programming-library" }
# ...
use ModInt;
use ;
use ModIntBaseExt as _;
↓
❯ cargo equip \
> --remove docs `# Remove doc comments` \
> --minify libs `# Minify each library` \
> --bin sqrt_mod `# Specify the bin crate` | xsel -b
Submit Info #52332 - Library-Checker
Works With
- fixedbitset 0.4.0
- lazy_static 1.4.0
- maplit 1.0.2
- memoise 0.3.2
- multimap 0.8.3
- permutohedron 0.2.4
- proconio 0.4.3
- rustc-hash 1.1.0
- smallvec 1.6.1
- strsim 0.10.0
- whiteread 0.5.0
Installation
Install a nightly toolchain and cargo-udeps first.
❯ rustup update nightly
❯ cargo install cargo-udeps
From Crates.io
❯ cargo install cargo-equip
From master branch
❯ cargo install --git https://github.com/qryxip/cargo-equip
GitHub Releases
Usage
Follow these constrants when you writing libraries to bundle.
-
Set
package.editionto"2018"."2015"is not supported. -
Do not use procedural macros in
libcrates.You can
pub usethem, but cannot call. -
Use
$crateinstead ofcratein macros.cargo-equip replaces
$crateinmacro_rules!with$crate::extern_crate_name_in_main_crate.crateidentifiers inmacro_rules!are not modified. -
Do not use absolute path as possible.
cargo-equip replaces
cratewithcrate::extern_crate_name_in_main_crateandpub(crate)withpub(in crate::extern_crate_name_in_main_crate).However I cannot ensure this works well. Use
self::andsuper::instead ofcrate::.-use crate::foo::Foo; +use super::foo::Foo; -
If possible, do not use glob import.
cargo-equip inserts glob imports as substitutes for extern prelude and
#[macro_use]. -
Split into small separate crates as possible.
cargo-equip does not search "dependencies among items".
On a website other except AtCoder, Split your library into small crates to fit in 64KiB.
. ├── a │ ├── Cargo.toml │ └── src │ └── lib.rs ├── b │ ├── Cargo.toml │ └── src │ └── lib.rs ⋮
When you finish preparing your library crates, add them to [dependencies] of the bin/example.
If you generate packages automatically with a tool, add them to its template.
If you want to use rust-lang-ja/ac-library-rs, use qryxip/ac-library-rs-parted instead.
[]
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
= { = "https://github.com/qryxip/ac-library-rs-parted" }
The constraints for bins/examples are:
-
If you use
proc-macrocrates, make sure the macro names unique.If you have trouble about procedural macro names, you can import them with
#[macor_use]. -
If possible, do not use glob import.
cargo-equip also inserts glob imports as it does into libraries.
crateprelude_for!; ;
use input;
use answer;
use RangeBoundsExt as _;
Then execute cargo-equip.
❯ cargo equip --bin "$name"
cargo-equip outputs code like this.
It gives tentative extern_crate_names like __package_name_0_1_0 to dependencies of the dependencies.
//! # Bundled libraries
//!
//! - `mic 0.0.0 (path+███████████████████████████████████████████)` published in https://github.com/qryxip/mic licensed under `CC0-1.0` as `crate::__cargo_equip::crates::mic`
//! - `qryxip-competitive-input 0.0.0 (git+https://github.com/qryxip/competitive-programming-library#dadeb6e4685a86f25b4e5c8079f56337321aa12e)` licensed under `CC0-1.0` as `crate::__cargo_equip::crates::input`
//! - `qryxip-competitive-partition-point 0.0.0 (git+https://github.com/qryxip/competitive-programming-library#dadeb6e4685a86f25b4e5c8079f56337321aa12e)` licensed under `CC0-1.0` as `crate::__cargo_equip::crates::partition_point`
//!
//! # Procedural macros
//!
//! - `mic_impl 0.0.0 (path+████████████████████████████████████████████████████)` published in https://github.com/qryxip/mic licensed under `CC0-1.0`
pub use *;
use input;
use answer;
use RangeBoundsExt as _;
/*#[answer(join("\n"))]
fn main() -> _ {
input! {
a: [u64],
}
a.into_iter()
.map(|a| (1u64..1_000_000_000).partition_point(|ans| ans.pow(2) < a))
}*/
// The following code was expanded by `cargo-equip`.
const _: = ;
Resolving #[cfg(…)]
By default, cargo-equip
- Removes
#[cfg(always_true_predicate)](e.g.cfg(feature = "enabled-feature")). - Removes items with
#[cfg(always_false_preducate)](e.g.cfg(test),cfg(feature = "disable-feature")).
Predicates are evaluated according to this rule.
test:falseproc_macro:falsecargo_equip:truefeature:truefor those enabled- Otherwise: unknown
↓
Checking the output
By default, cargo-equip creates a temporary package that shares the current target directory and execute cargo check before outputting.
Checking cargo-equip-check-output-6j2i3j3tgtugeaqm v0.1.0 (/tmp/cargo-equip-check-output-6j2i3j3tgtugeaqm)
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
Expanding procedural macros
cargo-equip can expand procedural macros.
use memoise;
use fastout;
↓
//! # Procedural macros
//!
//! - `memoise 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)` licensed under `BSD-3-Clause`
//! - `proconio-derive 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)` licensed under `MIT OR Apache-2.0`
pub use *;
use memoise;
use fastout;
/*#[fastout]
fn main() {
for i in 0..=10 {
println!("{}", fib(i));
}
}*/
/*#[memoise(n <= 10)]
fn fib(n: i64) -> i64 {
if n == 0 || n == 1 {
return n;
}
fib(n - 1) + fib(n - 2)
}*/
thread_local!;
// The following code was expanded by `cargo-equip`.
const _: = ;
rust-analyzer(.exe)is automatically downloaded.proc-macrocrates need to be compile with Rust 1.47.0+. If version of the active toolchain is less than 1.47.0, cargo-equip finds an alternative toolchain and uses it for compilingproc-macros.- procedural macros re-exported with
pub use $name::*;are also able to be expanded.
Options
--remove <REMOVE>...
Removes
- doc comments (
//! ..,/// ..,/** .. */,#[doc = ".."]) with--remove docs. - comments (
// ..,/* .. */) with--remove comments.
↓
--minify <MINIFY>
Minifies
- each expaned library with
--minify lib. - the whole code with
--minify all.
Not that the minification function is incomplete. Unnecessary spaces may be inserted.
--no-resolve-cfgs
Do not resolve #[cfg(…)].
--no-rustfmt
Do not format the output.
--no-check
Do not check the output.
License
Dual-licensed under MIT or Apache-2.0.