如何解决CLI工具在Rust Cargo工作区中的依赖冲突?

zdwk9cvp  于 2023-11-19  发布在  Go
关注(0)|答案(1)|浏览(159)

我正在开发一个CLI工具,其中包含几个用于不同用例的子命令。以下是我的项目结构:

project/
├── Cargo.toml 
└── crates/
    ├── project-foo/
    │   └── src/
    │       └── lib.rs (subcommand for 'foo')
    ├── project-bar/
    │   └── src/
    │       └── lib.rs (subcommand for 'bar')
    └── project-core/
        └── src/
            └── main.rs (main entry point for the CLI app)

字符串
在我的Cargo.toml中,我设置了一个工作区配置,如下所示:

[workspace]
members = ["crates/*"]

resolver = "2"


例如,考虑project-foo crate,它公开了一个名为FileAction的子命令。

#[derive(Debug, Subcommand)]
pub enum FileAction {
    Copy(CopyCommand),
    Paste(PasteCommand),
}

#[derive(Debug, clap::Args)]
pub struct CopyCommand {
    // Include any relevant options here.
}

impl CopyCommand {
    pub async fn handle(&self) -> Result<()> {
        // handle the code 
    }
}


project-core crate中,我们使用Cli结构来管理这些子命令。

#[derive(Parser)]
#[command(subcommand_required = true)]
pub struct Cli {
    #[command(subcommand)]
    pub command: Commands,
}

#[derive(Subcommand)]
pub enum Commands {
    File {
        #[clap(subcommand)]
        action: FileAction,
    },
}

fn main() {
    let matches = Cli::command().get_matches();
    let cli = Cli::from_arg_matches(&matches).unwrap();

    match cli.command {
        File { action } => match action {
            FileAction::Copy(copy_args) => {
                if let Err(err) = copy_args.handle().await {
                    eprintln!("{}", err);
                }
            },
            FileAction::Paste(paste_args) => {
                if let Err(err) = paste_args.handle().await {
                    eprintln!("{}", err);
                }
            },
        },
    }
}


理想情况下,我的project-core/Cargo.toml看起来像这样:

[package]
name = "project"
version = "0.1.0"
edition = "2021"

[dependencies]
project-foo = { path = "../project-foo" }
project-bar = { path = "../project-bar" }


由于两个子命令中使用的crate之间存在持久的依赖性问题,这种方法不起作用。
注意:由于功能统一,货物功能不能用于解决问题
我最初的想法是将一个crate移出crates文件夹,这样当我运行cargo build时它就不会自动编译。然后,我想找到一种方法从project-core构建它,并在project-core/main.rs中定义的CLI中作为子进程执行它。这种方法是否可行,它是否是一个好的解决方案?或者有没有更直接的方法来解决这个问题

4uqofj5v

4uqofj5v1#

我设法通过修补导致问题的板条箱来解决这个问题。
在两个依赖项(如project-fooproject-bar)依赖于第三个crate的不同版本的场景中,会出现依赖项冲突。
每个crate都指定了一个特定的版本,导致了这个冲突。幸运的是,我在第三个crate中找到了一个符合两个crate版本要求的提交。我给我的Cargo.toml添加了一个补丁来解决这个问题:

[patch.crates-io.third_crate]
git = "https://github.com/user/third_crate"
rev = "<commit>" # This commit meets both crates' version requirements

字符串
然而,如果没有合适的提交存在,我会采取分叉板条箱和修改来解决这个问题。

相关问题