rust/hgcli/build.rs
author Martin von Zweigbergk <martinvonz@google.com>
Wed, 11 Dec 2019 15:06:09 -0800
changeset 43910 c41ed5d4f770
parent 43818 ce088b38f92b
child 44729 26ce8e751503
permissions -rw-r--r--
config: close file even if we fail to read it If we get an exception from cfg.read(), we would not close the file before this patch. This patch uses a context manager to make sure we close it. Differential Revision: https://phab.mercurial-scm.org/D7626
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     1
// build.rs -- Configure build environment for `hgcli` Rust package.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     2
//
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     3
// Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     4
//
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     5
// This software may be used and distributed according to the terms of the
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     6
// GNU General Public License version 2 or any later version.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     7
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     8
use std::collections::HashMap;
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
     9
use std::env;
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    10
use std::path::Path;
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    11
use std::process::Command;
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    12
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    13
struct PythonConfig {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    14
    python: String,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    15
    config: HashMap<String, String>,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    16
}
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    17
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    18
fn get_python_config() -> PythonConfig {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    19
    // The python27-sys crate exports a Cargo variable defining the full
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    20
    // path to the interpreter being used.
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35607
diff changeset
    21
    let python = env::var("DEP_PYTHON27_PYTHON_INTERPRETER")
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35607
diff changeset
    22
        .expect("Missing DEP_PYTHON27_PYTHON_INTERPRETER; bad python27-sys crate?");
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    23
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    24
    if !Path::new(&python).exists() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    25
        panic!(
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    26
            "Python interpreter {} does not exist; this should never happen",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    27
            python
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    28
        );
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    29
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    30
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    31
    // This is a bit hacky but it gets the job done.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    32
    let separator = "SEPARATOR STRING";
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    33
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    34
    let script = "import sysconfig; \
43818
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35607
diff changeset
    35
                  c = sysconfig.get_config_vars(); \
ce088b38f92b rust: run rustfmt
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35607
diff changeset
    36
                  print('SEPARATOR STRING'.join('%s=%s' % i for i in c.items()))";
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    37
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    38
    let mut command = Command::new(&python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    39
    command.arg("-c").arg(script);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    40
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    41
    let out = command.output().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    42
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    43
    if !out.status.success() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    44
        panic!(
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    45
            "python script failed: {}",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    46
            String::from_utf8_lossy(&out.stderr)
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    47
        );
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    48
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    49
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    50
    let stdout = String::from_utf8_lossy(&out.stdout);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    51
    let mut m = HashMap::new();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    52
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    53
    for entry in stdout.split(separator) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    54
        let mut parts = entry.splitn(2, "=");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    55
        let key = parts.next().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    56
        let value = parts.next().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    57
        m.insert(String::from(key), String::from(value));
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    58
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    59
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    60
    PythonConfig {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    61
        python: python,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    62
        config: m,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    63
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    64
}
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    65
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    66
#[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    67
fn have_shared(config: &PythonConfig) -> bool {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    68
    match config.config.get("Py_ENABLE_SHARED") {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    69
        Some(value) => value == "1",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    70
        None => false,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    71
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    72
}
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    73
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    74
#[cfg(target_os = "windows")]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    75
fn have_shared(config: &PythonConfig) -> bool {
35603
11c86ab69e67 rust: move import of PathBuf
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35569
diff changeset
    76
    use std::path::PathBuf;
11c86ab69e67 rust: move import of PathBuf
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35569
diff changeset
    77
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    78
    // python27.dll should exist next to python2.7.exe.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    79
    let mut dll = PathBuf::from(&config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    80
    dll.pop();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    81
    dll.push("python27.dll");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    82
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    83
    return dll.exists();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    84
}
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    85
35607
24b5106e3e1e rust: avoid redundant 'static lifetime
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35603
diff changeset
    86
const REQUIRED_CONFIG_FLAGS: [&str; 2] = ["Py_USING_UNICODE", "WITH_THREAD"];
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    87
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    88
fn main() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    89
    let config = get_python_config();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    90
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    91
    println!("Using Python: {}", config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    92
    println!("cargo:rustc-env=PYTHON_INTERPRETER={}", config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    93
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    94
    let prefix = config.config.get("prefix").unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    95
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    96
    println!("Prefix: {}", prefix);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    97
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    98
    // TODO Windows builds don't expose these config flags. Figure out another
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    99
    // way.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   100
    #[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   101
    for key in REQUIRED_CONFIG_FLAGS.iter() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   102
        let result = match config.config.get(*key) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   103
            Some(value) => value == "1",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   104
            None => false,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   105
        };
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   106
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   107
        if !result {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   108
            panic!("Detected Python requires feature {}", key);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   109
        }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   110
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   111
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   112
    // We need a Python shared library.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   113
    if !have_shared(&config) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   114
        panic!("Detected Python lacks a shared library, which is required");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   115
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   116
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   117
    let ucs4 = match config.config.get("Py_UNICODE_SIZE") {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   118
        Some(value) => value == "4",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   119
        None => false,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   120
    };
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   121
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   122
    if !ucs4 {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   123
        #[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   124
        panic!("Detected Python doesn't support UCS-4 code points");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   125
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   126
}