1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//! duckfn 命令行工具的入口:
//! `cargo run --features quack --bin duckfn-cli -- function_descriptions`
//!
//! 工具本身的实现都在 `duckfn::cli`(需要打开 duckfn 的 `quack` feature,它带上 `cli`),这里只
//! 负责把插件本体挂进来、把项目根目录传下去。
//!
//! 为什么用 `#[path]` 把 `extension` 编进来,而不是 `use duckfn::…`:`#[duck_*]` 的文档元数据靠
//! `inventory` 的静态构造器收集,只有**真正被链接进最终二进制**的目标文件才会生效。直接依赖 rlib
//! 时,链接器可能因为没人引用那些模块而把它们整块丢掉,导出的 CSV 就会是空的(而且是静默的)。
//! 让 bin 自己把同一份源码编一遍,注册项就落在本 crate 里,一定齐全。
//!
//! 注意只编 `extension/mod.rs`:入口符号在 `extension/entry.rs`,由扩展产物那个 target
//! (`examples/duckfn.rs`)声明;这个 bin 是个 executable,用不上它。目标名之所以是 `duckfn-cli`
//! 而不是文件名里的 `duckfn`,是为了避开扩展产物(也叫 duckfn)的同名冲突,见根 Cargo.toml 的
//! 说明。
//!
//! The entry point of the duckfn command-line tool:
//! `cargo run --features quack --bin duckfn-cli -- function_descriptions`. The tool itself lives in
//! `duckfn::cli` (which needs duckfn's `quack` feature — it pulls `cli` in); this file only pulls the
//! extension in and passes the project root down. `#[path]` is used instead of `use duckfn::…`
//! because the documentation metadata behind `#[duck_*]` is collected by `inventory`'s static
//! constructors, which only fire for object files that are really linked into the final binary: when
//! merely depending on an rlib, the linker may drop those modules entirely and the exported CSV would
//! come out empty — silently.
//!
//! Only `extension/mod.rs` is included: the entry symbol lives in `extension/entry.rs`, declared by the
//! extension-artefact target (`examples/duckfn.rs`); this bin is an executable and has no use for it.
//! The target is called `duckfn-cli` rather than the `duckfn` its file is named after to avoid
//! colliding with the extension artefact, which is also called duckfn — see the note in the root
//! Cargo.toml.