3 个版本

0.1.2 2020年11月8日
0.1.1 2020年9月2日
0.1.0 2020年9月1日

#34 in #competitive-programming

MIT/Apache

2KB

cargo-equip

CI codecov dependency status Crates.io Crates.io

日语

A Cargo 子命令,用于将您的代码打包成一个 .rs 文件,以便进行竞技编程。

最近更新

请参阅 CHANGELOG.md发布 以获取最近更新。

功能

cargo-equip 可以

  • 打包多个crate,
  • 只打包使用的crate,
  • 排除某些crate (--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

提交信息 #59239 - 库检查器

兼容

安装

首先安装 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 发布

发布

用法

编写要打包的库时,请遵循以下约定。

  1. package.edition 设置为 "2018"

    "2015" 不受支持。

  2. 不要在lib包中使用过程宏。

    您可以使用它们,但不能调用它们。

  3. 在宏中使用$crate代替crate

    cargo-equip将宏中的$crate替换为$crate::extern_crate_name_in_main_crate。在macro_rules!中的crate标识符不会被修改。

  4. 尽量不要使用绝对路径。

    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;
    
  5. 如果可能,不要使用glob导入

    cargo-equip将glob导入作为extern预导入#[macro_use]的替代。

  6. 尽可能将它们拆分为小的独立包。

    cargo-equip不会在项目间搜索"依赖关系"。

    除了AtCoder之外的网站,将您的库拆分为小包以适应64KiB。

    .
    ├── a
       ├── Cargo.toml
       └── src
           └── lib.rs
    ├── b
       ├── Cargo.toml
       └── src
           └── lib.rs
    
    

当您准备好您的库包后,将它们添加到bin/example[dependencies]中。如果您使用工具自动生成包,请将其添加到其模板中。

如果您想使用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" }

binexample的约束条件是

  1. 如果您使用proc-macro包,请确保宏名称是唯一的。

    如果您在过程宏名称上有困难,您可以使用#[macor_use].导入它们。

  2. 如果可能,不要使用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

  1. 移除 #[cfg(always_true_predicate)](例如 cfg(feature = "enabled-feature"))。
  2. 移除具有 #[cfg(always_false_preducate)](例如 cfg(test)cfg(feature = "disable-feature"))的项。

根据此规则评估谓词。

  • testfalse
  • proc_macrofalse
  • cargo_equiptrue
  • 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

不要检查输出。

许可证

双许可下 MITApache-2.0

无运行时依赖