diff options
| author | 魏曹先生 <1992414357@qq.com> | 2026-08-17 19:21:52 +0800 |
|---|---|---|
| committer | 魏曹先生 <1992414357@qq.com> | 2026-08-17 19:21:52 +0800 |
| commit | 89bf57f33a9f0f5a96fc50e272c83d926fa35c4a (patch) | |
| tree | cc5a72e850bdd9215b60dc1655f162e22ee97d12 | |
| parent | 40bb7ffd6954184fac718c8f99c9cdc3e054e4eb (diff) | |
refactor!: replace build.rs with compile-time macro build steps
BREAKING CHANGE: Replace the `build`/`builds` feature system with
compile-time macro-driven generation. `gen_program!()` now automatically
invokes `build_comp!()` and `build_pathf!()` when the `comp`/`pathf`
features are enabled, eliminating the need for `build.rs` and
`[build-dependencies]` blocks.
This removes the `build` feature, the `mingling::build` module, and all
related build-time API functions. Completion scripts are now written to
`{target_directory}/mingling/` instead of `target/release/`. The
`mingling_cli` uses `build_comp!("mling")` for its custom binary name.
65 files changed, 1357 insertions, 771 deletions
diff --git a/.run/src/bin/install-mling.ps1 b/.run/src/bin/install-mling.ps1 index 2bc28ee..2b55a09 100644 --- a/.run/src/bin/install-mling.ps1 +++ b/.run/src/bin/install-mling.ps1 @@ -6,5 +6,5 @@ New-Item -ItemType Directory -Force -Path .temp/mling/bin, .temp/mling/scripts | Copy-Item .temp/target/release/mling.exe .temp/mling/bin/ Copy-Item .temp/target/release/mingling-cli.exe .temp/mling/bin/ -Copy-Item .temp/target/release/mling_comp.ps1 .temp/mling/scripts/mling_comp.ps1 +Copy-Item .temp/target/mingling/mling_comp.ps1 .temp/mling/scripts/mling_comp.ps1 Copy-Item mingling_cli/scripts/load_mling.ps1 .temp/mling/ diff --git a/.run/src/bin/install-mling.sh b/.run/src/bin/install-mling.sh index 139e221..e8cfa18 100755 --- a/.run/src/bin/install-mling.sh +++ b/.run/src/bin/install-mling.sh @@ -10,7 +10,7 @@ cp .temp/target/release/mling .temp/mling/bin/ cp .temp/target/release/mingling-cli .temp/mling/bin/ for comp in zsh sh fish; do - cp ".temp/target/release/mling_comp.$comp" ".temp/mling/scripts/mling_comp.$comp" + cp ".temp/target/mingling/mling_comp.$comp" ".temp/mling/scripts/mling_comp.$comp" done cp mingling_cli/scripts/load_mling.zsh .temp/mling/ cp mingling_cli/scripts/load_mling.sh .temp/mling/ diff --git a/.run/src/verify.rs b/.run/src/verify.rs index 0a4b354..b79bb73 100644 --- a/.run/src/verify.rs +++ b/.run/src/verify.rs @@ -215,16 +215,15 @@ pub fn generate_cargo_toml(block: &CodeBlock, package_name: &str, manifest_path: ) }; - // Build-time blocks: add `builds` by default, merge with explicit features + // Build-time blocks: mirror the declared features into [build-dependencies] + // so that build.rs can use the same feature set as the crate itself. let build_deps_section = if block.is_build_time { - let mut all_feats = vec!["builds".to_string()]; - for f in &block.features { - if f != "builds" { - all_feats.push(f.clone()); - } - } - let feats_str: Vec<String> = all_feats.iter().map(|f| format!("\"{f}\"")).collect(); - let build_feats = format!("features = [{}]", feats_str.join(", ")); + let feats_str: Vec<String> = block.features.iter().map(|f| format!("\"{f}\"")).collect(); + let build_feats = if feats_str.is_empty() { + String::new() + } else { + format!("features = [{}]", feats_str.join(", ")) + }; format!( "\n[build-dependencies]\nmingling = {{ path = \"{mingling_path}\", {build_feats} }}\n" ) @@ -292,14 +291,10 @@ pub fn generate_main_rs(block: &CodeBlock) -> String { /// Generate build.rs for a build-time block /// -/// Default: `use mingling::builds::*;`, code wrapped in `fn main() { }`. +/// Default: code wrapped in `fn main() { }`. pub fn generate_build_rs(block: &CodeBlock) -> String { let mut output = String::from("#![allow(dead_code)]\n#![allow(unused)]\n"); - if !block.code.contains("use mingling::build::*;") { - output.push_str("#[allow(unused_imports)]\nuse mingling::build::*;\n\n"); - } - if block.has_main { output.push_str(&block.code); } else { diff --git a/CHANGELOG.md b/CHANGELOG.md index 969a3e2..7566451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -395,6 +395,67 @@ None _All internal call sites, examples, docs, and tests updated_ (e.g., `mingling_cli` completion handlers, `example-completion`, `example-enum-tag`, `GETTING-STARTED.md`, `docs/pages/advanced/1-completion.md`, `docs/_zh_CN/pages/advanced/1-completion.md`, and `mingling/src/example_docs.rs`). +7. **[`build`]** **[BREAKING]** Replaced the `build` / `builds` build-time feature system with compile-time macro-driven build steps. The `build` feature, `builds` feature, `build_advanced` preset, `build_full` preset, `mingling::build` module, and the entire `build.rs`-based workflow have been removed. Build steps (completion script generation and pathf type-mapping analysis) now run automatically as a side effect of `gen_program!()` expansion via new `build_comp!()` / `build_pathf!()` macros. + + ### What changed + + Previously, build-time functionality was enabled through the `build` feature (and preset groups `build_advanced` / `build_full`, plus the deprecated `builds` alias). Users needed a `[build-dependencies.mingling]` entry in `Cargo.toml` and a hand-written `build.rs` that called `mingling::build::build_comp_scripts(...)` (for completion scripts) and `mingling::build::analyze_and_build_type_mapping()` (for pathf). These functions were gated behind the `build` + `comp` / `build` + `pathf` feature combinations and read `OUT_DIR` to locate the output directory. + + Now, the build steps are integrated directly into macro expansion: + + - **`gen_program!()` automatically invokes `build_comp!()`** (when the `comp` feature is enabled) and **`build_pathf!()`** (when the `pathf` feature is enabled) at the very start of its expansion. These macros run the build logic as a compile-time side effect and expand to nothing. + - **`build_comp!()`** is a proc macro (re-exported as `mingling::macros::build_comp`) that generates completion scripts into `{target_directory}/mingling/`. It accepts an optional string literal for the binary name; without an argument it defaults to `CARGO_PKG_NAME`. On failure it emits a `compile_error!`. + - **`build_pathf!()`** is a proc macro (re-exported as `mingling::macros::build_pathf`) that runs the pathf type-mapping analysis, writing mapping files into `{target_directory}/mingling/{CARGO_PKG_NAME}/`. On failure it emits a `compile_error!`. + - **No `build.rs` is required anymore.** Build logic runs from proc-macro expansion, so no `[build-dependencies.mingling]` entry, no `build` feature, and no `build.rs` file are needed. + + **Removed API:** + + - **`build` feature** — Removed from `mingling/Cargo.toml` and `mingling_core/Cargo.toml`. The `build = ["mingling_core/build"]` feature mapping and the `mingling_core/build` feature have been deleted. + - **`builds` feature** — Removed (deprecated alias, mapped to `mingling_core/build`). + - **`build_advanced` / `build_full` preset features** — Removed from `mingling/Cargo.toml` feature groups. + - **`mingling::build` module** — Removed entirely from `mingling_core`: + - `mingling_core/src/build.rs` and the `mingling_core/src/build/` directory deleted. + - `mingling_core/src/docs/build.md` deleted. + - `mingling_core/src/lib.rs` no longer gates `pub mod build` behind the `build` feature. + - **Build functions** — Removed: `build_comp_scripts`, `build_comp_script`, `build_comp_script_to`, `build_comp_script_to_file`, `analyze_and_build_type_mapping`, `analyze_and_build_type_mapping_for`, `analyze`. + - **`MINGLING_BUILD` / `MINGLING_BUILDS` / `MINGLING_BUILD_ADVANCED` / `MINGLING_BUILD_FULL` feature constants** — Removed from `mingling/src/features.rs`. + - **`mingling_core` dependencies** — Removed `just_template` (comp) and `mingling_pathf` (pathf) from `mingling_core/Cargo.toml`; these moved to `mingling_macros` as optional dependencies gated behind the `comp` / `pathf` features. + - **`mingling_macros` feature wiring** — Changed `comp = []` to `comp = ["dep:just_template", "dep:mingling_pathf"]` and `pathf = []` to `pathf = ["dep:mingling_pathf"]`; `mingling` crate's `pathf` feature no longer forwards to `mingling_core/pathf`. + - **`mingling::build::pathf` error re-exports** — `mingling_core::error` no longer re-exports `mingling_pathf::error::*`. + + **New internal infrastructure:** + + - **`mingling_macros/src/build.rs`** — New module hosting `comp_build_impl` (behind `comp`) and `pathf_build_impl` (behind `pathf`), which parse the macro input and delegate to the build logic, converting errors into `compile_error!` token streams. + - **`mingling_macros/src/build/comp.rs`** — Moved from `mingling_core/src/build/comp.rs` (with the shell templates, which moved from `mingling_core/tmpls/comps/` to `mingling_macros/tmpls/comps/`). Contains a private copy of `ShellFlag` (since the macros crate cannot depend on `mingling_core`); the template files are identical. Scripts are written to `{target_directory}/mingling/` resolved via the new `mingling_pathf::build_output_dir()`. + - **`mingling_macros/src/build/pathf.rs`** — New module providing `output_dir()` (`{target_directory}/mingling/{CARGO_PKG_NAME}`) and `analyze_and_build_type_mapping()` delegating to `mingling_pathf`. + - **`mingling_pathf::build_output_dir()`** — New public function resolving `{target_directory}/mingling/` via `cargo metadata` (from `CARGO_MANIFEST_DIR`). + - **`mingling_pathf::target_directory()`** — New public function running `cargo metadata` (`no_deps`) from a crate directory and returning the target directory. + - **`MinglingPathfinderError::CargoMetadata(String)`** — New error variant added to `mingling_pathf`'s error enum. + - **`cargo_metadata` dependency** — Added to `mingling_pathf` (workspace, version `0.23.1`) and to the root workspace `Cargo.toml`. + + **`gen_program!()` changes** (`mingling_macros/src/func/gen_program.rs`): + - Emits `::mingling::macros::build_comp!();` at the start of the expansion when `comp` is enabled (and `::mingling::macros::build_pathf!();` when `pathf` is enabled). + - The pathf `use`-statement loading now runs the analysis inline via `crate::build::pathf::analyze_and_build_type_mapping()` (so the mapping exists when the `use` statements are read) and loads `type_using.rs` from `crate::build::pathf::output_dir()`. + - The `load_pathf_uses` function now reads from `{target_directory}/mingling/{CARGO_PKG_NAME}/type_using.rs` instead of `{OUT_DIR}/{CARGO_PKG_NAME}/type_using.rs`. + - The empty-uses `compile_error!` hint was reworded: it no longer mentions `build.rs` or the `build` feature; it now says the analyzer found no types and suggests ensuring the `pathf` feature is enabled and `gen_program!()` is called in a crate with a `src/` directory. + - `mingling_pathf::analyze_and_build_type_mapping` no longer emits `cargo:rerun-if-changed=src/` / `cargo:rerun-if-env-changed=...` directives (there is no build script for Cargo to track). + + **Migration guide:** + + - **Delete `build.rs`** (and the `[build-dependencies]` block in `Cargo.toml`). Completion scripts are generated automatically when the `comp` feature is enabled; pathf analysis and any `[build-dependencies.mingling]`). If a feature list references only these, delete the whole section. + - **If your binary name differs from the crate name**, call `build_comp!()` manually with the binary name: + ```rust + // Features: ["comp"] + mingling::macros::build_comp!("mybin"); + ``` + This can be placed at module scope (e.g., in `src/lib.rs` or `src/main.rs`) alongside `gen_program!()`. + - **Remove any `mingling::build::...` imports.** + - **Example/build artifacts**: The completion scripts are now written to `{target_directory}/mingling/` rather than `{target_directory}/release/` or the `OUT_DIR`-derived path. Any scripts that copied them from the release directory must be updated (e.g., `.run/src/bin/install-mling.sh` now copies from `.temp/target/mingling/mling_comp.$comp`, and `.run/src/bin/install-mling.ps1` from `.temp/target/mingling/mling_comp.ps1`). + - **`mingling_cli`**: `build.rs` no longer calls `analyze_and_build_type_mapping` / `build_comp_scripts`; `mingling_cli/src/lib.rs` now invokes `mingling::macros::build_comp!("mling")` to generate scripts for the `mling` binary. `StateInstallBuild` / `StateInstallCopy` gained a `mingling_dir` field (`{target}/mingling/`) and the install copy step reads completion scripts from `{target}/mingling/` instead of `{target}/release/`. + - **Tests/examples**: Removed the `builds` feature from `mingling_core/tests/test-all`, `mingling_core/tests/test-comp`, and all pathf/completion examples, and deleted the corresponding `build.rs` files and `[build-dependencies]` blocks. + + _Behavioral note:_ the runtime behavior of programs is unchanged — completion scripts and pathf type mappings are still produced, just from compile-time macro expansion instead of a separate `build.rs` step. The output directory changed from an `OUT_DIR`-derived path (effectively `{target}/<profile>` style) to a dedicated `{target_directory}/mingling/` directory resolved via `cargo metadata`, which is deterministic regardless of build profile. + --- ## Contents @@ -75,7 +75,7 @@ version = "0.2.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -94,6 +94,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -193,7 +226,7 @@ checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -226,7 +259,7 @@ checksum = "1471eb68722ecefeb71debdde2859e8725341f171d3f42b3a98a0862ad19416e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -264,7 +297,7 @@ checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", "toml 0.8.23", ] @@ -290,10 +323,8 @@ version = "0.5.0" dependencies = [ "env_logger", "just_fmt 0.2.0", - "just_template", "log", "might_be_async", - "mingling_pathf", "ron", "serde", "serde_json", @@ -307,18 +338,21 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt 0.2.0", "proc-macro2", - "syn", + "syn 2.0.118", ] [[package]] @@ -471,6 +505,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -497,7 +541,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -582,6 +626,17 @@ dependencies = [ ] [[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "temp-env" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -591,6 +646,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "tokio" version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -615,7 +690,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -39,6 +39,7 @@ arg-picker-macros = { path = "arg_picker_macros", default-features = false } just_fmt = "0.2.0" just_template = "0.2.0" +cargo_metadata = "0.23.1" might_be_async = "0.1.0" diff --git a/GETTING-STARTED.md b/GETTING-STARTED.md index 020e098..e4a706a 100644 --- a/GETTING-STARTED.md +++ b/GETTING-STARTED.md @@ -234,13 +234,9 @@ fn main() { } ``` -In your `build.rs`, generate the shell scripts: - -```rust -// BUILD TIME -// Features: ["comp", "build"] -mingling::build::build_comp_scripts(env!("CARGO_PKG_NAME")).unwrap(); -``` +The completion scripts are generated automatically: with the `comp` feature enabled, +`gen_program!()` invokes `build_comp!()` at compile time and writes the shell scripts +(named after `CARGO_PKG_NAME`) into `target/mingling/`. For enum-based completions, use `suggest_enum!`: diff --git a/docs/_zh_CN/pages/advanced/1-completion.md b/docs/_zh_CN/pages/advanced/1-completion.md index d70786e..290fab0 100644 --- a/docs/_zh_CN/pages/advanced/1-completion.md +++ b/docs/_zh_CN/pages/advanced/1-completion.md @@ -11,13 +11,6 @@ Mingling 的补全是**完全动态**的——没有静态的补全文件,而 # Cargo.toml [dependencies.mingling] features = ["comp"] - -[build-dependencies.mingling] -features = [ - "comp", - # 启用 `build` 特性以提供构建期支持 - "build" -] ``` ## 工作原理 @@ -72,8 +65,18 @@ suggest! { ## 生成补全脚本 -在 `build.rs` 中调用 `build_comp_scripts` 生成补全脚本(需要 `builds` + `comp` 特性)。 +开启 `comp` 特性后,`gen_program!()` 会在编译期自动调用 `build_comp!()`,生成以 `CARGO_PKG_NAME` 命名的补全脚本到 `target/mingling/`。 + +如果你的二进制名与 crate 名不同,可以手动调用 `build_comp!()` 并指定二进制名: +```rust +// Features: ["comp"] +@@@use mingling::macros::build_comp; +@@@fn example() { +build_comp!("mybin"); +@@@} +``` + 详见 [example-completion](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-completion)。 <p align="center" style="font-size: 0.85em; color: gray;"> diff --git a/docs/_zh_CN/pages/other/features.md b/docs/_zh_CN/pages/other/features.md index 5fa7c86..f8753e5 100644 --- a/docs/_zh_CN/pages/other/features.md +++ b/docs/_zh_CN/pages/other/features.md @@ -25,42 +25,6 @@ Mingling 提供了一系列**预设特性组**,方便用户按需组合启用 **定位:** 完整模式,启用 Mingling 的全部核心功能。在 `advanced` 的基础上额外包含 clap 集成、完整的结构化渲染器(含所有序列化格式)以及实验性的路径分析器,适合大型、功能全面的命令行应用。 -## `build_advanced` - -**启用特性:** `build`、`comp` - -**定位:** 构建期增强配置,用于在项目构建时生成补全脚本等构建辅助材料(`comp` 特性提供补全脚本生成能力)。 - -> [!NOTE] -> -> 此特性组为**构建依赖**专用,需配合 `advanced` 特性使用。请在 `Cargo.toml` 的 `[build-dependencies]` 中启用: - -```toml -[dependencies.mingling] -features = ["advanced"] - -[build-dependencies.mingling] -features = ["build_advanced"] -``` - -## `build_full` - -**启用特性:** `build`、`comp`、`pathf`、`dispatch_tree` - -**定位:** 完整的构建期配置,在 `build_advanced` 的基础上额外包含路径分析器(`pathf`)以自动解析类型模块路径,适合结构复杂、需要自动化构建期分析的项目。 - -> [!NOTE] -> -> 此特性组为**构建依赖**专用,需配合 `full` 特性使用。请在 `Cargo.toml` 的 `[build-dependencies]` 中启用: - -```toml -[dependencies.mingling] -features = ["full"] - -[build-dependencies.mingling] -features = ["build_full"] -``` - # 特性详解 ## 特性 `all_serde_fmt` @@ -91,23 +55,6 @@ async fn handle_state_foo(foo: StateFoo) -> Next { 详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-async-support) -## 特性 `builds` - -**介绍:** - -启用部分需要在 `build.rs` 使用的脚本,目前包含: - -1. `comp` 特性下的补全脚本生成: - -```rust -// BUILD TIME -// Features: ["builds", "comp"] -use mingling::build::build_comp_scripts; - -// 为 `myprogram` 生成补全脚本 -build_comp_scripts("myprogram").unwrap(); -``` - ## 特性 `clap` **介绍:** @@ -318,17 +265,10 @@ pub struct ErrorNotDir(PathBuf); # Cargo.toml [dependencies.mingling] features = ["pathf"] - -[build-dependencies.mingling] -features = ["builds", "pathf"] -``` - -```rust -// BUILD TIME -// Features: ["pathf"] -analyze_and_build_type_mapping().unwrap(); ``` +开启 `pathf` 特性后,`gen_program!()` 会在编译期自动调用 `build_pathf!()` 执行类型映射分析。 + 详见 [示例](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-pathfinder) ## 特性 `picker` diff --git a/docs/dev/pages/abouts/code-verify-system.md b/docs/dev/pages/abouts/code-verify-system.md index 929b337..20da045 100644 --- a/docs/dev/pages/abouts/code-verify-system.md +++ b/docs/dev/pages/abouts/code-verify-system.md @@ -125,8 +125,11 @@ Marks the block as a `build.rs` script instead of `src/main.rs`. The block code ```rust // BUILD TIME -// Features: ["builds", "pathf"] -analyze_and_build_type_mapping().unwrap(); +// Dependencies: +// serde = "1" +fn main() { + // build-time work, e.g. writing generated sources into OUT_DIR +} ``` ### `// Features: [...]` diff --git a/docs/example-pages/examples.json b/docs/example-pages/examples.json index 38f73cd..dd5b65b 100644 --- a/docs/example-pages/examples.json +++ b/docs/example-pages/examples.json @@ -69,13 +69,11 @@ "tags": [ "pathf", "dispatch_tree", - "extras", - "build.rs" + "extras" ], "files": [ "src/main.rs", "src/sub/mod.rs", - "build.rs", "Cargo.toml" ] }, @@ -87,13 +85,11 @@ "desc": "Combines the `pathf` feature with entry metadata. The metadata `DataType` and the entry `BindType` are defined inside a submodule, and `pathf` resolves them for `gen_program!()` at build time.\n", "tags": [ "pathf", - "metadata", - "build.rs" + "metadata" ], "files": [ "src/main.rs", "src/sub/mod.rs", - "build.rs", "Cargo.toml" ] }, @@ -124,7 +120,6 @@ ], "files": [ "src/main.rs", - "build.rs", "Cargo.toml" ] }, @@ -294,12 +289,10 @@ "desc": "Demonstrates the `pathf` feature, which automatically resolves type module paths at build time. Types can be defined in submodules without explicit `use` in the main module.\n", "tags": [ "pathf", - "build.rs", "architecture" ], "files": [ "Cargo.toml", - "build.rs", "src/main.rs", "src/sub/mod.rs" ] diff --git a/docs/pages/advanced/1-completion.md b/docs/pages/advanced/1-completion.md index 20bd59e..ca1f621 100644 --- a/docs/pages/advanced/1-completion.md +++ b/docs/pages/advanced/1-completion.md @@ -11,13 +11,6 @@ Mingling's completion is **fully dynamic** — no static completion files, sugge # Cargo.toml [dependencies.mingling] features = ["comp"] - -[build-dependencies.mingling] -features = [ - "comp", - # Enable `build` for build-time support - "build" -] ``` ## How it works @@ -72,8 +65,18 @@ suggest! { ## Generate completion scripts -Call `build_comp_scripts` in `build.rs` to generate completion scripts (requires `builds` + `comp` features). +When the `comp` feature is enabled, `gen_program!()` automatically invokes `build_comp!()` at compile time, which generates the completion scripts (named after `CARGO_PKG_NAME`) into `target/mingling/`. + +If your binary name differs from the crate name, call `build_comp!()` manually with the binary name: +```rust +// Features: ["comp"] +@@@use mingling::macros::build_comp; +@@@fn example() { +build_comp!("mybin"); +@@@} +``` + See [example-completion](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-completion). <p align="center" style="font-size: 0.85em; color: gray;"> diff --git a/docs/pages/other/features.md b/docs/pages/other/features.md index b2c0ea5..858e556 100644 --- a/docs/pages/other/features.md +++ b/docs/pages/other/features.md @@ -25,42 +25,6 @@ Mingling provides a set of **preset feature groups** that make it easy to enable **Positioning:** Full mode, enables all of Mingling's core functionality. In addition to `advanced`, it includes clap integration, the full structural renderer (with all serialization formats), and the experimental path analyzer. Suitable for large, feature-complete command-line applications. -## `build_advanced` - -**Enables features:** `build`, `comp` - -**Positioning:** Build-time enhanced configuration, used to generate build helpers such as completion scripts at build time (the `comp` feature provides completion script generation). - -> [!NOTE] -> -> This feature group is intended for **build dependencies** only and must be used alongside the `advanced` feature. Enable it in the `[build-dependencies]` section of `Cargo.toml`: - -```toml -[dependencies.mingling] -features = ["advanced"] - -[build-dependencies.mingling] -features = ["build_advanced"] -``` - -## `build_full` - -**Enables features:** `build`, `comp`, `pathf`, `dispatch_tree` - -**Positioning:** Full build-time configuration, extends `build_advanced` with the path analyzer (`pathf`) to automatically resolve type module paths, suitable for projects with complex structures that require automated build-time analysis. - -> [!NOTE] -> -> This feature group is intended for **build dependencies** only and must be used alongside the `full` feature. Enable it in the `[build-dependencies]` section of `Cargo.toml`: - -```toml -[dependencies.mingling] -features = ["full"] - -[build-dependencies.mingling] -features = ["build_full"] -``` - # Feature Details ## Feature `all_serde_fmt` @@ -91,23 +55,6 @@ async fn handle_state_foo(foo: StateFoo) -> Next { See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-async-support) -## Feature `builds` - -**Description:** - -Enables scripts needed for use in `build.rs`, currently including: - -1. Completion script generation under the `comp` feature: - -```rust -// BUILD TIME -// Features: ["builds", "comp"] -use mingling::build::build_comp_scripts; - -// Generate completion scripts for `myprogram` -build_comp_scripts("myprogram").unwrap(); -``` - ## Feature `clap` **Description:** @@ -318,17 +265,10 @@ When enabled, types can be defined in any submodule, and `gen_program!()` can au # Cargo.toml [dependencies.mingling] features = ["pathf"] - -[build-dependencies.mingling] -features = ["builds", "pathf"] -``` - -```rust -// BUILD TIME -// Features: ["pathf"] -analyze_and_build_type_mapping().unwrap(); ``` +With the `pathf` feature enabled, `gen_program!()` automatically invokes `build_pathf!()` at compile time to run the type mapping analysis. + See [example](https://mingling-rs.github.io/mingling/docs/example-viewer.html?name=example-pathfinder) ## Feature `picker` diff --git a/examples/example-combine-pathf-dispatch-tree/Cargo.lock b/examples/example-combine-pathf-dispatch-tree/Cargo.lock index 9fdbf4f..3603db8 100644 --- a/examples/example-combine-pathf-dispatch-tree/Cargo.lock +++ b/examples/example-combine-pathf-dispatch-tree/Cargo.lock @@ -3,6 +3,39 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -32,6 +65,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,7 +108,6 @@ version = "0.5.0" dependencies = [ "just_fmt", "might_be_async", - "mingling_pathf", ] [[package]] @@ -77,6 +115,7 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.118", @@ -86,6 +125,7 @@ dependencies = [ name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt", "proc-macro2", "syn 2.0.118", @@ -110,12 +150,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -139,6 +190,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,6 +234,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/examples/example-combine-pathf-dispatch-tree/Cargo.toml b/examples/example-combine-pathf-dispatch-tree/Cargo.toml index 2c866f7..6fcfc48 100644 --- a/examples/example-combine-pathf-dispatch-tree/Cargo.toml +++ b/examples/example-combine-pathf-dispatch-tree/Cargo.toml @@ -10,17 +10,4 @@ mingling = { path = "../../mingling", features = [ "pathf", ] } -[build-dependencies] -mingling = { path = "../../mingling", features = [ - "builds", - - # --------- IMPORTANT --------- - # To use pathf under dispatch_tree - # **must** enable the `dispatch_tree` - # feature in build dependencies - "dispatch_tree", - "pathf", - # --------- IMPORTANT --------- -] } - [workspace] diff --git a/examples/example-combine-pathf-dispatch-tree/build.rs b/examples/example-combine-pathf-dispatch-tree/build.rs deleted file mode 100644 index d909431..0000000 --- a/examples/example-combine-pathf-dispatch-tree/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - mingling::build::analyze_and_build_type_mapping().unwrap(); -} diff --git a/examples/example-combine-pathf-dispatch-tree/page.toml b/examples/example-combine-pathf-dispatch-tree/page.toml index 88557af..b4e64e9 100644 --- a/examples/example-combine-pathf-dispatch-tree/page.toml +++ b/examples/example-combine-pathf-dispatch-tree/page.toml @@ -6,5 +6,5 @@ category = "advanced" desc = """ Demonstrates combining the `pathf` and `dispatch_tree` features. Types are defined in submodules and automatically resolved. Requires `dispatch_tree` in both `[dependencies]` and `[build-dependencies]`. """ -tags = ["pathf", "dispatch_tree", "extras", "build.rs"] -files = ["src/main.rs", "src/sub/mod.rs", "build.rs", "Cargo.toml"] +tags = ["pathf", "dispatch_tree", "extras"] +files = ["src/main.rs", "src/sub/mod.rs", "Cargo.toml"] diff --git a/examples/example-combine-pathf-dispatch-tree/src/main.rs b/examples/example-combine-pathf-dispatch-tree/src/main.rs index 75888ee..a93e7ae 100644 --- a/examples/example-combine-pathf-dispatch-tree/src/main.rs +++ b/examples/example-combine-pathf-dispatch-tree/src/main.rs @@ -4,11 +4,13 @@ //! > Types are defined in a submodule (`sub`), and `gen_program!()` resolves //! > them automatically via pathf without explicit `use` imports. //! > -//! > **Important**: `dispatch_tree` must be enabled in BOTH `[dependencies]` -//! > AND `[build-dependencies]` so that pathf's builder can detect -//! > `__internal_dispatcher_*` types needed by the dispatch tree. +//! > **Important**: `dispatch_tree` must be enabled so that pathf's builder can +//! > detect `__internal_dispatcher_*` types needed by the dispatch tree. //! > //! > Also requires `extras` for the implicit `dispatcher!("hello")` form. +//! > +//! > With the `pathf` feature, `gen_program!()` automatically invokes +//! > `build_pathf!()` at compile time — no `build.rs` needed. //! //! Run: //! ```bash diff --git a/examples/example-combine-pathf-metadata/Cargo.lock b/examples/example-combine-pathf-metadata/Cargo.lock index 0e1782e..304810b 100644 --- a/examples/example-combine-pathf-metadata/Cargo.lock +++ b/examples/example-combine-pathf-metadata/Cargo.lock @@ -3,6 +3,39 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -32,6 +65,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,7 +108,6 @@ version = "0.5.0" dependencies = [ "just_fmt", "might_be_async", - "mingling_pathf", ] [[package]] @@ -77,6 +115,7 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.119", @@ -86,6 +125,7 @@ dependencies = [ name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt", "proc-macro2", "syn 2.0.119", @@ -110,12 +150,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -139,6 +190,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,6 +234,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/examples/example-combine-pathf-metadata/Cargo.toml b/examples/example-combine-pathf-metadata/Cargo.toml index fd14c74..26ed74a 100644 --- a/examples/example-combine-pathf-metadata/Cargo.toml +++ b/examples/example-combine-pathf-metadata/Cargo.toml @@ -12,13 +12,4 @@ features = [ "pathf", ] -[build-dependencies.mingling] -path = "../../mingling" -features = [ - # Enable the `build` feature for build-time support - "build", - # `pathf` must also be enabled in build-dependencies - "pathf", -] - [workspace] diff --git a/examples/example-combine-pathf-metadata/build.rs b/examples/example-combine-pathf-metadata/build.rs deleted file mode 100644 index d909431..0000000 --- a/examples/example-combine-pathf-metadata/build.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - mingling::build::analyze_and_build_type_mapping().unwrap(); -} diff --git a/examples/example-combine-pathf-metadata/page.toml b/examples/example-combine-pathf-metadata/page.toml index 76c1700..7e9b48c 100644 --- a/examples/example-combine-pathf-metadata/page.toml +++ b/examples/example-combine-pathf-metadata/page.toml @@ -6,5 +6,5 @@ category = "advanced" desc = """ Combines the `pathf` feature with entry metadata. The metadata `DataType` and the entry `BindType` are defined inside a submodule, and `pathf` resolves them for `gen_program!()` at build time. """ -tags = ["pathf", "metadata", "build.rs"] -files = ["src/main.rs", "src/sub/mod.rs", "build.rs", "Cargo.toml"] +tags = ["pathf", "metadata"] +files = ["src/main.rs", "src/sub/mod.rs", "Cargo.toml"] diff --git a/examples/example-completion/Cargo.lock b/examples/example-completion/Cargo.lock index d4b2f33..d98661c 100644 --- a/examples/example-completion/Cargo.lock +++ b/examples/example-completion/Cargo.lock @@ -20,6 +20,39 @@ dependencies = [ ] [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -49,6 +82,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -113,7 +152,6 @@ name = "mingling_core" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", - "just_template", "might_be_async", ] @@ -122,12 +160,24 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.118", ] [[package]] +name = "mingling_pathf" +version = "0.5.0" +dependencies = [ + "cargo_metadata", + "just_fmt 0.2.0", + "proc-macro2", + "syn 2.0.118", +] + +[[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -146,12 +196,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -175,6 +236,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -206,6 +280,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -260,3 +354,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/examples/example-completion/Cargo.toml b/examples/example-completion/Cargo.toml index 9884f4e..59b6902 100644 --- a/examples/example-completion/Cargo.toml +++ b/examples/example-completion/Cargo.toml @@ -12,16 +12,4 @@ features = [ "picker", ] -[build-dependencies.mingling] -path = "../../mingling" - -features = [ - # Enable `comp` features - "comp", - - # If you want to build completion scripts, - # enable `build` features - "build", -] - [workspace] diff --git a/examples/example-completion/build.rs b/examples/example-completion/build.rs deleted file mode 100644 index e1ffba1..0000000 --- a/examples/example-completion/build.rs +++ /dev/null @@ -1,14 +0,0 @@ -fn main() { - build_scripts(); -} - -/// Generate completion scripts -fn build_scripts() { - // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name. - // If your binary name differs from the crate name, specify it explicitly. - mingling::build::build_comp_scripts( - // Your binary name: - env!("CARGO_PKG_NAME"), - ) - .unwrap(); -} diff --git a/examples/example-completion/page.toml b/examples/example-completion/page.toml index adccd86..4336513 100644 --- a/examples/example-completion/page.toml +++ b/examples/example-completion/page.toml @@ -7,4 +7,4 @@ desc = """ Demonstrates how to implement dynamic shell completion with `#[completion]` and generate scripts for bash, zsh, fish, and pwsh. """ tags = ["comp"] -files = ["src/main.rs", "build.rs", "Cargo.toml"] +files = ["src/main.rs", "Cargo.toml"] diff --git a/examples/example-completion/src/main.rs b/examples/example-completion/src/main.rs index 389cf74..385387b 100644 --- a/examples/example-completion/src/main.rs +++ b/examples/example-completion/src/main.rs @@ -7,30 +7,15 @@ //! To make your completions work, you need to generate a completion script using Mingling's tools //! //! 1. Enable features -//! You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]` +//! Enable the `comp` feature for `mingling` in `[dependencies]` //! -//! 2. Write `build.rs` -//! Write the following in `build.rs` -//! -//! ```rust,ignore -//! fn main() { -//! build_scripts(); -//! } -//! -//! /// Generate completion scripts -//! fn build_scripts() { -//! // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name. -//! // If your binary name differs from the crate name, specify it explicitly. -//! mingling::build::build_comp_scripts( -//! // Your binary name: -//! env!("CARGO_PKG_NAME"), -//! ) -//! .unwrap(); -//! } -//! ``` +//! 2. Generate completion scripts +//! When the `comp` feature is enabled, `gen_program!()` automatically invokes +//! `build_comp!()` at compile time, which generates the completion scripts +//! (named after `CARGO_PKG_NAME`) into `target/mingling/`. //! //! 3. Verify -//! Build your project with `cargo build --release`. The completion scripts will be generated in `target/release/` +//! Build your project with `cargo build`. The completion scripts will be generated in `target/mingling/` //! //! Execute the script or have it be automatically sourced by your Shell //! diff --git a/examples/example-enum-tag/Cargo.lock b/examples/example-enum-tag/Cargo.lock index 492d708..9b97008 100644 --- a/examples/example-enum-tag/Cargo.lock +++ b/examples/example-enum-tag/Cargo.lock @@ -20,6 +20,39 @@ dependencies = [ ] [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -49,6 +82,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -113,7 +152,6 @@ name = "mingling_core" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", - "just_template", "might_be_async", ] @@ -122,12 +160,24 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.118", ] [[package]] +name = "mingling_pathf" +version = "0.5.0" +dependencies = [ + "cargo_metadata", + "just_fmt 0.2.0", + "proc-macro2", + "syn 2.0.118", +] + +[[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -146,12 +196,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -175,6 +236,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -206,6 +280,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -260,3 +354,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/examples/example-pathfinder/Cargo.lock b/examples/example-pathfinder/Cargo.lock index b93e443..155e762 100644 --- a/examples/example-pathfinder/Cargo.lock +++ b/examples/example-pathfinder/Cargo.lock @@ -3,6 +3,39 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -32,6 +65,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,7 +108,6 @@ version = "0.5.0" dependencies = [ "just_fmt", "might_be_async", - "mingling_pathf", ] [[package]] @@ -77,6 +115,7 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.118", @@ -86,6 +125,7 @@ dependencies = [ name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt", "proc-macro2", "syn 2.0.118", @@ -110,12 +150,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -139,6 +190,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -170,6 +234,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -224,3 +308,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/examples/example-pathfinder/Cargo.toml b/examples/example-pathfinder/Cargo.toml index bc41bd2..00fc2a1 100644 --- a/examples/example-pathfinder/Cargo.toml +++ b/examples/example-pathfinder/Cargo.toml @@ -11,15 +11,4 @@ features = [ "pathf", ] -[build-dependencies.mingling] -path = "../../mingling" - -features = [ - # Enable `pathf` features - "pathf", - - # Enable the `build` feature for build-time support - "build", -] - [workspace] diff --git a/examples/example-pathfinder/build.rs b/examples/example-pathfinder/build.rs deleted file mode 100644 index e96f978..0000000 --- a/examples/example-pathfinder/build.rs +++ /dev/null @@ -1,10 +0,0 @@ -use mingling::build::analyze_and_build_type_mapping; - -fn main() { - // --------- IMPORTANT --------- - // Use this method in build.rs, - // to analyze the project structure at build time, - // and automatically introduce members from other modules into gen_program!() - analyze_and_build_type_mapping().unwrap(); - // --------- IMPORTANT --------- -} diff --git a/examples/example-pathfinder/page.toml b/examples/example-pathfinder/page.toml index 54f4118..6cf42e3 100644 --- a/examples/example-pathfinder/page.toml +++ b/examples/example-pathfinder/page.toml @@ -6,5 +6,5 @@ category = "advanced" desc = """ Demonstrates the `pathf` feature, which automatically resolves type module paths at build time. Types can be defined in submodules without explicit `use` in the main module. """ -tags = ["pathf", "build.rs", "architecture"] -files = [ "Cargo.toml", "build.rs", "src/main.rs", "src/sub/mod.rs"] +tags = ["pathf", "architecture"] +files = [ "Cargo.toml", "src/main.rs", "src/sub/mod.rs"] diff --git a/mingling/Cargo.toml b/mingling/Cargo.toml index 6130b1b..f1439af 100644 --- a/mingling/Cargo.toml +++ b/mingling/Cargo.toml @@ -25,7 +25,6 @@ features = [ "docs_rs", "core", "macros", - "builds", "structural_renderer", "repl", "comp", @@ -40,8 +39,6 @@ features = [ mini = ["extras", "picker"] advanced = ["extras", "picker", "repl", "comp", "dispatch_tree", "structural_renderer"] full = ["extras", "picker", "repl", "clap", "comp", "dispatch_tree", "structural_renderer_full", "pathf"] -build_advanced = ["build", "comp"] -build_full = ["build", "comp", "pathf", "dispatch_tree"] # Core core = ["dep:mingling_core", "mingling_core/default"] @@ -52,7 +49,6 @@ nightly = ["mingling_core/nightly", "mingling_macros/nightly"] debug = ["mingling_core/debug"] async = ["mingling_core/async", "mingling_macros/async"] default = ["core", "macros"] -build = ["mingling_core/build"] # - Section only shown in docs.rs docs_rs = [] @@ -62,7 +58,7 @@ dispatch_tree = ["mingling_macros/dispatch_tree"] repl = ["mingling_core/repl", "mingling_macros/repl"] comp = ["mingling_core/comp", "mingling_macros/comp"] picker = ["mingling_core/picker", "dep:arg-picker", "arg-picker/mingling_support"] -pathf = ["mingling_core/pathf", "mingling_macros/pathf"] +pathf = ["mingling_macros/pathf"] structural_renderer = [ "mingling_core/structural_renderer", @@ -101,7 +97,6 @@ extras = ["mingling_macros/extras"] # - LEGACY - # These are old names, will be Breaking Change in the future -builds = ["mingling_core/build"] extra_macros = ["mingling_macros/extras"] [dependencies] diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs index 2b1d21e..c9955b5 100644 --- a/mingling/src/example_docs.rs +++ b/mingling/src/example_docs.rs @@ -595,11 +595,13 @@ pub mod example_clap_binding {} /// > Types are defined in a submodule (`sub`), and `gen_program!()` resolves /// > them automatically via pathf without explicit `use` imports. /// > -/// > **Important**: `dispatch_tree` must be enabled in BOTH `[dependencies]` -/// > AND `[build-dependencies]` so that pathf's builder can detect -/// > `__internal_dispatcher_*` types needed by the dispatch tree. +/// > **Important**: `dispatch_tree` must be enabled so that pathf's builder can +/// > detect `__internal_dispatcher_*` types needed by the dispatch tree. /// > /// > Also requires `extras` for the implicit `dispatcher!("hello")` form. +/// > +/// > With the `pathf` feature, `gen_program!()` automatically invokes +/// > `build_pathf!()` at compile time — no `build.rs` needed. /// /// Run: /// ```bash @@ -625,19 +627,6 @@ pub mod example_clap_binding {} /// "pathf", /// ] } /// -/// [build-dependencies] -/// mingling = { path = "../../mingling", features = [ -/// "builds", -/// -/// # --------- IMPORTANT --------- -/// # To use pathf under dispatch_tree -/// # **must** enable the `dispatch_tree` -/// # feature in build dependencies -/// "dispatch_tree", -/// "pathf", -/// # --------- IMPORTANT --------- -/// ] } -/// /// [workspace] /// ``` /// @@ -691,15 +680,6 @@ pub mod example_combine_pathf_dispatch_tree {} /// "pathf", /// ] /// -/// [build-dependencies.mingling] -/// path = "../../mingling" -/// features = [ -/// # Enable the `build` feature for build-time support -/// "build", -/// # `pathf` must also be enabled in build-dependencies -/// "pathf", -/// ] -/// /// [workspace] /// ``` /// @@ -811,30 +791,15 @@ pub mod example_command_macro {} /// To make your completions work, you need to generate a completion script using Mingling's tools /// /// 1. Enable features -/// You need to enable the `build` and `comp` features for `mingling` in `[build-dependencies]` -/// -/// 2. Write `build.rs` -/// Write the following in `build.rs` -/// -/// ```rust,ignore -/// fn main() { -/// build_scripts(); -/// } -/// -/// /// Generate completion scripts -/// fn build_scripts() { -/// // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name. -/// // If your binary name differs from the crate name, specify it explicitly. -/// mingling::build::build_comp_scripts( -/// // Your binary name: -/// env!("CARGO_PKG_NAME"), -/// ) -/// .unwrap(); -/// } -/// ``` +/// Enable the `comp` feature for `mingling` in `[dependencies]` +/// +/// 2. Generate completion scripts +/// When the `comp` feature is enabled, `gen_program!()` automatically invokes +/// `build_comp!()` at compile time, which generates the completion scripts +/// (named after `CARGO_PKG_NAME`) into `target/mingling/`. /// /// 3. Verify -/// Build your project with `cargo build --release`. The completion scripts will be generated in `target/release/` +/// Build your project with `cargo build`. The completion scripts will be generated in `target/mingling/` /// /// Execute the script or have it be automatically sourced by your Shell /// @@ -864,18 +829,6 @@ pub mod example_command_macro {} /// "picker", /// ] /// -/// [build-dependencies.mingling] -/// path = "../../mingling" -/// -/// features = [ -/// # Enable `comp` features -/// "comp", -/// -/// # If you want to build completion scripts, -/// # enable `build` features -/// "build", -/// ] -/// /// [workspace] /// ``` /// @@ -2104,17 +2057,6 @@ pub mod example_panic_unwind {} /// "pathf", /// ] /// -/// [build-dependencies.mingling] -/// path = "../../mingling" -/// -/// features = [ -/// # Enable `pathf` features -/// "pathf", -/// -/// # Enable the `build` feature for build-time support -/// "build", -/// ] -/// /// [workspace] /// ``` /// diff --git a/mingling/src/features.rs b/mingling/src/features.rs index 9445328..777c3fb 100644 --- a/mingling/src/features.rs +++ b/mingling/src/features.rs @@ -31,50 +31,6 @@ pub const MINGLING_ASYNC: bool = false; #[cfg(feature = "async")] #[allow(unused)] pub const MINGLING_ASYNC: bool = true; -/// Whether the `build` feature is enabled -/// Current: `disabled` -#[cfg(not(feature = "build"))] -#[allow(unused)] -pub const MINGLING_BUILD: bool = false; - -/// Whether the `build` feature is enabled -/// Current: `enabled` -#[cfg(feature = "build")] -#[allow(unused)] -pub const MINGLING_BUILD: bool = true; -/// Whether the `build_advanced` feature is enabled -/// Current: `disabled` -#[cfg(not(feature = "build_advanced"))] -#[allow(unused)] -pub const MINGLING_BUILD_ADVANCED: bool = false; - -/// Whether the `build_advanced` feature is enabled -/// Current: `enabled` -#[cfg(feature = "build_advanced")] -#[allow(unused)] -pub const MINGLING_BUILD_ADVANCED: bool = true; -/// Whether the `build_full` feature is enabled -/// Current: `disabled` -#[cfg(not(feature = "build_full"))] -#[allow(unused)] -pub const MINGLING_BUILD_FULL: bool = false; - -/// Whether the `build_full` feature is enabled -/// Current: `enabled` -#[cfg(feature = "build_full")] -#[allow(unused)] -pub const MINGLING_BUILD_FULL: bool = true; -/// Whether the `builds` feature is enabled -/// Current: `disabled` -#[cfg(not(feature = "builds"))] -#[allow(unused)] -pub const MINGLING_BUILDS: bool = false; - -/// Whether the `builds` feature is enabled -/// Current: `enabled` -#[cfg(feature = "builds")] -#[allow(unused)] -pub const MINGLING_BUILDS: bool = true; /// Whether the `clap` feature is enabled /// Current: `disabled` #[cfg(not(feature = "clap"))] diff --git a/mingling/src/lib.rs b/mingling/src/lib.rs index 55240e5..45c8ec3 100644 --- a/mingling/src/lib.rs +++ b/mingling/src/lib.rs @@ -64,6 +64,10 @@ pub mod macros { #[cfg(feature = "picker")] pub use arg_picker::macros::*; pub use mingling_macros::buffer; + #[cfg(feature = "comp")] + pub use mingling_macros::build_comp; + #[cfg(feature = "pathf")] + pub use mingling_macros::build_pathf; pub use mingling_macros::chain; #[cfg(feature = "extras")] pub use mingling_macros::command; diff --git a/mingling_cli/Cargo.lock b/mingling_cli/Cargo.lock index c738a0e..aab6b82 100644 --- a/mingling_cli/Cargo.lock +++ b/mingling_cli/Cargo.lock @@ -95,9 +95,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "camino" -version = "1.2.4" +version = "1.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2d30e4173c4026932d51d31d6b0613b1fd3014bf3f9f8943d4ba139c437ba0" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" dependencies = [ "serde_core", ] @@ -746,15 +746,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.187" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7743783ea728ef5c31194c6590797eed286449b4a4e87d626d8a51f0a94e732" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libredox" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa" +checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" dependencies = [ "libc", ] @@ -849,9 +849,7 @@ name = "mingling_core" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", - "just_template", "might_be_async", - "mingling_pathf", ] [[package]] @@ -859,6 +857,8 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.119", @@ -868,6 +868,7 @@ dependencies = [ name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt 0.2.0", "proc-macro2", "syn 2.0.119", @@ -1402,18 +1403,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09a43598840e33d5b0331f38c5e30d13bb11c11210a4b58f0d9b18a5a5eefcd9" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.19" +version = "2.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43cbfe0cf76104d42a574802844187e84a305e531ed54455f11fbde0f10541cd" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" dependencies = [ "proc-macro2", "quote", @@ -1464,13 +1465,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.2", ] [[package]] diff --git a/mingling_cli/Cargo.toml b/mingling_cli/Cargo.toml index dfc686d..19b4c1b 100644 --- a/mingling_cli/Cargo.toml +++ b/mingling_cli/Cargo.toml @@ -30,15 +30,6 @@ features = [ "comp", ] -[build-dependencies.mingling] -path = "../mingling" -features = [ - "build", - "pathf", - "dispatch_tree", - "comp" -] - [dependencies] # Project analyze diff --git a/mingling_cli/build.rs b/mingling_cli/build.rs index 0dc0b28..4df33d0 100644 --- a/mingling_cli/build.rs +++ b/mingling_cli/build.rs @@ -1,14 +1,6 @@ -use mingling::build::{analyze_and_build_type_mapping, build_comp_scripts}; - pub mod pre; fn main() { - // Perform path analysis and build type mapping table - analyze_and_build_type_mapping().ok(); - - // Generate Mingling CLI Completion Scripts - build_comp_scripts("mling").unwrap(); - // Generate lint registry pre::gen_mod_file().unwrap(); pre::gen_lint_registry().unwrap(); diff --git a/mingling_cli/src/lib.rs b/mingling_cli/src/lib.rs index d5a5b22..0b93f08 100644 --- a/mingling_cli/src/lib.rs +++ b/mingling_cli/src/lib.rs @@ -24,6 +24,10 @@ pub mod proj_mgr; pub mod updater; pub mod utils; +// The `comp` feature makes `gen_program!()` generate completion scripts named after +// the crate (`mingling-cli_comp.*`). Generate an additional set for the `mling` binary. +mingling::macros::build_comp!("mling"); + #[help] pub fn help_global(_: EntryFallback) -> String { format!("{}\n", include_str!("../help/help.txt").parse_color_code()) diff --git a/mingling_cli/src/pkg_mgr/cmd_install.rs b/mingling_cli/src/pkg_mgr/cmd_install.rs index c7dcaef..0b552a6 100644 --- a/mingling_cli/src/pkg_mgr/cmd_install.rs +++ b/mingling_cli/src/pkg_mgr/cmd_install.rs @@ -34,6 +34,9 @@ pub struct StateInstallBuild { pub workspace_root: PathBuf, pub install_dir: PathBuf, pub release_dir: PathBuf, + /// Directory holding Mingling's compile-time build outputs + /// (`{target_directory}/mingling/`), e.g. the completion scripts. + pub mingling_dir: PathBuf, pub exe_suffix: &'static str, pub enable: bool, } @@ -43,6 +46,9 @@ pub struct StateInstallBuild { pub struct StateInstallCopy { pub install_dir: PathBuf, pub release_dir: PathBuf, + /// Directory holding Mingling's compile-time build outputs + /// (`{target_directory}/mingling/`), e.g. the completion scripts. + pub mingling_dir: PathBuf, pub exe_suffix: &'static str, pub installed: Vec<PathBuf>, pub enable: bool, @@ -95,6 +101,10 @@ pub fn install( .target_directory .join("release") .into_std_path_buf(), + mingling_dir: metadata + .target_directory + .join("mingling") + .into_std_path_buf(), exe_suffix: env::consts::EXE_SUFFIX, enable: enable.bool(), } @@ -117,6 +127,7 @@ pub fn handle_state_install_build(state: StateInstallBuild) -> Next { StateInstallCopy { install_dir: state.install_dir, release_dir: state.release_dir, + mingling_dir: state.mingling_dir, exe_suffix: state.exe_suffix, installed: vec![], enable: state.enable, @@ -159,13 +170,13 @@ pub fn handle_state_install_copy( } } - // Completion scripts are generated into the build profile directory - // (OUT_DIR/../../../), copy every one whose name contains `_comp`, - // regardless of its suffix - for entry in fs::read_dir(&state.release_dir).map_err(|e| { + // Completion scripts are generated into `{target_directory}/mingling/` at + // compile time (via `build_comp!()`); copy every one whose name contains + // `_comp`, regardless of its suffix. + for entry in fs::read_dir(&state.mingling_dir).map_err(|e| { io::Error::new( e.kind(), - format!("failed to read {}: {e}", state.release_dir.display()), + format!("failed to read {}: {e}", state.mingling_dir.display()), ) })? { let entry = entry.map_err(|e| { diff --git a/mingling_core/Cargo.toml b/mingling_core/Cargo.toml index aecf476..989abe4 100644 --- a/mingling_core/Cargo.toml +++ b/mingling_core/Cargo.toml @@ -14,7 +14,6 @@ categories = ["command-line-interface"] nightly = [] default = [] async = [] -build = [] picker = [] structural_renderer = ["dep:serde"] @@ -26,18 +25,12 @@ toml_serde_fmt = ["dep:toml"] repl = [] clap = [] -comp = ["dep:just_template"] +comp = [] debug = ["dep:log", "dep:env_logger"] -pathf = ["dep:mingling_pathf"] [dependencies] -mingling_pathf = { workspace = true, optional = true } - just_fmt.workspace = true -# comp -just_template = { workspace = true, optional = true } - # structural_renderer serde = { workspace = true, optional = true } ron = { workspace = true, optional = true } diff --git a/mingling_core/src/build.rs b/mingling_core/src/build.rs deleted file mode 100644 index 213d529..0000000 --- a/mingling_core/src/build.rs +++ /dev/null @@ -1,28 +0,0 @@ -#[doc(hidden)] -#[cfg(feature = "comp")] -mod comp; - -#[cfg(feature = "comp")] -mod comp_re_export { - pub use super::comp::build_comp_script; - pub use super::comp::build_comp_script_to; - pub use super::comp::build_comp_script_to_file; - pub use super::comp::build_comp_scripts; -} - -#[cfg(feature = "comp")] -pub use comp_re_export::*; - -#[doc(hidden)] -#[cfg(feature = "pathf")] -mod pathf; - -#[cfg(feature = "pathf")] -mod pathf_re_export { - pub use super::pathf::analyze; - pub use super::pathf::analyze_and_build_type_mapping; - pub use super::pathf::analyze_and_build_type_mapping_for; -} - -#[cfg(feature = "pathf")] -pub use pathf_re_export::*; diff --git a/mingling_core/src/build/pathf.rs b/mingling_core/src/build/pathf.rs deleted file mode 100644 index 4b8af1b..0000000 --- a/mingling_core/src/build/pathf.rs +++ /dev/null @@ -1,98 +0,0 @@ -#![allow(unused_imports)] - -pub use mingling_pathf::module_pathf::*; -pub use mingling_pathf::pattern_analyzer::*; -pub use mingling_pathf::patterns::*; - -use std::path::Path; - -/// Analyzes and builds a type mapping for a specific crate. -/// -/// Accepts `crate_dir` and `output_dir`, and invokes `pathf` to build the type mapping. -/// -/// # Arguments -/// -/// - `crate_dir`: Root directory of the crate's source code to analyze (usually `CARGO_MANIFEST_DIR`). -/// - `output_dir`: Output directory for generated artifacts (type mapping data). -/// -/// # Returns -/// -/// - On success: returns `Ok(())`; -/// - On failure: returns the corresponding `MinglingPathfinderError`. -/// -/// # Example -/// -/// ``` -/// # #[cfg(all(feature = "build", feature = "pathf"))] { -/// use mingling_core::build::analyze_and_build_type_mapping_for; -/// use std::path::Path; -/// -/// let crate_dir = Path::new("."); -/// let output_dir = Path::new(".temp/target/out"); -/// analyze_and_build_type_mapping_for(crate_dir, output_dir).expect("analysis failed"); -/// # } -/// ``` -pub fn analyze_and_build_type_mapping_for( - crate_dir: &Path, - output_dir: &Path, -) -> Result<(), crate::error::MinglingPathfinderError> { - mingling_pathf::analyze_and_build_type_mapping_for(crate_dir, output_dir) -} - -/// # Analyzes and builds a type mapping -/// -/// This function reads the current crate directory (`CARGO_PKG_NAME`) and output directory (`OUT_DIR`) -/// from environment variables, automatically combines them into the target output path, and invokes -/// the underlying analysis logic. Suitable for use in `build.rs`. -/// -/// It also sends the `cargo:rerun-if-changed=src/` directive to Cargo so that a rebuild is -/// automatically triggered when source code changes. -/// -/// # Prerequisites -/// -/// This function depends on the following environment variables, which are typically set -/// automatically during a Cargo build: -/// -/// - `CARGO_PKG_NAME`: Name of the current crate. -/// - `OUT_DIR`: Build output directory provided by Cargo. -/// -/// If these variables are missing, a corresponding [`MinglingPathfinderError`](crate::error::MinglingPathfinderError) -/// is returned. -/// -/// # Returns -/// -/// Returns `Ok(())` on success; returns a corresponding -/// [`MinglingPathfinderError`](crate::error::MinglingPathfinderError) on failure. -/// -/// # Example -/// -/// ``` -/// # #[cfg(all(feature = "build", feature = "pathf"))] { -/// use mingling_core::build::analyze_and_build_type_mapping; -/// -/// fn main() { -/// analyze_and_build_type_mapping().expect("failed to build type mapping"); -/// } -/// # } -/// ``` - -pub fn analyze_and_build_type_mapping() -> Result<(), crate::error::MinglingPathfinderError> { - let crate_dir = - std::env::current_dir().map_err(crate::error::MinglingPathfinderError::IoError)?; - let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| { - crate::error::MinglingPathfinderError::IoError(std::io::Error::new( - std::io::ErrorKind::NotFound, - "CARGO_PKG_NAME not set", - )) - })?; - let out_dir = std::env::var("OUT_DIR").map_err(|_| { - crate::error::MinglingPathfinderError::IoError(std::io::Error::new( - std::io::ErrorKind::NotFound, - "OUT_DIR not set", - )) - })?; - let output_dir = Path::new(&out_dir).join(&crate_name); - mingling_pathf::analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?; - println!("cargo:rerun-if-changed=src/"); - Ok(()) -} diff --git a/mingling_core/src/docs/build.md b/mingling_core/src/docs/build.md deleted file mode 100644 index 6f9285a..0000000 --- a/mingling_core/src/docs/build.md +++ /dev/null @@ -1,57 +0,0 @@ -Provide Mingling's build script module for build-time behavior of specific features in `build.rs`. - -To use it, add a dependency on mingling under `[build-dependencies]` in `Cargo.toml`, and enable the relevant features: - -## Build-Time Related Features - -| Name | Purpose | -| ---------------- | ------------------------------------------------------------------------------------------------- | -| `build` | Master switch for build-time features | -| `build_advanced` | Master switch for build-time features, paired with the `advanced` feature | -| `build_full` | Master switch for build-time features, paired with the `full` feature | -| `comp` | Completion script builder; both sides must enable it, generates cross-platform completion scripts | -| `pathf` | Type path analyzer; both sides must enable it, generates type mapping tables | -| `dispatch_tree` | Compile-time dispatch tree; when `pathf` is a build-time dependency, | -| | and `dispatch_tree` (included in `advanced` or `full`) is enabled, both sides should enable it | - -```toml -# Cargo.toml -[dependencies.mingling] -features = [ - "advanced", # Enable `advanced` if using it -] - -[build-dependencies.mingling] -features = [ - "build_advanced" # This side should enable `build_advanced` -] -``` - -## `build.rs` Templates - -You can use the following template to write `build.rs` to quickly gain the build-time capabilities of `comp` and `pathf`: - -```rust,ignore -// build.rs -fn main() { - build_scripts(); - build_pathf_mapping(); -} - -/// Generate completion scripts -fn build_scripts() { - // `env!("CARGO_PKG_NAME")` equals the crate name, which matches the binary name. - // If your binary name differs from the crate name, specify it explicitly. - mingling::build::build_comp_scripts( - // Your binary name: - env!("CARGO_PKG_NAME"), - ) - .unwrap(); -} - -fn build_pathf_mapping() { - // Build pathf type mapping to ensure that the enabled `pathf` feature - // can correctly scan macros in the project - mingling::build::analyze_and_build_type_mapping().unwrap(); -} -``` diff --git a/mingling_core/src/lib.rs b/mingling_core/src/lib.rs index 2aa2ce1..1d26ebb 100644 --- a/mingling_core/src/lib.rs +++ b/mingling_core/src/lib.rs @@ -46,10 +46,6 @@ pub mod core_res { #[cfg(feature = "comp")] pub(crate) mod comp; -#[cfg(feature = "build")] -#[doc = include_str!("docs/build.md")] -pub mod build; - // Public Modules /// Provides a toolkit for `Mingling` testing capabilities. @@ -90,9 +86,6 @@ pub mod error { #[cfg(feature = "structural_renderer")] pub use crate::renderer::structural::error::*; - - #[cfg(feature = "pathf")] - pub use mingling_pathf::error::*; } #[doc(hidden)] diff --git a/mingling_core/tests/test-all/Cargo.lock b/mingling_core/tests/test-all/Cargo.lock index d239541..79202f9 100644 --- a/mingling_core/tests/test-all/Cargo.lock +++ b/mingling_core/tests/test-all/Cargo.lock @@ -16,7 +16,7 @@ version = "0.2.0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -35,6 +35,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -108,7 +141,7 @@ checksum = "1471eb68722ecefeb71debdde2859e8725341f171d3f42b3a98a0862ad19416e" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -140,7 +173,7 @@ checksum = "eca871cea620b07bd2e6da0c883891a25bead698c43a9ab64b0fd663a7a78d5f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", "toml 0.8.23", ] @@ -159,7 +192,6 @@ name = "mingling_core" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", - "just_template", "might_be_async", "ron", "serde", @@ -173,9 +205,21 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", - "syn", + "syn 2.0.118", +] + +[[package]] +name = "mingling_pathf" +version = "0.5.0" +dependencies = [ + "cargo_metadata", + "just_fmt 0.2.0", + "proc-macro2", + "syn 2.0.118", ] [[package]] @@ -278,6 +322,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -304,7 +358,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] @@ -389,6 +443,17 @@ dependencies = [ ] [[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "test-all" version = "0.1.0" dependencies = [ @@ -398,6 +463,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "tokio" version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -422,7 +507,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.118", ] [[package]] diff --git a/mingling_core/tests/test-all/Cargo.toml b/mingling_core/tests/test-all/Cargo.toml index df2efdb..7f50f2f 100644 --- a/mingling_core/tests/test-all/Cargo.toml +++ b/mingling_core/tests/test-all/Cargo.toml @@ -10,7 +10,6 @@ publish = false mingling = { path = "../../../mingling", features = [ "structural_renderer_full", "comp", - "builds", "repl", "dispatch_tree", "picker", diff --git a/mingling_core/tests/test-comp/Cargo.lock b/mingling_core/tests/test-comp/Cargo.lock index 1a37590..199c76e 100644 --- a/mingling_core/tests/test-comp/Cargo.lock +++ b/mingling_core/tests/test-comp/Cargo.lock @@ -3,6 +3,39 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -25,6 +58,12 @@ dependencies = [ ] [[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -88,7 +127,6 @@ name = "mingling_core" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", - "just_template", "might_be_async", ] @@ -97,12 +135,24 @@ name = "mingling_macros" version = "0.5.0" dependencies = [ "just_fmt 0.2.0", + "just_template", + "mingling_pathf", "proc-macro2", "quote", "syn 2.0.118", ] [[package]] +name = "mingling_pathf" +version = "0.5.0" +dependencies = [ + "cargo_metadata", + "just_fmt 0.2.0", + "proc-macro2", + "syn 2.0.118", +] + +[[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -121,12 +171,23 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] name = "serde" version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", + "serde_derive", ] [[package]] @@ -150,6 +211,19 @@ dependencies = [ ] [[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "serde_spanned" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -188,6 +262,26 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "toml" version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -242,3 +336,9 @@ checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/mingling_core/tests/test-comp/Cargo.toml b/mingling_core/tests/test-comp/Cargo.toml index 9ceca3e..789e172 100644 --- a/mingling_core/tests/test-comp/Cargo.toml +++ b/mingling_core/tests/test-comp/Cargo.toml @@ -7,4 +7,4 @@ publish = false [workspace] [dependencies] -mingling = { path = "../../../mingling", features = ["comp", "builds"] } +mingling = { path = "../../../mingling", features = ["comp"] } diff --git a/mingling_macros/Cargo.toml b/mingling_macros/Cargo.toml index 137213a..6ae7aeb 100644 --- a/mingling_macros/Cargo.toml +++ b/mingling_macros/Cargo.toml @@ -19,11 +19,11 @@ default = [] async = [] clap = [] -comp = [] +comp = ["dep:just_template", "dep:mingling_pathf"] dispatch_tree = [] structural_renderer = [] repl = [] -pathf = [] +pathf = ["dep:mingling_pathf"] extras = [] @@ -33,3 +33,9 @@ quote.workspace = true proc-macro2.workspace = true just_fmt.workspace = true + +# comp — compile-time completion script generation (build_comp!()) +just_template = { workspace = true, optional = true } + +# pathf — compile-time type path analysis (build_pathf!()) +mingling_pathf = { workspace = true, optional = true } diff --git a/mingling_macros/src/build.rs b/mingling_macros/src/build.rs new file mode 100644 index 0000000..8f2949d --- /dev/null +++ b/mingling_macros/src/build.rs @@ -0,0 +1,56 @@ +//! Compile-time build logic for `build_comp!()` and `build_pathf!()`. +//! +//! The build steps run as a side effect of macro expansion (during `gen_program!`), +//! writing artifacts under `{target_directory}/mingling/`. + +#[doc(hidden)] +#[cfg(feature = "comp")] +pub(crate) mod comp; + +#[doc(hidden)] +#[cfg(feature = "pathf")] +pub(crate) mod pathf; + +/// Shared implementation behind `build_comp!()`. +/// +/// Accepts an optional string literal (the binary name); defaults to +/// `CARGO_PKG_NAME`. Returns an empty token stream on success, or a +/// `compile_error!` token stream on failure. +#[cfg(feature = "comp")] +pub(crate) fn comp_build_impl(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + let bin_name: String = if input.is_empty() { + std::env::var("CARGO_PKG_NAME").unwrap_or_default() + } else { + match syn::parse::<syn::LitStr>(input) { + Ok(lit) => lit.value(), + Err(e) => return e.to_compile_error().into(), + } + }; + + match comp::build_comp_scripts(&bin_name) { + Ok(()) => proc_macro::TokenStream::new(), + Err(e) => { + let msg = format!("build_comp: failed to generate completion scripts: {e}"); + syn::Error::new(proc_macro2::Span::call_site(), msg) + .to_compile_error() + .into() + } + } +} + +/// Shared implementation behind `build_pathf!()`. +/// +/// Runs the pathf type-mapping analysis. Returns an empty token stream on +/// success, or a `compile_error!` token stream on failure. +#[cfg(feature = "pathf")] +pub(crate) fn pathf_build_impl(_input: proc_macro::TokenStream) -> proc_macro::TokenStream { + match pathf::analyze_and_build_type_mapping() { + Ok(()) => proc_macro::TokenStream::new(), + Err(e) => { + let msg = format!("build_pathf: type mapping analysis failed: {e}"); + syn::Error::new(proc_macro2::Span::call_site(), msg) + .to_compile_error() + .into() + } + } +} diff --git a/mingling_core/src/build/comp.rs b/mingling_macros/src/build/comp.rs index d6bb34f..81a26e8 100644 --- a/mingling_core/src/build/comp.rs +++ b/mingling_macros/src/build/comp.rs @@ -2,7 +2,27 @@ use std::path::PathBuf; use just_template::tmpl; -use crate::ShellFlag; +/// Represents the shell environment for which the output format is intended. +/// +/// This is an internal copy of `mingling_core::ShellFlag`, kept private to the +/// build module because the macros crate must not depend on `mingling_core`. +/// Which variants are constructed depends on the target OS (`#[cfg]`), so +/// platform-gated variants may be unused on any given host. +#[allow(dead_code)] +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub(crate) enum ShellFlag { + /// Represents the Bash shell. + #[default] + Bash, + /// Represents the Zsh shell. + Zsh, + /// Represents the Fish shell. + Fish, + /// Represents `PowerShell`. + Powershell, + /// A custom or unsupported shell type, identified by the provided string. + Other(String), +} const TMPL_COMP_BASH: &str = include_str!("../../tmpls/comps/bash.sh"); const TMPL_COMP_ZSH: &str = include_str!("../../tmpls/comps/zsh.zsh"); @@ -15,21 +35,10 @@ const TMPL_COMP_PWSH: &str = include_str!("../../tmpls/comps/pwsh.ps1"); /// On Linux, generates Zsh, Bash, and Fish completions. /// Scripts are written to the `OUT_DIR` (or `target/` if `OUT_DIR` is not set). /// -/// # Example -/// ``` -/// # #[cfg(all(feature = "build", feature = "comp"))] { -/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || { -/// # use mingling_core::ShellFlag; -/// # use mingling_core::build::build_comp_scripts; -/// // Generate completion scripts for "myapp" -/// build_comp_scripts("myapp").unwrap(); +/// # Errors /// -/// // Generate completion scripts for current package -/// build_comp_scripts(env!("CARGO_PKG_NAME")).unwrap(); -/// # }); -/// # } -/// ``` -pub fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> { +/// Returns an [`std::io::Error`] if a script cannot be written. +pub(crate) fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> { #[cfg(target_os = "windows")] { build_comp_script(&ShellFlag::Powershell, name)?; @@ -57,22 +66,23 @@ pub fn build_comp_scripts(name: &str) -> Result<(), std::io::Error> { /// /// This function takes a shell flag and a binary name, selects the appropriate /// template, substitutes the binary name into the template, and writes the -/// resulting completion script to the target directory (typically `target/`). +/// resulting completion script to the Mingling build directory +/// (`{target_directory}/mingling/`, resolved via `cargo metadata`). +/// +/// # Errors /// -/// # Example -/// ``` -/// # #[cfg(all(feature = "build", feature = "comp"))] { -/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || { -/// # use mingling_core::ShellFlag; -/// # use mingling_core::build::build_comp_script; -/// build_comp_script(&ShellFlag::Bash, "myapp").unwrap(); -/// # }); -/// # } -/// ``` -pub fn build_comp_script(shell_flag: &ShellFlag, bin_name: &str) -> Result<(), std::io::Error> { - let out_dir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap()); - let target_dir = out_dir.join("../../../"); - build_comp_script_to(shell_flag, bin_name, &target_dir.to_string_lossy()) +/// Returns an [`std::io::Error`] if the script cannot be written. +pub(crate) fn build_comp_script( + shell_flag: &ShellFlag, + bin_name: &str, +) -> Result<(), std::io::Error> { + let output_dir = comp_output_dir()?; + build_comp_script_to(shell_flag, bin_name, &output_dir.to_string_lossy()) +} + +/// The directory where completion scripts are written: `{target_directory}/mingling/`. +fn comp_output_dir() -> Result<PathBuf, std::io::Error> { + mingling_pathf::build_output_dir().map_err(|e| std::io::Error::other(e.to_string())) } /// Generate a shell completion script to a specified directory. @@ -81,17 +91,10 @@ pub fn build_comp_script(shell_flag: &ShellFlag, bin_name: &str) -> Result<(), s /// selects the appropriate template, substitutes the binary name into the template, /// and writes the resulting completion script to the specified directory. /// -/// # Example -/// ``` -/// # #[cfg(all(feature = "build", feature = "comp"))] { -/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || { -/// # use mingling_core::ShellFlag; -/// # use mingling_core::build::build_comp_script_to; -/// build_comp_script_to(&ShellFlag::Bash, "myapp", ".temp/target/test/out/").unwrap(); -/// # }); -/// # } -/// ``` -pub fn build_comp_script_to( +/// # Errors +/// +/// Returns an [`std::io::Error`] if the script cannot be written. +pub(crate) fn build_comp_script_to( shell_flag: &ShellFlag, bin_name: &str, target_dir: &str, @@ -105,33 +108,6 @@ pub fn build_comp_script_to( std::fs::write(&output_path, tmpl.to_string()) } -/// Generate a shell completion script and write it to a specified file path. -/// -/// This function takes a shell flag, a binary name, and an output file path, -/// selects the appropriate template, substitutes the binary name into the template, -/// and writes the resulting completion script directly to the specified file path. -/// -/// # Example -/// ``` -/// # #[cfg(all(feature = "build", feature = "comp"))] { -/// # temp_env::with_var("OUT_DIR", Some(".temp/target/test/out/"), || { -/// # use mingling_core::ShellFlag; -/// # use mingling_core::build::build_comp_script_to_file; -/// build_comp_script_to_file(&ShellFlag::Bash, "myapp", ".temp/target/test/out/myapp.comp.sh").unwrap(); -/// # }); -/// # } -/// ``` -pub fn build_comp_script_to_file( - shell_flag: &ShellFlag, - bin_name: &str, - output_path: impl Into<PathBuf>, -) -> Result<(), std::io::Error> { - let (tmpl_str, _ext) = get_tmpl(shell_flag); - let mut tmpl = just_template::Template::from(tmpl_str); - tmpl!(bin_name = bin_name); - std::fs::write(output_path.into(), tmpl.to_string()) -} - const fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) { match shell_flag { ShellFlag::Bash | ShellFlag::Other(_) => (TMPL_COMP_BASH, ".sh"), @@ -144,7 +120,6 @@ const fn get_tmpl(shell_flag: &ShellFlag) -> (&'static str, &'static str) { #[cfg(test)] mod tests { use super::*; - use crate::ShellFlag; #[test] fn get_tmpl_bash() { diff --git a/mingling_macros/src/build/pathf.rs b/mingling_macros/src/build/pathf.rs new file mode 100644 index 0000000..788f527 --- /dev/null +++ b/mingling_macros/src/build/pathf.rs @@ -0,0 +1,19 @@ +use std::path::PathBuf; + +use mingling_pathf::error::MinglingPathfinderError; + +/// The directory where pathf's build artifacts are stored for the current +/// crate: `{target_directory}/mingling/{CARGO_PKG_NAME}`. +pub fn output_dir() -> Result<PathBuf, MinglingPathfinderError> { + Ok(mingling_pathf::build_output_dir()?.join(crate_name())) +} + +/// Runs the pathf type-mapping analysis for the current crate at compile time +/// (replacing the previous `build.rs` call). +pub fn analyze_and_build_type_mapping() -> Result<(), MinglingPathfinderError> { + mingling_pathf::analyze_and_build_type_mapping() +} + +fn crate_name() -> String { + std::env::var("CARGO_PKG_NAME").unwrap_or_default() +} diff --git a/mingling_macros/src/func/gen_program.rs b/mingling_macros/src/func/gen_program.rs index c0a7ea8..35e8352 100644 --- a/mingling_macros/src/func/gen_program.rs +++ b/mingling_macros/src/func/gen_program.rs @@ -7,6 +7,11 @@ use quote::quote; /// Generates the `Next` type alias, `Routable` impl for `ChainProcess`, /// and delegates to `program_comp_gen!()`, `program_fallback_gen!()`, /// and `program_final_gen!()`. +/// +/// When the `comp` / `pathf` features are enabled, the expansion begins by +/// invoking `build_comp!()` / `build_pathf!()`, which run the build steps +/// (previously done in `build.rs`) as a compile-time side effect and expand +/// to nothing. pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream { #[cfg(feature = "comp")] let comp_gen = quote! { @@ -16,18 +21,46 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream { #[cfg(not(feature = "comp"))] let comp_gen = quote! {}; - // When pathf is enabled, load the type_using.rs generated by the build script + // `build_pathf!()` / `build_comp!()` are invoked at the very beginning of the + // expansion: they run the build logic at compile time and expand to nothing. + #[cfg(feature = "comp")] + let comp_build = quote! { + ::mingling::macros::build_comp!(); + }; + + #[cfg(not(feature = "comp"))] + let comp_build = quote! {}; + + #[cfg(feature = "pathf")] + let pathf_build = quote! { + ::mingling::macros::build_pathf!(); + }; + + #[cfg(not(feature = "pathf"))] + let pathf_build = quote! {}; + + // When pathf is enabled, load the type_using.rs generated by the build logic // and emit its use statements so types from submodules are in scope. #[cfg(feature = "pathf")] let pathf_uses: Vec<proc_macro2::TokenStream> = { + // The `build_pathf!()` macro emitted above will (re-)run the analysis + // during expansion, but the `use` statements are needed right now, so + // make sure the mapping exists before reading it. + if let Err(e) = crate::build::pathf::analyze_and_build_type_mapping() { + let msg = format!("pathf: type mapping analysis failed: {e}"); + return syn::Error::new(proc_macro2::Span::call_site(), msg) + .to_compile_error() + .into(); + } let uses = load_pathf_uses(); if uses.is_empty() { - // The file might not exist yet — emit a clear hint + // The analyzer found nothing — emit a clear hint let hint: proc_macro2::TokenStream = syn::parse_quote! { compile_error!( - "pathf: `{}` not found or empty.\n\ - Make sure `build.rs` calls `mingling::build::analyze_and_build_type_mapping().unwrap();`\n\ - with features [\"build\", \"pathf\"] enabled." + "pathf: no types were found by the analyzer.\n\ + Make sure the `pathf` feature is enabled (which also enables\n\ + the `build_pathf!()` macro) and that `gen_program!()` is called\n\ + in a crate with a `src/` directory." ); }; vec![hint] @@ -47,6 +80,8 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream { }; TokenStream::from(quote! { + #comp_build + #pathf_build pub use __this_program_impl::*; #[doc(hidden)] @@ -88,24 +123,16 @@ pub(crate) fn gen_program_impl(_input: TokenStream) -> TokenStream { }) } -/// Loads `type_using.rs` generated by the pathf build script and returns each +/// Loads `type_using.rs` generated by the pathf build logic and returns each /// `use ...;` line as a token stream, ready to be emitted in the generated output. #[cfg(feature = "pathf")] fn load_pathf_uses() -> Vec<proc_macro2::TokenStream> { - let out_dir = match std::env::var("OUT_DIR") { - Ok(d) => d, - Err(_) => return Vec::new(), - }; - let crate_name = match std::env::var("CARGO_PKG_NAME") { - Ok(n) => n, - Err(_) => return Vec::new(), + let Ok(output_dir) = crate::build::pathf::output_dir() else { + return Vec::new(); }; - let path = std::path::Path::new(&out_dir) - .join(&crate_name) - .join("type_using.rs"); - let content = match std::fs::read_to_string(&path) { - Ok(c) => c, - Err(_) => return Vec::new(), + let path = output_dir.join("type_using.rs"); + let Ok(content) = std::fs::read_to_string(&path) else { + return Vec::new(); }; content .lines() diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs index d00773c..1aaedb1 100644 --- a/mingling_macros/src/lib.rs +++ b/mingling_macros/src/lib.rs @@ -20,6 +20,9 @@ mod derive; mod func; mod systems; +#[cfg(any(feature = "comp", feature = "pathf"))] +mod build; + mod extensions; mod utils; @@ -1653,6 +1656,50 @@ pub fn gen_program(input: TokenStream) -> TokenStream { func::gen_program::gen_program_impl(input) } +/// Executes the completion-script build at compile time and expands to nothing. +/// +/// **This macro is only available with the `comp` feature.** +/// +/// The completion scripts are written to `{target_directory}/mingling/` (the +/// target directory is resolved via `cargo metadata`). +/// +/// `gen_program!()` calls this macro automatically when the `comp` feature is +/// enabled. It can also be invoked manually to customize the binary name: +/// +/// - `build_comp!()` — uses the current package name (`CARGO_PKG_NAME`). +/// - `build_comp!("mybin")` — uses the given binary name. +/// +/// ```rust,ignore +/// mingling::macros::build_comp!(); +/// // or: +/// mingling::macros::build_comp!("mybin"); +/// ``` +#[cfg(feature = "comp")] +#[proc_macro] +pub fn build_comp(input: TokenStream) -> TokenStream { + build::comp_build_impl(input) +} + +/// Executes the pathf type-mapping build at compile time and expands to nothing. +/// +/// **This macro is only available with the `pathf` feature.** +/// +/// The mapping files are written to `{target_directory}/mingling/{CARGO_PKG_NAME}/` +/// (the target directory is resolved via `cargo metadata`), and are consumed by +/// `gen_program!()` so that types defined in submodules are resolved automatically. +/// +/// `gen_program!()` calls this macro automatically when the `pathf` feature is +/// enabled. +/// +/// ```rust,ignore +/// mingling::macros::build_pathf!(); +/// ``` +#[cfg(feature = "pathf")] +#[proc_macro] +pub fn build_pathf(input: TokenStream) -> TokenStream { + build::pathf_build_impl(input) +} + /// Internal macro used by `gen_program!` to generate the completion infrastructure for /// shell completion support. /// diff --git a/mingling_core/tmpls/comps/bash.sh b/mingling_macros/tmpls/comps/bash.sh index edec28d..edec28d 100644 --- a/mingling_core/tmpls/comps/bash.sh +++ b/mingling_macros/tmpls/comps/bash.sh diff --git a/mingling_core/tmpls/comps/fish.fish b/mingling_macros/tmpls/comps/fish.fish index 64b4ed3..64b4ed3 100644 --- a/mingling_core/tmpls/comps/fish.fish +++ b/mingling_macros/tmpls/comps/fish.fish diff --git a/mingling_core/tmpls/comps/pwsh.ps1 b/mingling_macros/tmpls/comps/pwsh.ps1 index d72a027..d72a027 100644 --- a/mingling_core/tmpls/comps/pwsh.ps1 +++ b/mingling_macros/tmpls/comps/pwsh.ps1 diff --git a/mingling_core/tmpls/comps/zsh.zsh b/mingling_macros/tmpls/comps/zsh.zsh index 7cf5f7b..7cf5f7b 100644 --- a/mingling_core/tmpls/comps/zsh.zsh +++ b/mingling_macros/tmpls/comps/zsh.zsh diff --git a/mingling_pathf/Cargo.toml b/mingling_pathf/Cargo.toml index 0d4e37a..a649cb4 100644 --- a/mingling_pathf/Cargo.toml +++ b/mingling_pathf/Cargo.toml @@ -12,3 +12,4 @@ description = "A library for automatically finding internal types generated by M syn.workspace = true proc-macro2.workspace = true just_fmt.workspace = true +cargo_metadata.workspace = true diff --git a/mingling_pathf/src/error.rs b/mingling_pathf/src/error.rs index 5a748c4..bd850a8 100644 --- a/mingling_pathf/src/error.rs +++ b/mingling_pathf/src/error.rs @@ -53,6 +53,11 @@ pub enum MinglingPathfinderError { /// Details from the parser about the parse failure. message: String, }, + + /// `cargo metadata` could not be executed or parsed. + /// + /// `message` contains the underlying error from the cargo invocation. + CargoMetadata(String), } impl fmt::Display for MinglingPathfinderError { @@ -82,6 +87,7 @@ impl fmt::Display for MinglingPathfinderError { Self::SynError { path, message } => { write!(f, "Failed to parse {}: {message}", path.display()) } + Self::CargoMetadata(message) => write!(f, "cargo metadata failed: {message}"), } } } diff --git a/mingling_pathf/src/lib.rs b/mingling_pathf/src/lib.rs index 492bfc7..f0637e8 100644 --- a/mingling_pathf/src/lib.rs +++ b/mingling_pathf/src/lib.rs @@ -13,3 +13,5 @@ pub mod patterns; mod type_mapping_builder; pub use type_mapping_builder::analyze_and_build_type_mapping; pub use type_mapping_builder::analyze_and_build_type_mapping_for; +pub use type_mapping_builder::build_output_dir; +pub use type_mapping_builder::target_directory; diff --git a/mingling_pathf/src/type_mapping_builder.rs b/mingling_pathf/src/type_mapping_builder.rs index 1ccd267..4d0799f 100644 --- a/mingling_pathf/src/type_mapping_builder.rs +++ b/mingling_pathf/src/type_mapping_builder.rs @@ -5,7 +5,9 @@ use std::collections::HashSet; use std::fmt::Write as FmtWrite; -use std::path::Path; +use std::path::{Path, PathBuf}; + +use cargo_metadata::MetadataCommand; use crate::error::MinglingPathfinderError; use crate::module_pathf; @@ -87,40 +89,74 @@ pub fn analyze_and_build_type_mapping_for( Ok(()) } -/// Convenience version to be called from `build.rs`, automatically reading configuration -/// from environment variables. +/// Runs `cargo metadata` from the given crate directory and returns the +/// workspace's target directory. +/// +/// The subprocess resolves the target directory exactly as Cargo does, +/// honoring `.cargo/config.toml`, `CARGO_TARGET_DIR`, and `--target-dir`. +/// +/// `crate_dir` — crate root directory (i.e., the directory containing Cargo.toml). +/// +/// # Errors +/// +/// Returns a [`MinglingPathfinderError::CargoMetadata`] if `cargo metadata` +/// cannot be executed or its output cannot be parsed. +pub fn target_directory(crate_dir: &Path) -> Result<PathBuf, MinglingPathfinderError> { + let metadata = MetadataCommand::new() + .current_dir(crate_dir) + .no_deps() + .exec() + .map_err(|e| MinglingPathfinderError::CargoMetadata(e.to_string()))?; + Ok(metadata.target_directory.into_std_path_buf()) +} + +/// The directory where all of Mingling's compile-time build artifacts are +/// written for the current crate: `{target_directory}/mingling/`. +/// +/// Reads `CARGO_MANIFEST_DIR` from the environment to locate the crate, then +/// resolves the target directory via [`target_directory`]. Works both from a +/// `build.rs` and from proc-macro expansion (no `OUT_DIR` required). +/// +/// # Errors +/// +/// Returns a [`MinglingPathfinderError`] if the environment variables are +/// missing or the target directory cannot be resolved. +pub fn build_output_dir() -> Result<PathBuf, MinglingPathfinderError> { + let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| { + MinglingPathfinderError::IoError(std::io::Error::new( + std::io::ErrorKind::NotFound, + "CARGO_MANIFEST_DIR not set", + )) + })?; + Ok(target_directory(Path::new(&crate_dir))?.join("mingling")) +} + +/// Convenience version to be called from `build.rs` or macro expansion, +/// automatically reading configuration from environment variables. /// -/// Reads `CARGO_PKG_NAME` and `OUT_DIR`, and outputs to `{OUT_DIR}/{CARGO_PKG_NAME}/`. +/// Reads `CARGO_PKG_NAME` and `CARGO_MANIFEST_DIR`, and outputs to +/// `{target_directory}/mingling/{CARGO_PKG_NAME}/` (see [`build_output_dir`]). /// /// # Errors /// /// Returns a [`MinglingPathfinderError`] if the required environment variables -/// (`CARGO_PKG_NAME`, `OUT_DIR`) are not set, the current directory cannot be -/// determined, or the type mapping generation fails. +/// (`CARGO_PKG_NAME`, `CARGO_MANIFEST_DIR`) are not set or the type mapping +/// generation fails. pub fn analyze_and_build_type_mapping() -> Result<(), MinglingPathfinderError> { let crate_name = std::env::var("CARGO_PKG_NAME").map_err(|_| { MinglingPathfinderError::IoError(std::io::Error::new( std::io::ErrorKind::NotFound, - "CARGO_PKG_NAME not set (not running in build.rs?)", + "CARGO_PKG_NAME not set", )) })?; - - let out_dir = std::env::var("OUT_DIR").map_err(|_| { + let crate_dir = std::env::var("CARGO_MANIFEST_DIR").map_err(|_| { MinglingPathfinderError::IoError(std::io::Error::new( std::io::ErrorKind::NotFound, - "OUT_DIR not set (not running in build.rs?)", + "CARGO_MANIFEST_DIR not set", )) })?; - let crate_dir = std::env::current_dir()?; - let output_dir = Path::new(&out_dir).join(&crate_name); - - analyze_and_build_type_mapping_for(&crate_dir, &output_dir)?; + let output_dir = build_output_dir()?.join(&crate_name); - // Notify Cargo to re-run build.rs when source files change - println!("cargo:rerun-if-changed=src/"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_OS"); - println!("cargo:rerun-if-env-changed=CARGO_CFG_TARGET_ARCH"); - - Ok(()) + analyze_and_build_type_mapping_for(Path::new(&crate_dir), &output_dir) } diff --git a/mingling_pathf/test/Cargo.lock b/mingling_pathf/test/Cargo.lock index 58c7c9a..7dc772a 100644 --- a/mingling_pathf/test/Cargo.lock +++ b/mingling_pathf/test/Cargo.lock @@ -3,6 +3,45 @@ version = 4 [[package]] +name = "camino" +version = "1.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +dependencies = [ + "serde_core", +] + +[[package]] +name = "cargo-platform" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0061da739915fae12ea00e16397555ed4371a6bb285431aab930f61b0aa4ba" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "cargo_metadata" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef987d17b0a113becdd19d3d0022d04d7ef41f9efe4f3fb63ac44ba61df3ade9" +dependencies = [ + "camino", + "cargo-platform", + "semver", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] name = "just_fmt" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -15,12 +54,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6170dccbc3ea15dfb7f2da964097f814aba1dd8f746d4ffc56f33245c38e6d96" [[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] name = "mingling_pathf" version = "0.5.0" dependencies = [ + "cargo_metadata", "just_fmt 0.2.0", "proc-macro2", - "syn", + "syn 2.0.118", ] [[package]] @@ -42,6 +88,59 @@ dependencies = [ ] [[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] +name = "serde_json" +version = "1.0.151" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] name = "syn" version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -53,6 +152,17 @@ dependencies = [ ] [[package]] +name = "syn" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] name = "test-mingling-pathf" version = "0.1.0" dependencies = [ @@ -61,7 +171,33 @@ dependencies = [ ] [[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.3", +] + +[[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" |
