diff --git a/Changelog.md b/Changelog.md index 702a7c558..c13f392e9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add support for using [`zig cc`](https://andrewkelley.me/post/zig-cc-powerful-drop-in-replacement-gcc-clang.html) as linker for easier cross compiling and manylinux compliance in [#756](https://github.com/PyO3/maturin/pull/756) * Switch from reqwest to ureq to reduce dependencies in [#767](https://github.com/PyO3/maturin/pull/767) * Fix missing Python submodule in wheel in [#772](https://github.com/PyO3/maturin/pull/772) +* Add support for specifying cargo manifest path in pyproject.toml in [#781](https://github.com/PyO3/maturin/pull/781) ## [0.12.6] - 2021-12-31 diff --git a/src/build_options.rs b/src/build_options.rs index c269444e3..59d246480 100644 --- a/src/build_options.rs +++ b/src/build_options.rs @@ -47,15 +47,9 @@ pub struct BuildOptions { /// Which kind of bindings to use. Possible values are pyo3, rust-cpython, cffi and bin #[clap(short, long)] pub bindings: Option, - #[clap( - short = 'm', - long = "manifest-path", - parse(from_os_str), - default_value = "Cargo.toml", - name = "PATH" - )] + #[clap(short = 'm', long = "manifest-path", parse(from_os_str), name = "PATH")] /// The path to the Cargo.toml - pub manifest_path: PathBuf, + pub manifest_path: Option, /// The directory to store the built wheels in. Defaults to a new "wheels" /// directory in the project's target directory #[clap(short, long, parse(from_os_str))] @@ -99,7 +93,7 @@ impl Default for BuildOptions { platform_tag: None, interpreter: Some(vec![]), bindings: None, - manifest_path: PathBuf::from("Cargo.toml"), + manifest_path: None, out: None, skip_auditwheel: false, zig: false, @@ -112,6 +106,31 @@ impl Default for BuildOptions { } impl BuildOptions { + /// Get cargo manifest file path + fn manifest_path(&self) -> Result { + // use command line argument if specified + if let Some(path) = &self.manifest_path { + return Ok(path.clone()); + } + // check `manifest-path` option in pyproject.toml + let current_dir = env::current_dir().context("Failed to detect current directory ಠ_ಠ")?; + let pyproject = PyProjectToml::new(¤t_dir).context("pyproject.toml is invalid")?; + if let Some(path) = pyproject.manifest_path() { + println!("🔗 Found cargo manifest path in pyproject.toml"); + return Ok(path.to_path_buf()); + } + // check Cargo.toml in current directory + let path = PathBuf::from("Cargo.toml"); + if path.exists() { + Ok(path) + } else { + Err(format_err!( + "Can't find {} (in {})", + path.display(), + current_dir.display() + )) + } + } /// Tries to fill the missing metadata for a BuildContext by querying cargo and python pub fn into_build_context( self, @@ -119,21 +138,10 @@ impl BuildOptions { strip: bool, editable: bool, ) -> Result { - let manifest_file = &self.manifest_path; - if !manifest_file.exists() { - let current_dir = - env::current_dir().context("Failed to detect current directory ಠ_ಠ")?; - bail!( - "Can't find {} (in {})", - self.manifest_path.display(), - current_dir.display() - ); - } - + let manifest_file = self.manifest_path()?; if !manifest_file.is_file() { bail!( - "{} (resolved to {}) is not the path to a Cargo.toml", - self.manifest_path.display(), + "{} is not the path to a Cargo.toml", manifest_file.display() ); } @@ -195,7 +203,7 @@ impl BuildOptions { let cargo_metadata_extra_args = extract_cargo_metadata_args(&cargo_extra_args)?; let result = MetadataCommand::new() - .manifest_path(&self.manifest_path) + .manifest_path(&manifest_file) .other_options(cargo_metadata_extra_args) .exec(); @@ -318,7 +326,7 @@ impl BuildOptions { metadata21, crate_name: crate_name.to_string(), module_name, - manifest_path: self.manifest_path, + manifest_path: manifest_file, out: wheel_dir, release, strip, diff --git a/src/develop.rs b/src/develop.rs index acf8c905a..679fef33e 100644 --- a/src/develop.rs +++ b/src/develop.rs @@ -32,7 +32,7 @@ pub fn develop( platform_tag: Some(PlatformTag::Linux), interpreter: Some(vec![python.clone()]), bindings, - manifest_path: manifest_file.to_path_buf(), + manifest_path: Some(manifest_file.to_path_buf()), out: Some(wheel_dir.path().to_path_buf()), skip_auditwheel: false, zig: false, diff --git a/src/main.rs b/src/main.rs index f2c649f02..c546305aa 100644 --- a/src/main.rs +++ b/src/main.rs @@ -299,7 +299,7 @@ fn pep517(subcommand: Pep517Command) -> Result<()> { manifest_path, } => { let build_options = BuildOptions { - manifest_path, + manifest_path: Some(manifest_path), out: Some(sdist_directory), ..Default::default() }; @@ -405,7 +405,7 @@ fn run() -> Result<()> { } Opt::SDist { manifest_path, out } => { let build_options = BuildOptions { - manifest_path, + manifest_path: Some(manifest_path), out, ..Default::default() }; diff --git a/src/pyproject_toml.rs b/src/pyproject_toml.rs index 4a1a71acd..6a52aa50e 100644 --- a/src/pyproject_toml.rs +++ b/src/pyproject_toml.rs @@ -3,7 +3,7 @@ use anyhow::{format_err, Context, Result}; use pyproject_toml::PyProjectToml as ProjectToml; use serde::{Deserialize, Serialize}; use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; /// The `[tool]` section of a pyproject.toml #[derive(Serialize, Deserialize, Debug, Clone)] @@ -16,6 +16,7 @@ pub struct Tool { #[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "kebab-case")] pub struct ToolMaturin { + manifest_path: Option, sdist_include: Option>, bindings: Option, cargo_extra_args: Option, @@ -119,6 +120,16 @@ impl PyProjectToml { .unwrap_or_default() } + /// Returns the value of `[tool.maturin.manifest-path]` in pyproject.toml + pub fn manifest_path(&self) -> Option<&Path> { + self.tool + .as_ref()? + .maturin + .as_ref()? + .manifest_path + .as_deref() + } + /// Having a pyproject.toml without a version constraint is a bad idea /// because at some point we'll have to do breaking changes and then source /// distributions would break diff --git a/tests/common/other.rs b/tests/common/other.rs index cf64f2ba2..651b980b8 100644 --- a/tests/common/other.rs +++ b/tests/common/other.rs @@ -116,7 +116,7 @@ pub fn test_source_distribution( let sdist_directory = Path::new("test-crates").join("wheels").join(unique_name); let build_options = BuildOptions { - manifest_path, + manifest_path: Some(manifest_path), out: Some(sdist_directory), cargo_extra_args: vec![ "--quiet".to_string(),