39 个不稳定版本
0.20.1 | 2023年8月6日 |
---|---|
0.19.0 | 2022年3月26日 |
0.18.1 | 2021年12月23日 |
0.18.0 | 2021年9月7日 |
0.9.0 | 2020年11月27日 |
#200 在 Cargo 插件 中
205KB
4.5K SLoC
cargo-equip
Cargo 子命令,用于将您的代码打包成一个 .rs
文件进行竞技编程。
近期更新
请参阅 CHANGELOG.md 或 发布 了解最近更新。
功能
cargo-equip 可以
- 打包多个包
- 只打包使用过的包
- 排除某些包 (
--exclude-{atcoder, codingame}-crates
) - 展开过程宏
- 保留
#[macro_export]
宏的作用域 - 解析
#[cfg(..)]
- 移除注释和文档注释 (
--remove
) - 压缩代码 (
--minify
) - 并检查输出
示例
[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
兼容
- 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
安装
首先安装 nightly
工具链和 cargo-udeps。
❯ rustup update nightly
❯ cargo install cargo-udeps
从 Crates.io
❯ cargo install cargo-equip
从 master
分支
❯ cargo install cargo-equip --git https://github.com/qryxip/cargo-equip
GitHub 发布
用法
在编写用于打包的库时,请遵循以下约定。
-
将
package.edition
设置为"2018"
。"2015"
不受支持。 -
在
lib
包中不要使用过程宏。你可以使用它们,但不能调用。
-
在宏中使用
$crate
代替crate
。cargo-equip将宏中的
$crate
替换为$crate::extern_crate_name_in_main_crate
。宏中的crate
标识符不会被修改。 -
尽可能不要使用绝对路径。
cargo-equip将
crate
替换为crate::extern_crate_name_in_main_crate
,并将pub(crate)
替换为pub(in crate::extern_crate_name_in_main_crate)
。然而,我无法保证这会很好地工作。使用
self::
和super::
代替crate::
。-use crate::foo::Foo; +use super::foo::Foo;
-
如果可能,不要使用glob导入。
cargo-equip将glob导入作为extern预导入和
#[macro_use]
的替代。 -
尽可能将它们分成小的单独包。
cargo-equip不会搜索"项目之间的依赖关系"。
在AtCoder以外的网站上,将你的库拆分成小的包以适应64KiB。
. ├── a │ ├── Cargo.toml │ └── src │ └── lib.rs ├── b │ ├── Cargo.toml │ └── src │ └── lib.rs ⋮
当你准备好你的库包后,将它们添加到[dependencies]
的bin
/example
中。如果你使用工具自动生成包,请将其添加到其模板中。
如果你想使用rust-lang-ja/ac-library-rs,请使用qryxip/ac-library-rs-parted。
[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" }
二进制文件/示例的约束条件是
-
如果你使用
proc-macro
包,请确保宏名称是唯一的。如果你在过程宏名称上遇到困难,你可以使用
#[macor_use].
导入它们。 -
如果可能,不要使用glob导入。
cargo-equip也会像在库中做的那样插入glob导入。
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))
}
然后执行cargo-equip
。
❯ cargo equip --bin "$name"
解析#[cfg(…)]
默认情况下,cargo-equip
- 移除
#[cfg(always_true_predicate)]
(例如:cfg(feature = "enabled-feature")
)。 - 移除带有
#[cfg(always_false_preducate)]
(例如:cfg(test)
,cfg(feature = "disable-feature")
)的项目。
谓词将根据此规则进行评估。
test
:false
proc_macro
:false
cargo_equip
:true
feature
:对已启用的功能为true
- 否则:未知
#[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;
}
检查输出
默认情况下,cargo-equip 创建一个与当前目标目录共享的临时包,并在输出之前执行 cargo check
。
Checking cargo-equip-check-output-6j2i3j3tgtugeaqm v0.1.0 (/tmp/cargo-equip-check-output-6j2i3j3tgtugeaqm)
Finished dev [unoptimized + debuginfo] target(s) in 0.11s
展开过程宏
cargo-equip 可以展开过程宏。
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
包需要使用 Rust 1.48.0+ 编译。如果活动工具链的版本低于 1.48.0,则 cargo-equip 会找到替代工具链并使用它来编译proc-macro
。- 使用
pub use $name::*;
重导出的过程宏也可以展开。
选项
--remove<REMOVE>...
移除
- 文档注释(
//! ..
、/// ..
、/** .. */
、#[doc = ".."]
)使用--remove docs
。 - 注释(
// ..
、/* .. */
)使用--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>
精简
- 使用
--minify lib
对每个展开的库进行精简。 - 使用
--minify all
对整个代码进行精简。
请注意,精简功能尚不完整。可能会插入不必要的空格。
--no-resolve-cfgs
不要解析 #[cfg(…)]
。
--no-rustfmt
不要格式化输出。
--no-check
不要检查输出。
许可证
MIT或Apache-2.0双许可。
依赖项
~14–25MB
~345K SLoC