Skip to content

Commit

Permalink
Merge branch 'main' into 193-lint-unit
Browse files Browse the repository at this point in the history
  • Loading branch information
DaAlbrecht committed Jan 13, 2025
2 parents df6fbea + 6702a64 commit 7703db0
Show file tree
Hide file tree
Showing 30 changed files with 970 additions and 377 deletions.
826 changes: 535 additions & 291 deletions Cargo.lock

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,16 @@ actix-web = "4.9.0"
# Opening the app in the browser
webbrowser = "1.0.2"

# Parsing the Cargo manifest
toml_edit = "0.22.22"

# Copying directories
fs_extra = "1.3.0"

# Optimizing Wasm binaries
wasm-opt = { version = "0.116.1", optional = true }

[build-dependencies]
# We don't use `cc` directly, but our dependency `wasm-opt-sys` fails to compile on Windows when using a newer version.
# This can be removed when /~https://github.com/rust-lang/cc-rs/issues/1324 is fixed.
cc = "=1.2.2"
70 changes: 68 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ A prototype [Bevy] CLI tool intended to streamline common tasks when working on

- Project generation from a template
- [A custom, Bevy-specific linter](bevy_lint/README.md)
- Out-of-the-box support for bundling projects into WebAssembly
- An HTTP server for testing these WASM bundles
- Out-of-the-box support for building and running your Bevy app in the browser

If you need assistance or want to help, reach out to the [`bevy_cli` working group channel] in the [Bevy Discord].

Expand All @@ -15,6 +14,73 @@ If you need assistance or want to help, reach out to the [`bevy_cli` working gro
[`bevy_cli` working group channel]: https://discord.com/channels/691052431525675048/1278871953721262090
[Bevy Discord]: https://discord.gg/bevy

## Installation

At this point, the CLI is not published as a package yet and needs to be installed via git:

```cli
cargo install --git /~https://github.com/TheBevyFlock/bevy_cli --locked bevy_cli
```

## Bevy web apps

The CLI makes it easy to build and run web apps made with Bevy, using `bevy build web` and `bevy run web`.
It takes care of compiling the app to Wasm, creating JavaScript bindings and serving it on a local web server to test it out.
Necessary tools will also be installed automatically.

> [!NOTE]
>
> The arguments you know from `cargo` (like `--release`) must be placed before the `web` subcommand, while the web-specific options (like `--open`) must be placed afterwards, e.g.
>
> ```cli
> bevy run --release web --open
> ```
### Running in the browser
Use the `bevy run web` command to run your app in the browser.
The app will be automatically served on a local web server, use the `--open` flag to automatically open it in the browser.
The server will provide a default `index.html` serving as entrypoint for your app.
It features a loading screen and some other utilities.
If you want to customize it, simply create a `web/index.html` file to override the default behavior.
Other files in the `web` folder will also be included in your application.
### Creating web bundles
To deploy your app on a web server, it's often necessary to bundle the binary, assets and web files into a single folder.
Using `bevy build web --bundle`, the CLI can create this bundle for you automatically.
It will be available in the `target/bevy_web` folder, see the command's output for the full file path.
### Compilation profiles
Web apps have different needs than native builds when it comes to compilation.
For example, binary size is a lot more important for web apps, as it has a big influence on the loading times.
The Bevy CLI provides custom `web` and `web-release` compilation profiles, which are optimized for web apps.
They are used by default for the web sub-commands (depending on the `--release` flag).
The profiles can be customized as usual in `Cargo.toml`:
```toml
[profile.web-release]
inherits = "release"
opt-level = "z"
```
Alternatively, you can change the profile entirely, e.g. `bevy run --profile=foo web`.

### Usage in CI

The CLI may include interactive prompts if parts of the required tooling is not installed on the system.
These prompts will break your pipeline if they are triggered in CI.

To avoid this problem, use the `--yes` flag to automatically confirm the prompts:

```cli
bevy build --yes web
```

## License

The Bevy CLI is licensed under either of
Expand Down
4 changes: 2 additions & 2 deletions bevy_lint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ harness = false
# Contains a series of useful utilities when writing lints. The version is chosen to work with the
# currently pinned nightly Rust version. When the Rust version changes, this too needs to be
# updated!
clippy_utils = "=0.1.85"
clippy_utils = "=0.1.86"

# Easy error propagation and contexts.
anyhow = "1.0.86"
Expand All @@ -41,7 +41,7 @@ toml_edit = { version = "0.22.22", default-features = false, features = [

[dev-dependencies]
# Used when running UI tests.
bevy = { version = "0.14.2", default-features = false }
bevy = { version = "0.15.0", default-features = false }

# Used to deserialize `--message-format=json` messages from Cargo.
serde = { version = "1.0.210", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion bevy_lint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ There are several other ways to toggle lints, but they have varying levels of su

|`bevy_lint` Version|Rust Version|Rustup Toolchain|Bevy Version|
|-|-|-|-|
|0.2.0-dev|1.84.0|`nightly-2024-11-28`|0.14|
|0.2.0-dev|1.84.0|`nightly-2025-01-09`|0.15|
|0.1.0|1.84.0|`nightly-2024-11-14`|0.14|

The Rust version in the above table specifies what [version of the Rust language](/~https://github.com/rust-lang/rust/releases) can be compiled with `bevy_lint`. Code written for a later version of Rust may not compile. (This is not usually an issue, though, because `bevy_lint`'s Rust version is kept 1 to 2 releases ahead of stable Rust.)
Expand Down
1 change: 1 addition & 0 deletions bevy_lint/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Thanks for your interest in contributing to `bevy_lint`! Please feel free to ski
- [Setting up your Editor](how-to/editor.md)
- [How to Work with Types](how-to/types.md)
- [How to Release `bevy_lint`](how-to/release.md)
- [Bump to a Newer Version of Rust](how-to/bump-rust.md)
- [Reference](reference/)
- [Explanations](explanations/)

Expand Down
34 changes: 34 additions & 0 deletions bevy_lint/docs/how-to/bump-rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# How to Bump to a Newer Version of Rust

`bevy_lint` matches nightly Rust versions with `clippy_utils`. A new version of `clippy_utils` is released with each version of Rust, which `bevy_lint` should keep up to date with.

1. Go to [`clippy_utils`'s page on crates.io](https://crates.io/crates/clippy_utils) and find the nightly toolchain it requires. For example:

> This crate is only guaranteed to build with this nightly toolchain:
>
> ```
> nightly-2025-01-09
> ```
2. Change the `channel` field in [`rust-toolchain.toml`](../../../rust-toolchain.toml) to the version specified by `clippy_utils`.
3. Update the [compatibility table in `README.md`](../../README.md#compatibility) for the latest `-dev` version.
4. Increase the version of `clippy_utils` in [`Cargo.toml`](../../Cargo.toml) to the latest version.
Once you've finished upgrading the Rust toolchain and `clippy_utils`, there are a few extra steps that can verify `bevy_lint` still functions the same.
1. Read over the [release notes](/~https://github.com/rust-lang/rust/releases) for potentially breaking changes.
2. Skim through [diff.rs for `clippy_utils`](https://diff.rs/clippy_utils) to see if anything the linter uses may have changed.
- `clippy_utils` doesn't provide a user-facing changelog, unfortunately. You may find the [Git history](/~https://github.com/rust-lang/rust-clippy/commits/master/clippy_utils) useful, though!
3. Verify you've installed the latest pinned Rust toolchain. If you use Rustup, it should be automatically installed the first time you run `rustc` or `cargo` in the workspace.
```shell
rustc --version
```
4. Test that the linter still compiles and passes all tests.
```shell
cargo clean
cargo build
cargo test
```
4 changes: 3 additions & 1 deletion bevy_lint/src/bin/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@ fn main() -> ExitCode {
args.remove(0);

// Call the compiler with our custom callback.
RunCompiler::new(&args, &mut BevyLintCallback).run()
RunCompiler::new(&args, &mut BevyLintCallback).run();

Ok(())
});

// We truncate the `i32` to a `u8`. `catch_with_exit_code()` currently only returns 1 or 0, so
Expand Down
47 changes: 42 additions & 5 deletions bevy_lint/src/lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,43 @@ pub struct LintGroup {
pub level: Level,
}

/// Creates a new [`BevyLint`].
///
/// # Example
///
/// ```ignore
/// declare_bevy_lint! {
/// // This lint will be named `bevy::lint_name`.
/// pub LINT_NAME,
/// // See the `groups` module for the available names.
/// LINT_GROUP,
/// // The description printed by `bevy_lint_driver rustc -W help`, and sometimes also used in
/// // diagnostic messages.
/// "short description of lint",
///
/// // The following are optional fields, and may be excluded. They all default to false.
/// //
/// // Whether to report this lint, even if it is inside the expansion of an external macro.
/// @report_in_external_macro = true,
/// // Whether to only run this macro for the crate root. This should be enabled for lint
/// // passes that only override `check_crate()`.
/// @crate_level_only = false,
/// // The compiler can sometimes skip lint passes that are guaranteed not to run. This can
/// // disable that behavior.
/// @eval_always = true,
/// }
/// ```
#[macro_export]
#[doc(hidden)]
macro_rules! declare_bevy_lint {
{
$(#[$attr:meta])*
$vis:vis $name:ident,
$group:ident,
$desc:expr$(,)?
$desc:expr,
$(@report_in_external_macro = $report_in_external_macro:expr,)?
$(@crate_level_only = $crate_level_only:expr,)?
$(@eval_always = $eval_always:expr,)?
} => {
/// Click me for more information.
///
Expand All @@ -49,16 +78,24 @@ macro_rules! declare_bevy_lint {
$(#[$attr])*
$vis static $name: &$crate::lint::BevyLint = &$crate::lint::BevyLint {
lint: &::rustc_lint::Lint {
// Fields that are always configured by macro.
name: concat!("bevy::", stringify!($name)),
default_level: $crate::groups::$group.level,
desc: $desc,

// Fields that cannot be configured.
edition_lint_opts: None,
report_in_external_macro: false,
future_incompatible: None,
is_externally_loaded: true,
feature_gate: None,
crate_level_only: false,
eval_always: false,
is_externally_loaded: true,

// Fields that may sometimes be configured by macro. These all default to false in
// `Lint::default_fields_for_macro()`, but may be overridden to true.
$(report_in_external_macro: $report_in_external_macro,)?
$(crate_level_only: $crate_level_only,)?
$(eval_always: $eval_always,)?

..::rustc_lint::Lint::default_fields_for_macro()
},
group: &$crate::groups::$group,
};
Expand Down
2 changes: 2 additions & 0 deletions bevy_lint/src/lints/missing_reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ declare_bevy_lint! {
pub MISSING_REFLECT,
RESTRICTION,
"defined a component, resource, or event without a `Reflect` implementation",
// We only override `check_crate()`.
@crate_level_only = true,
}

declare_lint_pass! {
Expand Down
4 changes: 2 additions & 2 deletions bevy_lint/src/lints/panicking_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ use rustc_span::{Span, Symbol};
declare_bevy_lint! {
pub PANICKING_QUERY_METHODS,
RESTRICTION,
"called a `Query` or `QueryState` method that can panic when a non-panicking alternative exists"
"called a `Query` or `QueryState` method that can panic when a non-panicking alternative exists",
}

declare_bevy_lint! {
pub PANICKING_WORLD_METHODS,
RESTRICTION,
"called a `World` method that can panic when a non-panicking alternative exists"
"called a `World` method that can panic when a non-panicking alternative exists",
}

declare_lint_pass! {
Expand Down
2 changes: 1 addition & 1 deletion bevy_lint/src/lints/zst_query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ use rustc_session::declare_lint_pass;
declare_bevy_lint! {
pub ZST_QUERY,
RESTRICTION,
"query for a zero-sized type"
"query for a zero-sized type",
}

declare_lint_pass! {
Expand Down
5 changes: 2 additions & 3 deletions bevy_lint/src/paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ pub const DEFERRED: [&str; 4] = ["bevy_ecs", "system", "system_param", "Deferred
pub const DEFERRED_WORLD: [&str; 4] = ["bevy_ecs", "world", "deferred_world", "DeferredWorld"];
pub const ENTITY_COMMANDS: [&str; 4] = ["bevy_ecs", "system", "commands", "EntityCommands"];
pub const ENTITY_MUT: [&str; 4] = ["bevy_ecs", "world", "entity_ref", "EntityMut"];
// Note that this moves to `bevy_ecs::event::base::Event` in 0.15.
pub const EVENT: [&str; 3] = ["bevy_ecs", "event", "Event"];
pub const EVENTS: [&str; 3] = ["bevy_ecs", "event", "Events"];
pub const EVENT: [&str; 4] = ["bevy_ecs", "event", "base", "Event"];
pub const EVENTS: [&str; 4] = ["bevy_ecs", "event", "collections", "Events"];
pub const FILTERED_ENTITY_MUT: [&str; 4] = ["bevy_ecs", "world", "entity_ref", "FilteredEntityMut"];
pub const MUT: [&str; 3] = ["bevy_ecs", "change_detection", "Mut"];
pub const MUT_UNTYPED: [&str; 3] = ["bevy_ecs", "change_detection", "MutUntyped"];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: parameter takes `&mut EntityCommands` instead of a re-borrowed `EntityCom
--> tests/ui/borrowed_reborrowable/entity_commands.rs:17:22
|
17 | fn mutable_reference(_param: &mut EntityCommands) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `EntityCommands` instead: `mut _param: bevy::bevy_ecs::system::EntityCommands<'_>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `EntityCommands` instead: `mut _param: bevy::prelude::EntityCommands<'_>`
|
note: the lint level is defined here
--> tests/ui/borrowed_reborrowable/entity_commands.rs:5:9
Expand All @@ -14,7 +14,7 @@ error: parameter takes `&mut EntityCommands` instead of a re-borrowed `EntityCom
--> tests/ui/borrowed_reborrowable/entity_commands.rs:23:33
|
23 | fn mutable_reference_return<'a>(_param: &'a mut EntityCommands) -> usize {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `EntityCommands` instead: `mut _param: bevy::bevy_ecs::system::EntityCommands<'_>`
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `EntityCommands` instead: `mut _param: bevy::prelude::EntityCommands<'_>`

error: aborting due to 2 previous errors

4 changes: 3 additions & 1 deletion bevy_lint/tests/ui/missing_reflect/impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,6 @@ impl Component for MyEvent {
}

//~v NOTE: `Event` implemented here
impl Event for MyEvent {}
impl Event for MyEvent {
type Traversal = ();
}
6 changes: 4 additions & 2 deletions bevy_lint/tests/ui/missing_reflect/impl.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ error: defined an event without a `Reflect` implementation
note: `Event` implemented here
--> tests/ui/missing_reflect/impl.rs:40:1
|
40 | impl Event for MyEvent {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
40 | / impl Event for MyEvent {
41 | | type Traversal = ();
42 | | }
| |_^
note: the lint level is defined here
--> tests/ui/missing_reflect/impl.rs:8:9
|
Expand Down
4 changes: 3 additions & 1 deletion bevy_lint/tests/ui/missing_reflect/impl_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,6 @@ impl Component for &'static &'static &'static MyEvent {
}

//~v NOTE: `Event` implemented here
impl Event for &'static &'static &'static MyEvent {}
impl Event for &'static &'static &'static MyEvent {
type Traversal = ();
}
6 changes: 4 additions & 2 deletions bevy_lint/tests/ui/missing_reflect/impl_ref.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ error: defined an event without a `Reflect` implementation
note: `Event` implemented here
--> tests/ui/missing_reflect/impl_ref.rs:45:1
|
45 | impl Event for &'static &'static &'static MyEvent {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
45 | / impl Event for &'static &'static &'static MyEvent {
46 | | type Traversal = ();
47 | | }
| |_^
note: the lint level is defined here
--> tests/ui/missing_reflect/impl_ref.rs:13:9
|
Expand Down
2 changes: 2 additions & 0 deletions bevy_lint/tests/ui/panicking_methods/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@ fn main() {
//~^ ERROR: called a `World` method that can panic when a non-panicking alternative exists
//~| HELP: use `world.get_entity_mut(bob)`

#[expect(deprecated, reason = "While this method is deprecated, we should still check for it while it exists.")]
world.many_entities([bob]);
//~^ ERROR: called a `World` method that can panic when a non-panicking alternative exists
//~| HELP: use `world.get_many_entities([bob])`

#[expect(deprecated, reason = "While this method is deprecated, we should still check for it while it exists.")]
world.many_entities_mut([bob]);
//~^ ERROR: called a `World` method that can panic when a non-panicking alternative exists
//~| HELP: use `world.get_many_entities_mut([bob])`
Expand Down
Loading

0 comments on commit 7703db0

Please sign in to comment.