Skip to content

Commit 10382f4

Browse files
authored
feat: improve codegen crate calculation, separate bindings into crates (#467)
1 parent 432b91b commit 10382f4

File tree

125 files changed

+89784
-37998
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+89784
-37998
lines changed

.gitattributes

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
crates/bevy_mod_scripting_functions/src/bevy_bindings/*.rs linguist-generated
2-
crates/bevy_mod_scripting_functions/src/bevy_gindings/*.rs -diff -merge
1+
crates/bindings/**/* linguist-generated
2+
crates/bindings/**/* -diff -merge

.github/workflows/bevy_mod_scripting.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ jobs:
4444
base: main
4545
filters: |
4646
src:
47+
- 'bindings/**'
4748
- 'src/**'
4849
- 'crates/**'
4950
- 'examples/**'
@@ -132,6 +133,7 @@ jobs:
132133
echo "Clippy version: $(cargo clippy --version)"
133134
echo "Active toolchain: $(rustup show active-toolchain)"
134135
continue-on-error: true
136+
135137
- name: Rust Cache
136138
if: ${{ needs.check-needs-run.outputs.any-changes == 'true' && (matrix.run_args.run_on_forks || needs.check-is-fork.outputs.is_fork != 'true') }}
137139
uses: Swatinem/[email protected]
@@ -185,4 +187,19 @@ jobs:
185187
sed -n 's/.*pull\/\([0-9]*\).*/\1/p' pr.txt > pr_number.txt
186188
PRNUMBER=$(cat pr_number.txt)
187189
gh pr merge $PRNUMBER --squash
190+
fi
191+
192+
rollup-check:
193+
name: Required Checks Successful
194+
needs: [check]
195+
runs-on: ubuntu-latest
196+
if: ${{ always() }}
197+
steps:
198+
- name: Check if all jobs succeeded
199+
run: |
200+
if [[ "${{ needs.check.result }}" != "success" ]]; then
201+
echo "One or more checks failed. See detailed job results above."
202+
exit 1
203+
else
204+
echo "All checks passed successfully!"
188205
fi

.github/workflows/synchronize_bindings.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ jobs:
2626
- name: Generate Bindings
2727
run: |
2828
cargo xtask codegen
29+
cargo fmt
2930
- name: Check for changes and create diff
3031
id: check_changes
3132
run: |

Cargo.toml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ default = [
2929
"bevy_reflect_bindings",
3030
"bevy_time_bindings",
3131
"bevy_transform_bindings",
32+
"bevy_color_bindings",
33+
"bevy_core_pipeline_bindings",
3234
]
3335

3436
lua = [
@@ -46,10 +48,29 @@ luau = ["bevy_mod_scripting_lua/luau", "lua"]
4648

4749
# bindings
4850
core_functions = ["bevy_mod_scripting_functions/core_functions"]
51+
52+
bevy_a11y_bindings = ["bevy_mod_scripting_functions/bevy_a11y"]
53+
bevy_animation_bindings = ["bevy_mod_scripting_functions/bevy_animation"]
54+
bevy_asset_bindings = ["bevy_mod_scripting_functions/bevy_asset"]
55+
bevy_color_bindings = ["bevy_mod_scripting_functions/bevy_color"]
56+
bevy_core_pipeline_bindings = [
57+
"bevy_mod_scripting_functions/bevy_core_pipeline",
58+
]
4959
bevy_ecs_bindings = ["bevy_mod_scripting_functions/bevy_ecs"]
60+
bevy_gizmos_bindings = ["bevy_mod_scripting_functions/bevy_gizmos"]
61+
bevy_gltf_bindings = ["bevy_mod_scripting_functions/bevy_gltf"]
62+
bevy_image_bindings = ["bevy_mod_scripting_functions/bevy_image"]
5063
bevy_input_bindings = ["bevy_mod_scripting_functions/bevy_input"]
64+
bevy_input_focus_bindings = ["bevy_mod_scripting_functions/bevy_input_focus"]
5165
bevy_math_bindings = ["bevy_mod_scripting_functions/bevy_math"]
66+
bevy_mesh_bindings = ["bevy_mod_scripting_functions/bevy_mesh"]
67+
bevy_pbr_bindings = ["bevy_mod_scripting_functions/bevy_pbr"]
68+
bevy_picking_bindings = ["bevy_mod_scripting_functions/bevy_picking"]
5269
bevy_reflect_bindings = ["bevy_mod_scripting_functions/bevy_reflect"]
70+
bevy_render_bindings = ["bevy_mod_scripting_functions/bevy_render"]
71+
bevy_scene_bindings = ["bevy_mod_scripting_functions/bevy_scene"]
72+
bevy_sprite_bindings = ["bevy_mod_scripting_functions/bevy_sprite"]
73+
bevy_text_bindings = ["bevy_mod_scripting_functions/bevy_text"]
5374
bevy_time_bindings = ["bevy_mod_scripting_functions/bevy_time"]
5475
bevy_transform_bindings = ["bevy_mod_scripting_functions/bevy_transform"]
5576

@@ -105,6 +126,38 @@ bevy_diagnostic = { version = "0.16.0", default-features = false }
105126
bevy_platform = { version = "0.16.0", default-features = false }
106127
bevy_time = { version = "0.16.0", default-features = false }
107128
bevy_input = { version = "0.16.0", default-features = false }
129+
bevy_a11y = { version = "0.16.0", default-features = false, features = [
130+
"std",
131+
"bevy_reflect",
132+
] }
133+
bevy_animation = { version = "0.16.0", default-features = false }
134+
bevy_color = { version = "0.16.0", default-features = false, features = [
135+
"std",
136+
"bevy_reflect",
137+
] }
138+
bevy_core_pipeline = { version = "0.16.0", default-features = false }
139+
bevy_gizmos = { version = "0.16.0", default-features = false }
140+
bevy_gltf = { version = "0.16.0", default-features = false }
141+
bevy_image = { version = "0.16.0", default-features = false, features = [
142+
"bevy_reflect",
143+
] }
144+
bevy_input_focus = { version = "0.16.0", default-features = false, features = [
145+
"std",
146+
"bevy_reflect",
147+
] }
148+
bevy_mesh = { version = "0.16.0", default-features = false }
149+
bevy_pbr = { version = "0.16.0", default-features = false }
150+
bevy_picking = { version = "0.16.0", default-features = false }
151+
bevy_render = { version = "0.16.0", default-features = false }
152+
bevy_scene = { version = "0.16.0", default-features = false }
153+
bevy_sprite = { version = "0.16.0", default-features = false }
154+
bevy_text = { version = "0.16.0", default-features = false }
155+
bevy_window = { version = "0.16.0", default-features = false, features = [
156+
"bevy_reflect",
157+
"std",
158+
] }
159+
bevy_winit = { version = "0.16.0", default-features = false }
160+
108161
glam = { version = "0.29.3", default-features = false }
109162
uuid = { version = "1.11", default-features = false }
110163
smol_str = { version = "0.2.0", default-features = false }
@@ -186,6 +239,7 @@ members = [
186239
"crates/lad_backends/mdbook_lad_preprocessor",
187240
"crates/ladfile_builder",
188241
"crates/bevy_system_reflection",
242+
"crates/bindings/*",
189243
]
190244
resolver = "2"
191245
exclude = ["codegen", "crates/macro_tests", "xtask"]

check.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ WORKSPACE_DIR="$PWD"
44
cd "$(dirname "$0")"
55
# if the path is in /bevy_api_gen then we run the codegen check
66

7-
if [[ "$WORKSPACE_DIR" == *"/bevy_api_gen"* ]]; then
7+
if [[ "$WORKSPACE_DIR" == *"/codegen"* ]]; then
88
# save output to file as well as stdout and stderr
99
cargo xtask check --ide-mode --kind codegen
1010
elif [[ "$WORKSPACE_DIR" == *"/xtask"* ]]; then

codegen/.cargo/config.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[alias]
2+
xtask = "run --manifest-path ../xtask/Cargo.toml --package xtask --"

codegen/Cargo.toml

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ include = [
1616
]
1717

1818
[workspace]
19-
members = []
19+
members = ["crates/crate_feature_graph"]
20+
exclude = [
21+
"crates/test_crates/workspace/root",
22+
"crates/test_crates/workspace/crate_a",
23+
"crates/test_crates/workspace/crate_b",
24+
]
2025

2126
[[bin]]
2227
name = "cargo-bms-codegen"
@@ -37,9 +42,12 @@ debug = false
3742
[package.metadata.rust-analyzer]
3843
rustc_private = true
3944

40-
[dependencies]
45+
[workspace.dependencies]
46+
crate_feature_graph = { path = "crates/crate_feature_graph", version = "0.1" }
47+
petgraph = { version = "0.8" }
4148
log = "0.4"
4249
env_logger = "0.11"
50+
pretty_env_logger = "0.4"
4351
indexmap = "2"
4452
cargo_metadata = "0.18"
4553
serde_json = "1"
@@ -53,6 +61,26 @@ convert_case = "0.6"
5361
syn = { version = "2", features = ["parsing"], default-features = false }
5462
itertools = "0.12"
5563
chrono = "0.4"
64+
pretty_assertions = "1.3"
65+
66+
[dependencies]
67+
crate_feature_graph = { workspace = true, features = ["dot_parser", "serde"] }
68+
clap = { workspace = true }
69+
tera = { workspace = true }
70+
strum = { workspace = true }
71+
include_dir = { workspace = true }
72+
syn = { workspace = true }
73+
itertools = { workspace = true }
74+
log = { workspace = true }
75+
# env_logger = { workspace = true }
76+
pretty_env_logger = { workspace = true }
77+
indexmap = { workspace = true }
78+
cargo_metadata = { workspace = true }
79+
serde_json = { workspace = true }
80+
serde = { workspace = true }
81+
prettyplease = { workspace = true }
82+
convert_case = { workspace = true }
83+
chrono = { workspace = true }
5684

5785
[build-dependencies]
5886
toml = "0.8"
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
[package]
2+
name = "crate_feature_graph"
3+
version = "0.1.0"
4+
edition = "2024"
5+
readme = "README.md"
6+
license = "MIT OR Apache-2.0"
7+
include = ["src/**", "bin/**", "Cargo.toml", "README.md", "example.png"]
8+
description = "A tool to visualize the flow of features throughout your crate graph."
9+
10+
[lib]
11+
path = "src/lib.rs"
12+
13+
[[bin]]
14+
name = "crate_feature_graph"
15+
path = "bin/main.rs"
16+
17+
[features]
18+
dot_parser = ["petgraph/dot_parser"]
19+
serde = ["dep:serde", "dep:serde_json"]
20+
21+
[dependencies]
22+
petgraph = { workspace = true }
23+
cargo_metadata = { workspace = true }
24+
itertools = { workspace = true }
25+
log = { workspace = true }
26+
clap = { workspace = true, features = ["derive"] }
27+
serde = { workspace = true, features = ["derive"], optional = true }
28+
serde_json = { workspace = true, optional = true }
29+
pretty_env_logger = { workspace = true }
30+
indexmap = { workspace = true, features = ["serde"] }
31+
32+
[dev-dependencies]
33+
petgraph = { workspace = true, features = ["dot_parser"] }
34+
pretty_assertions = { workspace = true }
35+
env_logger = { workspace = true }
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Crate Feature Graph
2+
3+
![Example output graph](./example.png)
4+
5+
A tool for visualising feature flow in a rust workspace, from the perspective of build time features.
6+
7+
## Features
8+
- Compute feature flow throughout your workspace
9+
- Filter out crates you don't want to see from the graph, but retain the connections
10+
- Output as a dot graph or if the `dot_parser` feature is disabled as a text representation
11+
12+
## Usage
13+
You can either filter the output or generate the entire graph.
14+
If you filter out any crates, the edges will be "collapsed" at the edges of the filtered crates, so you can still see how features propagate through the graph.
15+
16+
For larger workspaces it is recommended to generate an svg so you can properly view the entire graph.
17+
18+
features obey the following syntax:
19+
- `feature1` - enable feature1 in the root crate
20+
- `crate/feature2` - enable feature2 in the crate crate (and implicitly enable crate as a dependency)
21+
- `crate/default` - enable the default feature for the crate
22+
- `default` - enable the default feature for the root crate
23+
24+
```bash
25+
cargo install crate_feature_graph --features dot_parser
26+
27+
RUST_LOG=info cargo_feature_graph --manifest-path path/to/Cargo.toml --features="feature1,feature2" --only-show-crates="maybe_crate1,maybe_crate2"
28+
```
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use clap::Parser;
2+
use crate_feature_graph::{CrateName, Workspace, WorkspaceGraph};
3+
4+
#[derive(Parser)]
5+
struct Args {
6+
/// Path to the Cargo.toml of the workspace to analyze
7+
#[clap(long, short, default_value = "./Cargo.toml")]
8+
manifest_path: String,
9+
10+
/// Comma-separated list of feature names to enable for the given manifest
11+
#[clap(
12+
short,
13+
long,
14+
default_value = "",
15+
use_value_delimiter = true,
16+
value_delimiter = ','
17+
)]
18+
features: Vec<String>,
19+
20+
/// Whether to disable the default features of the given manifest
21+
/// Defaults to true
22+
#[clap(long, default_value = "false")]
23+
disable_default_features: bool,
24+
25+
/// Only show crates in the output graph that match one of these names
26+
/// Only works for dot graphs
27+
/// Defaults to empty, which shows all crates
28+
#[clap(long, use_value_delimiter = true, value_delimiter = ',')]
29+
only_show_crates: Vec<String>,
30+
31+
/// The package to consider as the root of the search
32+
/// The default will use the root of the workspace
33+
/// The features provided will be applied to this package, unless a crate prefix is provided
34+
#[clap(long)]
35+
root_package: Option<String>,
36+
}
37+
38+
pub fn main() -> std::io::Result<()> {
39+
pretty_env_logger::init();
40+
let args = Args::parse();
41+
42+
let metadata = cargo_metadata::MetadataCommand::new()
43+
.manifest_path(&args.manifest_path)
44+
.exec()
45+
.expect("Failed to get cargo metadata");
46+
47+
let workspace = Workspace::from(&metadata);
48+
let mut graph = WorkspaceGraph::from(workspace);
49+
50+
let root = args.root_package;
51+
log::info!(
52+
"Calculating features for root: {:?} with features: {:?}, default features: {}",
53+
root,
54+
args.features,
55+
!args.disable_default_features
56+
);
57+
58+
// TODO: allow focusing on a non-workspace root, i.e. package
59+
graph
60+
.calculate_enabled_features_and_dependencies_parse(args.features, root.map(CrateName::new));
61+
62+
#[cfg(feature = "dot_parser")]
63+
let dot_graph = graph.visualise_feature_flow(args.only_show_crates)?;
64+
65+
#[cfg(not(feature = "dot_parser"))]
66+
let dot_graph = {
67+
log::warn!("Feature `dot_parser` not enabled, dumping debug print instead");
68+
format!("{:?}", graph.workspace)
69+
};
70+
71+
// dump the graph
72+
println!("{dot_graph}");
73+
74+
Ok(())
75+
}

0 commit comments

Comments
 (0)