-
Notifications
You must be signed in to change notification settings - Fork 79
/
build.rs
187 lines (162 loc) · 6.69 KB
/
build.rs
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use fil_actor_bundler::Bundler;
use fil_actors_runtime::runtime::builtins::Type;
use num_traits::cast::FromPrimitive;
use std::error::Error;
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::{Command, Stdio};
use std::thread;
/// Cargo package for an actor.
type Package = str;
/// Technical identifier for the actor in legacy CodeCIDs and else.
type ID = str;
const ACTORS: &[(&Package, &ID)] = &[
("system", "system"),
("init", "init"),
("cron", "cron"),
("account", "account"),
("power", "storagepower"),
("miner", "storageminer"),
("market", "storagemarket"),
("paych", "paymentchannel"),
("multisig", "multisig"),
("reward", "reward"),
("verifreg", "verifiedregistry"),
("datacap", "datacap"),
("placeholder", "placeholder"),
("evm", "evm"),
("eam", "eam"),
("ethaccount", "ethaccount"),
];
const NETWORK_ENV: &str = "BUILD_FIL_NETWORK";
/// Returns the configured network name, checking both the environment and feature flags.
fn network_name() -> String {
let env_network = std::env::var_os(NETWORK_ENV);
let feat_network = if cfg!(feature = "mainnet") {
Some("mainnet")
} else if cfg!(feature = "caterpillarnet") {
Some("caterpillarnet")
} else if cfg!(feature = "butterflynet") {
Some("butterflynet")
} else if cfg!(feature = "calibrationnet") {
Some("calibrationnet")
} else if cfg!(feature = "devnet") {
Some("devnet")
} else if cfg!(feature = "testing") {
Some("testing")
} else if cfg!(feature = "testing-fake-proofs") {
Some("testing-fake-proofs")
} else {
None
};
// Make sure they match if they're both set. Otherwise, pick the one
// that's set, or fallback on "mainnet".
match (feat_network, &env_network) {
(Some(from_feature), Some(from_env)) => {
assert_eq!(from_feature, from_env, "different target network configured via the features than via the {} environment variable", NETWORK_ENV);
from_feature
}
(Some(net), None) => net,
(None, Some(net)) => net.to_str().expect("network name not utf8"),
(None, None) => "mainnet",
}.to_owned()
}
fn main() -> Result<(), Box<dyn Error>> {
// Cargo executable location.
let cargo = std::env::var_os("CARGO").expect("no CARGO env var");
println!("cargo:warning=cargo: {:?}", &cargo);
let out_dir = std::env::var_os("OUT_DIR")
.as_ref()
.map(Path::new)
.map(|p| p.join("bundle"))
.expect("no OUT_DIR env var");
println!("cargo:warning=out_dir: {:?}", &out_dir);
// Compute the package names.
let packages =
ACTORS.iter().map(|(pkg, _)| String::from("fil_actor_") + pkg).collect::<Vec<String>>();
let manifest_path =
Path::new(&std::env::var_os("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR unset"))
.join("Cargo.toml");
println!("cargo:warning=manifest_path={:?}", &manifest_path);
// Determine the network name.
let network_name = network_name();
println!("cargo:warning=network name: {}", network_name);
// Make sure we re-build if the network name changes.
println!("cargo:rerun-if-env-changed={}", NETWORK_ENV);
// Rerun if the source, dependencies, build options, build script _or_ actors have changed. We
// need to check if the actors have changed because otherwise, when building in a workspace, we
// won't re-run the build script and therefore won't re-compile them.
//
// This _isn't_ an issue when building as a dependency fetched from crates.io (because the crate
// is immutable).
for file in ["actors", "Cargo.toml", "Cargo.lock", "src", "build.rs"] {
println!("cargo:rerun-if-changed={}", file);
}
// Cargo build command for all actors at once.
let mut cmd = Command::new(&cargo);
cmd.arg("build")
.args(packages.iter().map(|pkg| "-p=".to_owned() + pkg))
.arg("--target=wasm32-unknown-unknown")
.arg("--profile=wasm")
.arg("--locked")
.arg("--features=fil-actor")
.arg("--manifest-path=".to_owned() + manifest_path.to_str().unwrap())
.env(NETWORK_ENV, network_name)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
// We are supposed to only generate artifacts under OUT_DIR,
// so set OUT_DIR as the target directory for this build.
.env("CARGO_TARGET_DIR", &out_dir)
// As we are being called inside a build-script, this env variable is set. However, we set
// our own `RUSTFLAGS` and thus, we need to remove this. Otherwise cargo favors this
// env variable.
.env_remove("CARGO_ENCODED_RUSTFLAGS");
// Print out the command line we're about to run.
println!("cargo:warning=cmd={:?}", &cmd);
// Launch the command.
let mut child = cmd.spawn().expect("failed to launch cargo build");
// Pipe the output as cargo warnings. Unfortunately this is the only way to
// get cargo build to print the output.
let stdout = child.stdout.take().expect("no stdout");
let stderr = child.stderr.take().expect("no stderr");
let j1 = thread::spawn(move || {
for line in BufReader::new(stderr).lines() {
println!("cargo:warning={:?}", line.unwrap());
}
});
let j2 = thread::spawn(move || {
for line in BufReader::new(stdout).lines() {
println!("cargo:warning={:?}", line.unwrap());
}
});
j1.join().unwrap();
j2.join().unwrap();
let result = child.wait().expect("failed to wait for build to finish");
if !result.success() {
return Err("actor build failed".into());
}
let dst = Path::new(&out_dir).join("bundle.car");
let mut bundler = Bundler::new(&dst);
for (&(pkg, name), id) in ACTORS.iter().zip(1u32..) {
assert_eq!(
name,
Type::from_u32(id).expect("type not defined").name(),
"actor types don't match actors included in the bundle"
);
let bytecode_path = Path::new(&out_dir)
.join("wasm32-unknown-unknown/wasm")
.join(format!("fil_actor_{}.wasm", pkg));
// This actor version doesn't force synthetic CIDs; it uses genuine
// content-addressed CIDs.
let forced_cid = None;
let cid = bundler
.add_from_file(id, name.to_owned(), forced_cid, &bytecode_path)
.unwrap_or_else(|err| {
panic!("failed to add file {:?} to bundle for actor {}: {}", bytecode_path, id, err)
});
println!("cargo:warning=added {} ({}) to bundle with CID {}", name, id, cid);
}
bundler.finish().expect("failed to finish bundle");
println!("cargo:warning=bundle={}", dst.display());
Ok(())
}