Skip to content

Commit

Permalink
Use Py_GIL_DISABLED from sysconfig
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Nov 24, 2024
1 parent 7073a84 commit 417eb38
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 18 deletions.
8 changes: 8 additions & 0 deletions src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@ impl BuildOptions {
.get("ABIFLAGS")
.map(ToString::to_string)
.unwrap_or_default();
let gil_disabled = sysconfig_data
.get("Py_GIL_DISABLED")
.map(|x| x == "1")
.unwrap_or_default();
let ext_suffix = sysconfig_data
.get("EXT_SUFFIX")
.context("syconfig didn't define an `EXT_SUFFIX` ಠ_ಠ")?;
Expand All @@ -299,6 +303,7 @@ impl BuildOptions {
abiflags,
ext_suffix: ext_suffix.to_string(),
pointer_width: None,
gil_disabled,
},
executable: PathBuf::new(),
platform: None,
Expand Down Expand Up @@ -376,6 +381,7 @@ impl BuildOptions {
abiflags: "".to_string(),
ext_suffix: ".pyd".to_string(),
pointer_width: None,
gil_disabled: false,
},
executable: PathBuf::new(),
platform: None,
Expand All @@ -402,6 +408,7 @@ impl BuildOptions {
abiflags: "".to_string(),
ext_suffix: ".pyd".to_string(),
pointer_width: None,
gil_disabled: false,
},
executable: PathBuf::new(),
platform: None,
Expand Down Expand Up @@ -441,6 +448,7 @@ impl BuildOptions {
abiflags: "".to_string(),
ext_suffix: "".to_string(),
pointer_width: None,
gil_disabled: false,
},
executable: PathBuf::new(),
platform: None,
Expand Down
1 change: 1 addition & 0 deletions src/cross_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ KEYS = [
"ABIFLAGS",
"EXT_SUFFIX",
"SOABI",
"Py_GIL_DISABLED",
]
for key in KEYS:
print(key, build_time_vars.get(key, ""))
Expand Down
31 changes: 27 additions & 4 deletions src/python_interpreter/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,20 @@ pub struct InterpreterConfig {
#[serde(rename = "interpreter")]
pub interpreter_kind: InterpreterKind,
/// For linux and mac, this contains the value of the abiflags, e.g. "m"
/// for python3.7m or "dm" for python3.6dm. Since python3.8, the value is
/// empty. On windows, the value was always None.
/// for python3.7m or "dm" for python3.6dm.
///
/// * Since python3.8, the value is empty
/// * Since python3.13, the value is "t" for free-threaded builds.
/// * On Windows, the value was always None.
///
/// See PEP 261 and PEP 393 for details
pub abiflags: String,
/// Suffix to use for extension modules as given by sysconfig.
pub ext_suffix: String,
/// Pointer width
pub pointer_width: Option<usize>,
/// Is GIL disabled, i.e. free-threaded build
pub gil_disabled: bool,
}

impl InterpreterConfig {
Expand All @@ -50,6 +55,7 @@ impl InterpreterConfig {
}
let python_ext_arch = target.get_python_ext_arch(python_impl);
let target_env = target.get_python_target_env(python_impl, python_version);
let gil_disabled = abiflags == "t";
match (target.target_os(), python_impl) {
(Os::Linux, CPython) => {
let abiflags = if python_version < (3, 8) {
Expand All @@ -67,6 +73,7 @@ impl InterpreterConfig {
abiflags,
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Linux, PyPy) => {
Expand All @@ -79,6 +86,7 @@ impl InterpreterConfig {
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Macos, CPython) => {
Expand All @@ -96,6 +104,7 @@ impl InterpreterConfig {
abiflags,
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Macos, PyPy) => {
Expand All @@ -107,6 +116,7 @@ impl InterpreterConfig {
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Windows, CPython) => {
Expand All @@ -125,9 +135,11 @@ impl InterpreterConfig {
major,
minor,
interpreter_kind: CPython,
// abiflags is always empty on Windows
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Windows, PyPy) => {
Expand All @@ -140,9 +152,11 @@ impl InterpreterConfig {
major,
minor,
interpreter_kind: PyPy,
// abiflags is always empty on Windows
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::FreeBsd, CPython) => {
Expand All @@ -161,6 +175,7 @@ impl InterpreterConfig {
abiflags,
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::NetBsd, CPython) => {
Expand All @@ -169,10 +184,10 @@ impl InterpreterConfig {
major,
minor,
interpreter_kind: CPython,
// FIXME: netbsd abiflags for free-threaded python?
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::OpenBsd, CPython) => {
Expand All @@ -185,6 +200,7 @@ impl InterpreterConfig {
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(Os::Emscripten, CPython) => {
Expand All @@ -197,6 +213,7 @@ impl InterpreterConfig {
abiflags: String::new(),
ext_suffix,
pointer_width: Some(target.pointer_width()),
gil_disabled,
})
}
(_, _) => None,
Expand Down Expand Up @@ -249,6 +266,7 @@ impl InterpreterConfig {
let mut ext_suffix = None;
let mut abi_tag = None;
let mut pointer_width = None;
let mut build_flags: Option<String> = None;

for (i, line) in lines.enumerate() {
let line = line.context("failed to read line from config")?;
Expand All @@ -262,6 +280,7 @@ impl InterpreterConfig {
"ext_suffix" => parse_value!(ext_suffix, value),
"abi_tag" => parse_value!(abi_tag, value),
"pointer_width" => parse_value!(pointer_width, value),
"build_flags" => parse_value!(build_flags, value),
_ => continue,
}
}
Expand Down Expand Up @@ -340,19 +359,23 @@ impl InterpreterConfig {
} else {
ext_suffix.context("missing value for ext_suffix")?
};
let gil_disabled = build_flags
.map(|flags| flags.contains("Py_GIL_DISABLED"))
.unwrap_or(false);
Ok(Self {
major,
minor,
interpreter_kind,
abiflags: abiflags.unwrap_or_default(),
ext_suffix,
pointer_width,
gil_disabled,
})
}

/// Generate pyo3 config file content
pub fn pyo3_config_file(&self) -> String {
let build_flags = if self.abiflags == "t" {
let build_flags = if self.gil_disabled {
"Py_GIL_DISABLED"
} else {
""
Expand Down
1 change: 1 addition & 0 deletions src/python_interpreter/get_interpreter_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"system": platform.system().lower(),
# This one is for generating a config file for pyo3
"pointer_width": struct.calcsize("P") * 8,
"gil_disabled": sysconfig.get_config_var("Py_GIL_DISABLED") == 1,
}

print(json.dumps(metadata))
29 changes: 15 additions & 14 deletions src/python_interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,13 @@ fn find_all_windows(
Ok(interpreter)
}

fn windows_python_info(executable: &Path) -> Result<Option<InterpreterConfig>> {
struct WindowsPythonInfo {
major: usize,
minor: usize,
pointer_width: Option<usize>,
}

fn windows_python_info(executable: &Path) -> Result<Option<WindowsPythonInfo>> {
let python_info = Command::new(executable)
.arg("-c")
.arg("import sys; print(sys.version)")
Expand Down Expand Up @@ -276,12 +282,9 @@ fn windows_python_info(executable: &Path) -> Result<Option<InterpreterConfig>> {
} else {
32
};
Ok(Some(InterpreterConfig {
Ok(Some(WindowsPythonInfo {
major,
minor,
interpreter_kind: InterpreterKind::CPython,
abiflags: String::new(),
ext_suffix: String::new(),
pointer_width: Some(pointer_width),
}))
} else {
Expand Down Expand Up @@ -353,6 +356,7 @@ struct InterpreterMetadataMessage {
// comes from `platform.system()`
system: String,
soabi: Option<String>,
gil_disabled: bool,
}

/// The location and version of an interpreter
Expand Down Expand Up @@ -425,19 +429,19 @@ fn fun_with_abiflags(
if matches!(message.abiflags.as_deref(), Some("") | None) {
Ok("".to_string())
} else {
bail!("A python 3 interpreter on windows does not define abiflags in its sysconfig ಠ_ಠ")
bail!("A python 3 interpreter on Windows does not define abiflags in its sysconfig ಠ_ಠ")
}
} else if let Some(ref abiflags) = message.abiflags {
if message.minor >= 8 {
// for 3.8, "builds with and without pymalloc are ABI compatible" and the flag dropped
Ok(abiflags.to_string())
} else if (abiflags != "m") && (abiflags != "dm") {
bail!("A python 3 interpreter on linux or mac os must have 'm' or 'dm' as abiflags ಠ_ಠ")
bail!("A python 3 interpreter on Linux or macOS must have 'm' or 'dm' as abiflags ಠ_ಠ")
} else {
Ok(abiflags.to_string())
}
} else {
bail!("A python 3 interpreter on linux or mac os must define abiflags in its sysconfig ಠ_ಠ")
bail!("A python 3 interpreter on Linux or macOS must define abiflags in its sysconfig ಠ_ಠ")
}
}

Expand All @@ -448,7 +452,8 @@ impl PythonInterpreter {
false
} else {
match self.interpreter_kind {
InterpreterKind::CPython => !(self.config.abiflags.starts_with("t")),
// Free-threaded python does not have stable api support yet
InterpreterKind::CPython => !self.config.gil_disabled,
InterpreterKind::PyPy | InterpreterKind::GraalPy => false,
}
}
Expand Down Expand Up @@ -695,6 +700,7 @@ impl PythonInterpreter {
.ext_suffix
.context("syconfig didn't define an `EXT_SUFFIX` ಠ_ಠ")?,
pointer_width: None,
gil_disabled: message.gil_disabled,
},
executable,
platform,
Expand Down Expand Up @@ -924,11 +930,6 @@ impl PythonInterpreter {
venv_base.as_ref().join("Lib").join("site-packages")
}
}

/// Is this a free threaded python interpreter
pub fn is_free_threaded(&self) -> bool {
self.abiflags == "t"
}
}

impl fmt::Display for PythonInterpreter {
Expand Down

0 comments on commit 417eb38

Please sign in to comment.