Skip to content

Commit

Permalink
use sys.maxsize rather than platform.machine()
Browse files Browse the repository at this point in the history
platform.machine() gives the wrong answer if you're running 32-bit
Python on a 64-bit machine. sys.maxsize gives the answer we want. See
also https://stackoverflow.com/a/1405971/823869.

Also use CARGO_CFG_TARGET_POINTER_WIDTH rather than inferring the
pointer width from CARGO_CFG_TARGET_ARCH.
  • Loading branch information
oconnor663 committed Mar 23, 2020
1 parent 1c1d3c4 commit 010b842
Showing 1 changed file with 31 additions and 21 deletions.
52 changes: 31 additions & 21 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ struct InterpreterConfig {
base_prefix: String,
executable: String,
machine: String,
maxsize_bits: Option<u32>,
}

#[derive(Deserialize, Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -181,6 +182,7 @@ fn load_cross_compile_info() -> Result<(InterpreterConfig, HashMap<String, Strin
base_prefix: "".to_string(),
executable: "".to_string(),
machine: "".to_string(),
maxsize_bits: None,
};

Ok((interpreter_config, fix_config_map(config_map)))
Expand Down Expand Up @@ -456,7 +458,8 @@ print(json.dumps({
"base_prefix": base_prefix,
"shared": PYPY or bool(sysconfig.get_config_var('Py_ENABLE_SHARED')),
"executable": sys.executable,
"machine": platform.machine()
"machine": platform.machine(),
"maxsize_bits": sys.maxsize.bit_length(),
}))
"#;
let json = run_python_script(interpreter, script)?;
Expand All @@ -475,7 +478,7 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<String> {
}
}

check_target_architecture(&interpreter_config.machine)?;
check_target_architecture(interpreter_config)?;

let is_extension_module = env::var_os("CARGO_FEATURE_EXTENSION_MODULE").is_some();
if !is_extension_module || cfg!(target_os = "windows") {
Expand Down Expand Up @@ -517,32 +520,39 @@ fn configure(interpreter_config: &InterpreterConfig) -> Result<String> {
Ok(flags)
}

fn check_target_architecture(python_machine: &str) -> Result<()> {
fn check_target_architecture(interpreter_config: &InterpreterConfig) -> Result<()> {
// Try to check whether the target architecture matches the python library
let target_arch = match env::var("CARGO_CFG_TARGET_ARCH")
.as_ref()
.map(|e| e.as_str())
{
Ok("x86_64") => Some("64-bit"),
Ok("x86") => Some("32-bit"),
_ => None, // It might be possible to recognise other architectures, this will do for now.
let rust_target = match env::var("CARGO_CFG_TARGET_POINTER_WIDTH")?.as_str() {
"64" => "64-bit",
"32" => "32-bit",
x => bail!("unexpected Rust target pointer width: {}", x),
};

let python_arch = match python_machine {
"AMD64" | "x86_64" => Some("64-bit"),
"i686" | "x86" => Some("32-bit"),
_ => None, // It might be possible to recognise other architectures, this will do for now.
// Why are we using at sys.maxsize here, rather than just
// platform.architecture()? Because the latter can give weird results on
// macOS. See https://stackoverflow.com/a/1405971/823869.
let python_target = match interpreter_config.maxsize_bits {
// sys.maxsize is a signed value, so it's one bit shorter than the
// pointer width.
Some(63) => "64-bit",
Some(31) => "32-bit",
None => {
// Unset, e.g. because we're cross-compiling. Don't check anything
// in this case.
return Ok(());
}
Some(n) => bail!("unexpected Python maxsize_bits: {}", n),
};

match (target_arch, python_arch) {
// If we could recognise both, and they're different, fail.
(Some(t), Some(p)) if p != t => bail!(
if rust_target != python_target {
bail!(
"Your Rust target architecture ({}) does not match your python interpreter ({})",
t,
p
),
_ => Ok(()),
rust_target,
python_target
);
}

Ok(())
}

fn check_rustc_version() -> Result<()> {
Expand Down

0 comments on commit 010b842

Please sign in to comment.