Headless by features (#16401)

# Objective

- Fixes #16152 

## Solution

- Put `bevy_window` and `bevy_a11y` behind the `bevy_window` feature.
they were the only difference
- Add `ScheduleRunnerPlugin` to the `DefaultPlugins` when `bevy_window`
is disabled
- Remove `HeadlessPlugins`
- Update the `headless` example
This commit is contained in:
François Mockers 2024-11-16 22:33:37 +01:00 committed by GitHub
parent bce19c1012
commit 6e81a05c93
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 38 additions and 63 deletions

View file

@ -125,6 +125,7 @@ default = [
"bevy_text",
"bevy_ui",
"bevy_ui_picking_backend",
"bevy_window",
"bevy_winit",
"custom_cursor",
"default_font",
@ -218,6 +219,9 @@ bevy_ui = [
"bevy_ui_picking_backend",
]
# Windowing layer
bevy_window = ["bevy_internal/bevy_window"]
# winit window and input backend
bevy_winit = ["bevy_internal/bevy_winit"]

View file

@ -17,7 +17,7 @@ use core::time::Duration;
/// (`ci_testing_config.ron` by default) and executes its specified actions. For a reference of the
/// allowed configuration, see [`CiTestingConfig`].
///
/// This plugin is included within `DefaultPlugins`, `HeadlessPlugins` and `MinimalPlugins`
/// This plugin is included within `DefaultPlugins` and `MinimalPlugins`
/// when the `bevy_ci_testing` feature is enabled.
/// It is recommended to only used this plugin during testing (manual or
/// automatic), and disable it during regular development and for production builds.

View file

@ -97,7 +97,7 @@ serialize = [
"bevy_time/serialize",
"bevy_transform/serialize",
"bevy_ui?/serialize",
"bevy_window/serialize",
"bevy_window?/serialize",
"bevy_winit?/serialize",
]
multi_threaded = [
@ -162,6 +162,7 @@ animation = ["bevy_animation", "bevy_gltf?/bevy_animation"]
bevy_sprite = ["dep:bevy_sprite", "bevy_gizmos?/bevy_sprite"]
bevy_pbr = ["dep:bevy_pbr", "bevy_gizmos?/bevy_pbr"]
bevy_window = ["dep:bevy_window", "dep:bevy_a11y"]
# Used to disable code that is unsupported when Bevy is dynamically linked
dynamic_linking = ["bevy_diagnostic/dynamic_linking"]
@ -248,7 +249,7 @@ ghost_nodes = ["bevy_ui/ghost_nodes"]
[dependencies]
# bevy
bevy_a11y = { path = "../bevy_a11y", version = "0.15.0-dev" }
bevy_a11y = { path = "../bevy_a11y", version = "0.15.0-dev", optional = true }
bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }
bevy_core = { path = "../bevy_core", version = "0.15.0-dev" }
bevy_derive = { path = "../bevy_derive", version = "0.15.0-dev" }
@ -266,7 +267,7 @@ bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
bevy_time = { path = "../bevy_time", version = "0.15.0-dev" }
bevy_transform = { path = "../bevy_transform", version = "0.15.0-dev" }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.15.0-dev" }
bevy_window = { path = "../bevy_window", version = "0.15.0-dev", optional = true }
bevy_tasks = { path = "../bevy_tasks", version = "0.15.0-dev" }
# bevy (optional)
bevy_animation = { path = "../bevy_animation", optional = true, version = "0.15.0-dev" }

View file

@ -13,7 +13,11 @@ plugin_group! {
bevy_hierarchy:::HierarchyPlugin,
bevy_diagnostic:::DiagnosticsPlugin,
bevy_input:::InputPlugin,
#[custom(cfg(not(feature = "bevy_window")))]
bevy_app:::ScheduleRunnerPlugin,
#[cfg(feature = "bevy_window")]
bevy_window:::WindowPlugin,
#[cfg(feature = "bevy_window")]
bevy_a11y:::AccessibilityPlugin,
#[custom(cfg(not(target_arch = "wasm32")))]
bevy_app:::TerminalCtrlCHandlerPlugin,
@ -72,55 +76,6 @@ plugin_group! {
///
/// [`DefaultPlugins`] contains all the plugins typically required to build
/// a *Bevy* application which includes a *window* and presentation components.
/// For *headless* cases without a *window* or presentation, see [`HeadlessPlugins`].
/// For the absolute minimum number of plugins needed to run a Bevy application, see [`MinimalPlugins`].
}
plugin_group! {
/// This plugin group will add all the default plugins for a headless (no *window* or rendering) *Bevy* application:
pub struct HeadlessPlugins {
bevy_app:::PanicHandlerPlugin,
bevy_log:::LogPlugin,
bevy_core:::TaskPoolPlugin,
bevy_core:::TypeRegistrationPlugin,
bevy_core:::FrameCountPlugin,
bevy_time:::TimePlugin,
bevy_transform:::TransformPlugin,
bevy_hierarchy:::HierarchyPlugin,
bevy_diagnostic:::DiagnosticsPlugin,
bevy_app:::ScheduleRunnerPlugin,
#[custom(cfg(not(target_arch = "wasm32")))]
bevy_app:::TerminalCtrlCHandlerPlugin,
#[cfg(feature = "bevy_asset")]
bevy_asset:::AssetPlugin,
#[cfg(feature = "bevy_scene")]
bevy_scene:::ScenePlugin,
#[cfg(feature = "bevy_animation")]
bevy_animation:::AnimationPlugin,
#[cfg(feature = "bevy_state")]
bevy_state::app:::StatesPlugin,
#[cfg(feature = "bevy_ci_testing")]
bevy_dev_tools::ci_testing:::CiTestingPlugin,
#[doc(hidden)]
:IgnoreAmbiguitiesPlugin,
}
/// This group of plugins is intended for use for *headless* programs, for example: dedicated game servers.
/// See the [*Bevy* *headless* example](https://github.com/bevyengine/bevy/blob/main/examples/app/headless.rs)
///
/// [`HeadlessPlugins`] obeys *Cargo* *feature* flags. Users may exert control over this plugin group
/// by disabling `default-features` in their `Cargo.toml` and enabling only those features
/// that they wish to use.
///
/// [`HeadlessPlugins`] contains all the plugins typically required to build
/// a *Bevy* application. In contrast with [`DefaultPlugins`], it leaves out *window* and presentation components.
/// This allows applications built using this plugin group to run on devices that do not have a screen or rendering
/// capabilities.
/// It includes a [schedule runner (`ScheduleRunnerPlugin`)](crate::app::ScheduleRunnerPlugin)
/// to provide functionality that would otherwise be driven by a windowed application's
/// *event loop* or *message loop*.
///
/// Windowed applications that wish to use a reduced set of plugins should consider the
/// [`DefaultPlugins`] plugin group which can be controlled with *Cargo* *feature* flags.
/// For the absolute minimum number of plugins needed to run a Bevy application, see [`MinimalPlugins`].
}
@ -162,8 +117,6 @@ plugin_group! {
}
/// This plugin group represents the absolute minimum, bare-bones, bevy application.
/// Use this if you want to have absolute control over the plugins used.
/// If you are looking to make a *headless* application - without a *window* or rendering,
/// it is usually best to use [`HeadlessPlugins`].
///
/// It includes a [schedule runner (`ScheduleRunnerPlugin`)](crate::app::ScheduleRunnerPlugin)
/// to provide functionality that would otherwise be driven by a windowed application's

View file

@ -13,6 +13,7 @@ pub mod prelude;
mod default_plugins;
pub use default_plugins::*;
#[cfg(feature = "bevy_window")]
pub use bevy_a11y as a11y;
#[cfg(feature = "bevy_animation")]
pub use bevy_animation as animation;
@ -66,6 +67,7 @@ pub use bevy_transform as transform;
#[cfg(feature = "bevy_ui")]
pub use bevy_ui as ui;
pub use bevy_utils as utils;
#[cfg(feature = "bevy_window")]
pub use bevy_window as window;
#[cfg(feature = "bevy_winit")]
pub use bevy_winit as winit;

View file

@ -2,10 +2,13 @@
pub use crate::{
app::prelude::*, core::prelude::*, ecs::prelude::*, hierarchy::prelude::*, input::prelude::*,
log::prelude::*, math::prelude::*, reflect::prelude::*, time::prelude::*,
transform::prelude::*, utils::prelude::*, window::prelude::*, DefaultPlugins, HeadlessPlugins,
MinimalPlugins,
transform::prelude::*, utils::prelude::*, DefaultPlugins, MinimalPlugins,
};
#[doc(hidden)]
#[cfg(feature = "bevy_window")]
pub use crate::window::prelude::*;
#[doc(hidden)]
#[cfg(feature = "bevy_image")]
pub use crate::image::prelude::*;

View file

@ -34,6 +34,7 @@ The default feature set enables most of the expected features of a game engine,
|bevy_text|Provides text functionality|
|bevy_ui|A custom ECS-driven UI framework|
|bevy_ui_picking_backend|Provides an implementation for picking ui|
|bevy_window|Windowing layer|
|bevy_winit|winit window and input backend|
|custom_cursor|Enable winit custom cursor support|
|default_font|Include a default font, containing only ASCII characters, at the cost of a 20kB binary size increase|

View file

@ -1,26 +1,37 @@
//! This example only enables a minimal set of plugins required for bevy to run.
//! You can also completely remove rendering / windowing Plugin code from bevy
//! by making your import look like this in your Cargo.toml.
//! This example shows how to configure the `ScheduleRunnerPlugin` to run your
//! application without windowing. You can completely remove rendering / windowing
//! Plugin code from bevy by making your import look like this in your Cargo.toml.
//!
//! ```toml
//! [dependencies]
//! bevy = { version = "*", default-features = false }
//! # replace "*" with the most recent version of bevy
//! ```
//!
//! And then enabling the features you need.
//! See the full list: <https://docs.rs/bevy/latest/bevy/#cargo-features>
use bevy::{app::ScheduleRunnerPlugin, log::LogPlugin, prelude::*, utils::Duration};
fn main() {
if cfg!(feature = "bevy_window") {
println!("This example is running with the bevy_window feature enabled and will not run headless.");
println!("Disable the default features and rerun the example to run headless.");
println!("To do so, run:");
println!();
println!(" cargo run --example headless --no-default-features");
return;
}
// This app runs once
App::new()
.add_plugins(HeadlessPlugins.set(ScheduleRunnerPlugin::run_once()))
.add_plugins(DefaultPlugins.set(ScheduleRunnerPlugin::run_once()))
.add_systems(Update, hello_world_system)
.run();
// This app loops forever at 60 fps
App::new()
.add_plugins(
HeadlessPlugins
DefaultPlugins
.set(ScheduleRunnerPlugin::run_loop(Duration::from_secs_f64(
1.0 / 60.0,
)))