rust/hgcli/build.rs
branchstable
changeset 44729 26ce8e751503
parent 43818 ce088b38f92b
parent 44638 af739894a4c1
child 45620 426294d06ddc
equal deleted inserted replaced
44692:539490756a72 44729:26ce8e751503
     1 // build.rs -- Configure build environment for `hgcli` Rust package.
     1 // This Source Code Form is subject to the terms of the Mozilla Public
     2 //
     2 // License, v. 2.0. If a copy of the MPL was not distributed with this
     3 // Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
     3 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
     4 //
       
     5 // This software may be used and distributed according to the terms of the
       
     6 // GNU General Public License version 2 or any later version.
       
     7 
     4 
     8 use std::collections::HashMap;
     5 /*! Build script to integrate PyOxidizer. */
     9 use std::env;
       
    10 use std::path::Path;
       
    11 use std::process::Command;
       
    12 
     6 
    13 struct PythonConfig {
     7 fn main() {
    14     python: String,
     8     if let Ok(config_rs) = std::env::var("DEP_PYTHONXY_DEFAULT_PYTHON_CONFIG_RS") {
    15     config: HashMap<String, String>,
     9         println!(
    16 }
    10             "cargo:rustc-env=PYOXIDIZER_DEFAULT_PYTHON_CONFIG_RS={}",
    17 
    11             config_rs
    18 fn get_python_config() -> PythonConfig {
       
    19     // The python27-sys crate exports a Cargo variable defining the full
       
    20     // path to the interpreter being used.
       
    21     let python = env::var("DEP_PYTHON27_PYTHON_INTERPRETER")
       
    22         .expect("Missing DEP_PYTHON27_PYTHON_INTERPRETER; bad python27-sys crate?");
       
    23 
       
    24     if !Path::new(&python).exists() {
       
    25         panic!(
       
    26             "Python interpreter {} does not exist; this should never happen",
       
    27             python
       
    28         );
    12         );
    29     }
    13     } else {
    30 
    14         panic!("unable to find build artifacts generated by pyembed crate");
    31     // This is a bit hacky but it gets the job done.
       
    32     let separator = "SEPARATOR STRING";
       
    33 
       
    34     let script = "import sysconfig; \
       
    35                   c = sysconfig.get_config_vars(); \
       
    36                   print('SEPARATOR STRING'.join('%s=%s' % i for i in c.items()))";
       
    37 
       
    38     let mut command = Command::new(&python);
       
    39     command.arg("-c").arg(script);
       
    40 
       
    41     let out = command.output().unwrap();
       
    42 
       
    43     if !out.status.success() {
       
    44         panic!(
       
    45             "python script failed: {}",
       
    46             String::from_utf8_lossy(&out.stderr)
       
    47         );
       
    48     }
       
    49 
       
    50     let stdout = String::from_utf8_lossy(&out.stdout);
       
    51     let mut m = HashMap::new();
       
    52 
       
    53     for entry in stdout.split(separator) {
       
    54         let mut parts = entry.splitn(2, "=");
       
    55         let key = parts.next().unwrap();
       
    56         let value = parts.next().unwrap();
       
    57         m.insert(String::from(key), String::from(value));
       
    58     }
       
    59 
       
    60     PythonConfig {
       
    61         python: python,
       
    62         config: m,
       
    63     }
    15     }
    64 }
    16 }
    65 
       
    66 #[cfg(not(target_os = "windows"))]
       
    67 fn have_shared(config: &PythonConfig) -> bool {
       
    68     match config.config.get("Py_ENABLE_SHARED") {
       
    69         Some(value) => value == "1",
       
    70         None => false,
       
    71     }
       
    72 }
       
    73 
       
    74 #[cfg(target_os = "windows")]
       
    75 fn have_shared(config: &PythonConfig) -> bool {
       
    76     use std::path::PathBuf;
       
    77 
       
    78     // python27.dll should exist next to python2.7.exe.
       
    79     let mut dll = PathBuf::from(&config.python);
       
    80     dll.pop();
       
    81     dll.push("python27.dll");
       
    82 
       
    83     return dll.exists();
       
    84 }
       
    85 
       
    86 const REQUIRED_CONFIG_FLAGS: [&str; 2] = ["Py_USING_UNICODE", "WITH_THREAD"];
       
    87 
       
    88 fn main() {
       
    89     let config = get_python_config();
       
    90 
       
    91     println!("Using Python: {}", config.python);
       
    92     println!("cargo:rustc-env=PYTHON_INTERPRETER={}", config.python);
       
    93 
       
    94     let prefix = config.config.get("prefix").unwrap();
       
    95 
       
    96     println!("Prefix: {}", prefix);
       
    97 
       
    98     // TODO Windows builds don't expose these config flags. Figure out another
       
    99     // way.
       
   100     #[cfg(not(target_os = "windows"))]
       
   101     for key in REQUIRED_CONFIG_FLAGS.iter() {
       
   102         let result = match config.config.get(*key) {
       
   103             Some(value) => value == "1",
       
   104             None => false,
       
   105         };
       
   106 
       
   107         if !result {
       
   108             panic!("Detected Python requires feature {}", key);
       
   109         }
       
   110     }
       
   111 
       
   112     // We need a Python shared library.
       
   113     if !have_shared(&config) {
       
   114         panic!("Detected Python lacks a shared library, which is required");
       
   115     }
       
   116 
       
   117     let ucs4 = match config.config.get("Py_UNICODE_SIZE") {
       
   118         Some(value) => value == "4",
       
   119         None => false,
       
   120     };
       
   121 
       
   122     if !ucs4 {
       
   123         #[cfg(not(target_os = "windows"))]
       
   124         panic!("Detected Python doesn't support UCS-4 code points");
       
   125     }
       
   126 }