From 33119c68f1f0fb2366f30c7eca283c27526bc55d Mon Sep 17 00:00:00 2001 From: messense Date: Sun, 19 Jul 2026 15:56:05 +0800 Subject: [PATCH] feat: support --pgo for maturin develop Add a --pgo flag to `maturin develop` that runs the same three-phase PGO build as `maturin build --pgo`. Since PGO-optimizing a debug build makes no sense, --pgo implies the release profile unless another profile is explicitly requested with --profile. Closes #3255 --- guide/src/local_development.md | 7 +++++++ src/develop/mod.rs | 16 ++++++++++++++++ tests/cmd/develop.stdout | 8 ++++++++ tests/common/develop.rs | 1 + 4 files changed, 32 insertions(+) diff --git a/guide/src/local_development.md b/guide/src/local_development.md index f94cc4e74..8d7c0f338 100644 --- a/guide/src/local_development.md +++ b/guide/src/local_development.md @@ -20,6 +20,13 @@ Options: [possible values: pyo3, pyo3-ffi, cffi, uniffi, bin] + --pgo + Build with Profile-Guided Optimization (PGO). + + Requires `pgo-command` to be set in `[tool.maturin]` in pyproject.toml. This performs a three-phase build: instrumented build, profile training, and optimized rebuild. + + Implies `--release` unless `--profile` is specified. + --strip Strip the library for minimum file size diff --git a/src/develop/mod.rs b/src/develop/mod.rs index 1c4d4e44c..40b2b3039 100644 --- a/src/develop/mod.rs +++ b/src/develop/mod.rs @@ -39,6 +39,15 @@ pub struct DevelopOptions { /// Pass --release to cargo #[arg(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS, conflicts_with = "profile")] pub release: bool, + /// Build with Profile-Guided Optimization (PGO). + /// + /// Requires `pgo-command` to be set in `[tool.maturin]` in pyproject.toml. + /// This performs a three-phase build: instrumented build, profile training, + /// and optimized rebuild. + /// + /// Implies `--release` unless `--profile` is specified. + #[arg(long)] + pub pgo: bool, /// Strip the library for minimum file size #[arg(long)] pub strip: bool, @@ -324,6 +333,7 @@ pub fn develop(develop_options: DevelopOptions, venv_dir: &Path) -> Result<()> { let DevelopOptions { bindings, release, + pgo, strip, extras, group, @@ -340,6 +350,11 @@ pub fn develop(develop_options: DevelopOptions, venv_dir: &Path) -> Result<()> { if release { cargo_options.profile = Some("release".to_string()); } + // PGO-optimizing a debug build makes no sense, so `--pgo` implies the + // release profile unless another profile was requested explicitly + if pgo && cargo_options.profile.is_none() { + cargo_options.profile = Some("release".to_string()); + } let mut target_triple = cargo_options.target.clone(); let target = Target::from_target_triple(cargo_options.target.as_ref())?; @@ -385,6 +400,7 @@ pub fn develop(develop_options: DevelopOptions, venv_dir: &Path) -> Result<()> { .into_build_context() .strip(if strip { Some(true) } else { None }) .editable(true) + .pgo(pgo) .build()?; // Ensure that version information is present, https://github.com/PyO3/maturin/issues/2416 diff --git a/tests/cmd/develop.stdout b/tests/cmd/develop.stdout index cde0da044..a90f96982 100644 --- a/tests/cmd/develop.stdout +++ b/tests/cmd/develop.stdout @@ -12,6 +12,14 @@ Options: [possible values: pyo3, pyo3-ffi, cffi, uniffi, bin] + --pgo + Build with Profile-Guided Optimization (PGO). + + Requires `pgo-command` to be set in `[tool.maturin]` in pyproject.toml. This performs a + three-phase build: instrumented build, profile training, and optimized rebuild. + + Implies `--release` unless `--profile` is specified. + --strip Strip the library for minimum file size diff --git a/tests/common/develop.rs b/tests/common/develop.rs index 4b324d074..730467440 100644 --- a/tests/common/develop.rs +++ b/tests/common/develop.rs @@ -105,6 +105,7 @@ pub fn test_develop(case: &DevelopCase<'_>) -> Result<()> { let develop_options = DevelopOptions { bindings: case.bindings.map(|binding| binding.to_owned()), release: false, + pgo: false, strip: false, extras: Vec::new(), group: Vec::new(),