3 releases
0.1.2 | Nov 8, 2020 |
---|---|
0.1.1 | Sep 2, 2020 |
0.1.0 | Sep 1, 2020 |
#38 in #competitive-programming
2KB
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
[package]
name = "library-checker"
version = "0.0.0"
edition = "2018"
[dependencies]
ac-library-rs-parted-modint = { git = "https://github.com/qryxip/ac-library-rs-parted" }
proconio = { version = "0.4.3", features = ["derive"] }
qryxip-competitive-tonelli-shanks = { git = "https://github.com/qryxip/competitive-programming-library" }
# ...
use acl_modint::ModInt;
use proconio::{fastout, input};
use tonelli_shanks::ModIntBaseExt as _;
#[fastout]
fn main() {
input! {
yps: [(u32, u32)],
}
for (y, p) in yps {
ModInt::set_modulus(p);
if let Some(x) = ModInt::new(y).sqrt() {
println!("{}", x);
} else {
println!("-1");
}
}
}
mod sub {
// You can also `use` the crate in submodules.
#[allow(unused_imports)]
use proconio::input as _;
}
↓
❯ cargo equip \
> --remove docs `# Remove doc comments` \
> --minify libs `# Minify each library` \
> --bin sqrt_mod `# Specify the bin crate` | xsel -b
Submit Info #59239 - 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 cargo-equip --git https://github.com/qryxip/cargo-equip
GitHub Releases
Usage
Follow these constrants when you writing libraries to bundle.
-
Set
package.edition
to"2018"
."2015"
is not supported. -
Do not use procedural macros in
lib
crates.You can
pub use
them, but cannot call. -
Use
$crate
instead ofcrate
in macros.cargo-equip replaces
$crate
inmacro_rules!
with$crate::extern_crate_name_in_main_crate
.crate
identifiers inmacro_rules!
are not modified. -
Do not use absolute path as possible.
cargo-equip replaces
crate
withcrate::extern_crate_name_in_main_crate
andpub(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.
[dependencies]
ac-library-rs-parted = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-convolution = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-dsu = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-fenwicktree = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-lazysegtree = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-math = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-maxflow = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-mincostflow = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-modint = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-scc = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-segtree = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-string = { git = "https://github.com/qryxip/ac-library-rs-parted" }
ac-library-rs-parted-twosat = { git = "https://github.com/qryxip/ac-library-rs-parted" }
The constraints for bin
s/example
s are:
-
If you use
proc-macro
crates, 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.
pub use __cargo_equip::prelude::*; // ︙ pub mod __cargo_equip { pub mod crates { // ︙ } // ︙ pub(crate) prelude { pub use crate::__cargo_equip::crates::*; } }
use input::input;
use mic::answer;
use partition_point::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))
}
Then execute cargo-equip
.
❯ cargo equip --bin "$name"
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
:false
proc_macro
:false
cargo_equip
:true
feature
:true
for those enabled- Otherwise: unknown
#[allow(dead_code)]
pub mod a {
pub struct A;
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
}
↓
#[allow(dead_code)]
pub mod a {
pub struct A;
}
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::memoise;
use proconio_derive::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)
}
proc-macro
crates need to be compile with Rust 1.48.0+. If version of the active toolchain is less than 1.48.0, cargo-equip finds an alternative toolchain and uses it for compilingproc-macro
s.- 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
.
#[allow(dead_code)]
pub mod a {
//! A.
/// A.
pub struct A; // aaaaa
}
↓
#[allow(dead_code)]
pub mod a {
pub struct A;
}
--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.