author | Matt Harbison <matt_harbison@yahoo.com> |
Thu, 20 Sep 2018 17:27:01 -0700 | |
changeset 40324 | 6637b079ae45 |
parent 35607 | 24b5106e3e1e |
child 43818 | ce088b38f92b |
permissions | -rw-r--r-- |
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 |
} |