rust/hgcli/build.rs
author Gregory Szorc <gregory.szorc@gmail.com>
Wed, 10 Jan 2018 19:24:58 -0800
changeset 35607 24b5106e3e1e
parent 35603 11c86ab69e67
child 43818 ce088b38f92b
permissions -rw-r--r--
rust: avoid redundant 'static lifetime 'static is apparently automatic for const variables. Differential Revision: https://phab.mercurial-scm.org/D1846
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.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    21
    let python = env::var("DEP_PYTHON27_PYTHON_INTERPRETER").expect(
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    22
        "Missing DEP_PYTHON27_PYTHON_INTERPRETER; bad python27-sys crate?",
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    25
    if !Path::new(&python).exists() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    26
        panic!(
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    27
            "Python interpreter {} does not exist; this should never happen",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    28
            python
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    32
    // 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
    33
    let separator = "SEPARATOR STRING";
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    34
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    35
    let script = "import sysconfig; \
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    36
c = sysconfig.get_config_vars(); \
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    37
print('SEPARATOR STRING'.join('%s=%s' % i for i in c.items()))";
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    38
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    39
    let mut command = Command::new(&python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    40
    command.arg("-c").arg(script);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    41
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    42
    let out = command.output().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    43
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    44
    if !out.status.success() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    45
        panic!(
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    46
            "python script failed: {}",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    47
            String::from_utf8_lossy(&out.stderr)
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    51
    let stdout = String::from_utf8_lossy(&out.stdout);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    52
    let mut m = HashMap::new();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    53
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    54
    for entry in stdout.split(separator) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    55
        let mut parts = entry.splitn(2, "=");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    56
        let key = parts.next().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    57
        let value = parts.next().unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    58
        m.insert(String::from(key), String::from(value));
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    61
    PythonConfig {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    62
        python: python,
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    63
        config: m,
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    67
#[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    68
fn have_shared(config: &PythonConfig) -> bool {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    69
    match config.config.get("Py_ENABLE_SHARED") {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    70
        Some(value) => value == "1",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    71
        None => false,
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    75
#[cfg(target_os = "windows")]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    76
fn have_shared(config: &PythonConfig) -> bool {
35603
11c86ab69e67 rust: move import of PathBuf
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35569
diff changeset
    77
    use std::path::PathBuf;
11c86ab69e67 rust: move import of PathBuf
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35569
diff changeset
    78
35569
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    79
    // python27.dll should exist next to python2.7.exe.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    80
    let mut dll = PathBuf::from(&config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    81
    dll.pop();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    82
    dll.push("python27.dll");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    83
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    84
    return dll.exists();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    85
}
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    86
35607
24b5106e3e1e rust: avoid redundant 'static lifetime
Gregory Szorc <gregory.szorc@gmail.com>
parents: 35603
diff changeset
    87
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
    88
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    89
fn main() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    90
    let config = get_python_config();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    91
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    92
    println!("Using Python: {}", config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    93
    println!("cargo:rustc-env=PYTHON_INTERPRETER={}", config.python);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    94
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    95
    let prefix = config.config.get("prefix").unwrap();
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    96
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    97
    println!("Prefix: {}", prefix);
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    98
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
    99
    // 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
   100
    // way.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   101
    #[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   102
    for key in REQUIRED_CONFIG_FLAGS.iter() {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   103
        let result = match config.config.get(*key) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   104
            Some(value) => value == "1",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   105
            None => false,
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   108
        if !result {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   109
            panic!("Detected Python requires feature {}", key);
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   113
    // We need a Python shared library.
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   114
    if !have_shared(&config) {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   115
        panic!("Detected Python lacks a shared library, which is required");
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   118
    let ucs4 = match config.config.get("Py_UNICODE_SIZE") {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   119
        Some(value) => value == "4",
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   120
        None => false,
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
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   123
    if !ucs4 {
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   124
        #[cfg(not(target_os = "windows"))]
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   125
        panic!("Detected Python doesn't support UCS-4 code points");
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   126
    }
964212780daf rust: implementation of `hg`
Gregory Szorc <gregory.szorc@gmail.com>
parents:
diff changeset
   127
}