< 返回版块

jasper2007111 发表于 2024-05-05 09:12

比如有如下目录:

src:
  app
    main.rs
    render.rs
  dyn_app
    main.rs
    render.rs
  gui
    mod.rs
  macos_gui
    mod.rs
    factory.rs
  windows_gui
    mod.rs
    factory.rs

然后我在tom文件中设定

[[bin]]
name = "app"
path = "src/app/main.rs"

[[bin]]
name = "dyn_app"
path = "src/dyn_app/main.rs"

这样就可以使用cargo run --bin运行不同的main程序了,但是有个问题无论是app还是dyn_app都无法引用到根目录下的gui、macos_gui、windows_gui的东西。


use crate::macos_gui::factory::MacFactory;
use super::render::render;

// use windows_gui::factory::WindowsFactory;

fn main() {
    let windows = false;

    if windows {
        // render(WindowsFactory);
    } else {
        render(MacFactory);
    }
}

我在根目录下弄了一个mod.rs似乎也不行。所以想请教下正确的思路应该如何设计?谢谢


Ext Link:

评论区

写评论
viruscamp 2024-05-06 20:59

实际测试下来,最近的 cargo 应该是有些改进,src\bin\bin1.rs 和 examples\ex1.rs 的处理方法几乎是一样了。

相当于一个 隐形的 bin 类型的 crate 只有一个 main 对应 src\bin\bin1.rs ,然后加入主 crate 作为依赖,所以要有 src/lib.rs ,而且 bin 只能使用 pub 的 mod 。

这样的话 src\bin\bin1.rs 和 src\bin\bin2.rs 和 examples\ex1.rs 属于3个不同的 crate ,一个编译错误不会妨碍别的运行。

src/main.rs 内不定义 mod 时,也是通过 src/lib.rs 使用的,与上面的方法一样。

src/main.rs 特殊的点在于它可自成 mod 树根,定义 mod 后不用 src/lib.rs 。

viruscamp 2024-05-06 20:40

多 bin 也可以,必须这样做:

  1. src/lib.rs 定义所有 mod
  2. src/bin/bin1.rs 只能通过 src/lib.rs 来引用其他 mod
  3. src/bin/bin1.rs 内 use crate::gui; 不能用,必须写成 use actual_crate_name::gui;
  4. src/main.rs 内定义 mod 的话,可以直接使用
  5. src/main.rs 内不定义 mod 的话,必须通过 lib.rs 引用,同样写成 use actual_crate_name::gui;
  6. src/main.rs 如下定义后, 可以直接运行 cargo run
[package]
name = "actual_crate_name"
version = "0.1.0"
edition = "2021"
default-run = "main"

[[bin]]
name = "main"
path = "src/main.rs"
viruscamp 2024-05-06 20:10
  • 文件布局
src/lib.rs # 要定义 gui
src/main.rs # 要定义 gui
src/gui/mod.rs

examples/app/main.rs
examples/dyn_app/main.rs
  • cargo.toml
[[example]]
name = "app"
path = "examples/app/main.rs"

[[example]]
name = "dyn_app"
path = "examples/dyn_app/main.rs"
required-features = ["dyn"]

[dev-dependencies]
# 可以放 examples 的额外依赖,不影响主库
  • 运行命令行
cargo run --example app
cargo run --example dyn_app
# examples 里面的文件编译失败, 不影响 src/main.rs

# 仍然可以跑 src/main.rs
cargo run
asuper 2024-05-06 09:41

需要这个文件 src/lib.rs,里面定义各个mod。

另外,一般定义多个bin,是放在工作目录的根目录下放一个app或者是bin,与src同级,你这样感觉不伦不类的

TinusgragLin 2024-05-05 19:10

[[]]是定义一个 table array[]是定义一个 table,从文档上来看,lib 应该是只能有一个:

A package can have only one library.

所以用的是 []

作者 jasper2007111 2024-05-05 16:42

你说的应该是另建一个lib工程是不?在原来的工程中我如果把Cargo.toml改成这样好像有问题。


[[bin]]
name = "app"
path = "src/app/main.rs"

[[bin]]
name = "dyn_app"
path = "src/dyn_app/main.rs"


[[lib]]
name = "gui"
path = "src/gui/lib.rs"

[[lib]]
name = "macos_gui"
path = "src/macos_gui/lib.rs"

会报invalid type: map, expected a string in 'lib'

👇
TinusgragLin: 如果 crate 的类型就是 lib 的话,在其他 binary 里用 use [crate名字] 就可以引用这个 lib crate;如果类型是 binary 的话,可以像这样创建一个 lib,把公用的东西放在这个lib里:

# Cargo.toml
[lib]
name = "mylib"
path = "src/mylib/lib.rs"

在其他 binary 里就可以用 use mylib 了。

bestgopher 2024-05-05 15:40

放bin不行吗?

TinusgragLin 2024-05-05 14:14

如果 crate 的类型就是 lib 的话,在其他 binary 里用 use [crate名字] 就可以引用这个 lib crate;如果类型是 binary 的话,可以像这样创建一个 lib,把公用的东西放在这个lib里:

# Cargo.toml
[lib]
name = "mylib"
path = "src/mylib/lib.rs"

在其他 binary 里就可以用 use mylib 了。

作者 jasper2007111 2024-05-05 12:32

因为这个是多个main文件分别在app和dyn_app目录下,而引用的模块是在他们的上层目录下,所以声明了也是有问题的。

--
👇
ankoGo: 你都还没在main中声明mod xxx

ankoGo 2024-05-05 11:44

你都还没在main中声明mod xxx

1 共 10 条评论, 1 页