1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
fn download_sources() {
#[cfg(feature = "download-sources")]
{
const VERSION: &str = env!("CARGO_PKG_VERSION");
use std::fs;
use std::path::{Path, PathBuf};
fn copy<U: AsRef<Path>, V: AsRef<Path>>(from: U, to: V) -> Result<(), std::io::Error> {
let mut stack = Vec::new();
stack.push(PathBuf::from(from.as_ref()));
let output_root = PathBuf::from(to.as_ref());
let input_root = PathBuf::from(from.as_ref()).components().count();
while let Some(working_path) = stack.pop() {
// Generate a relative path
let src: PathBuf = working_path.components().skip(input_root).collect();
// Create a destination if missing
let dest = if src.components().count() == 0 {
output_root.clone()
} else {
output_root.join(&src)
};
if fs::metadata(&dest).is_err() {
fs::create_dir_all(&dest)?;
}
for entry in fs::read_dir(working_path)? {
let entry = entry?;
let path = entry.path();
if path.is_dir() {
stack.push(path);
} else {
match path.file_name() {
Some(filename) => {
let dest_path = dest.join(filename);
fs::copy(&path, &dest_path)?;
}
None => {
panic!("Cannot read: {:?}", path);
}
}
}
}
}
Ok(())
}
match fs::remove_dir_all("sdk") {
Ok(()) => (),
Err(err) if err.kind() == std::io::ErrorKind::NotFound => (),
Err(err) => panic!("cannot remove old sdk/ repo: {}", err),
}
let download = std::process::Command::new("git").arg("clone")
.arg("--depth")
.arg("1")
.arg("--branch")
.arg(VERSION)
.arg("--single-branch")
.arg("git@github.com:dart-lang/sdk.git")
.output()
.expect("To download sources");
if !download.status.success() {
let stderr = String::from_utf8(download.stderr).expect("stderr is not utf-8");
panic!("Failed to download dart sdk: {}", stderr);
}
let source = ["sdk", "runtime", "include"].iter().collect::<PathBuf>();
let _ = fs::remove_dir_all("dart");
copy(source, "dart").expect("To copy dart headers");
let _ = fs::remove_dir_all("sdk");
}
}
fn generate_lib() {
#[cfg(feature = "build-bindings")]
{
use std::path::PathBuf;
const PREPEND_LIB: &'static str = "
#![no_std]
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
";
let out = PathBuf::new().join("src").join("lib.rs");
let bindings = bindgen::Builder::default().header("dart/dart_native_api.h")
.header("dart/dart_tools_api.h")
.raw_line(PREPEND_LIB)
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
.generate_comments(false)
.layout_tests(false)
.allowlist_type("_*Dart.+")
.allowlist_function("_*Dart.+")
.allowlist_var("_*Dart.+")
.ctypes_prefix("libc")
//do not use bindgen rustfmt as it produces bad
//line endings on windows when you force unix
//files
.formatter(bindgen::Formatter::None)
.use_core()
.generate()
.expect("Unable to generate bindings");
bindings.write_to_file(out).expect("Couldn't write bindings!");
let fmt = std::process::Command::new("rustfmt").arg("src/lib.rs")
.status()
.map(|status| status.success())
.unwrap_or(false);
if !fmt {
println!("cargo:warning=cannot format bindings");
}
}
}
fn main() {
download_sources();
generate_lib();
}