Reorganising the repository - external renames and moves (#4074)

* Adding first rough ouline of the repository structure

* Remove old CI stuff

* add title

* formatting fixes

* move node-exits job's script to scripts dir

* Move docs into subdir

* move to bin

* move maintainence scripts, configs and helpers into its own dir

* add .local to ignore

* move core->client

* start up 'test' area

* move test client

* move test runtime

* make test move compile

* Add dependencies rule enforcement.

* Fix indexing.

* Update docs to reflect latest changes

* Moving /srml->/paint

* update docs

* move client/sr-* -> primitives/

* clean old readme

* remove old broken code in rhd

* update lock

* Step 1.

* starting to untangle client

* Fix after merge.

* start splitting out client interfaces

* move children and blockchain interfaces

* Move trie and state-machine to primitives.

* Fix WASM builds.

* fixing broken imports

* more interface moves

* move backend and light to interfaces

* move CallExecutor

* move cli off client

* moving around more interfaces

* re-add consensus crates into the mix

* fix subkey path

* relieve client from executor

* starting to pull out client from grandpa

* move is_decendent_of out of client

* grandpa still depends on client directly

* lemme tests pass

* rename srml->paint

* Make it compile.

* rename interfaces->client-api

* Move keyring to primitives.

* fixup libp2p dep

* fix broken use

* allow dependency enforcement to fail

* move fork-tree

* Moving wasm-builder

* make env

* move build-script-utils

* fixup broken crate depdencies and names

* fix imports for authority discovery

* fix typo

* update cargo.lock

* fixing imports

* Fix paths and add missing crates

* re-add missing crates
This commit is contained in:
Benjamin Kampmann
2019-11-14 21:51:17 +01:00
committed by Bastian Köcher
parent becc3b0a4f
commit 60e5011c72
809 changed files with 7801 additions and 6464 deletions
+245
View File
@@ -0,0 +1,245 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! # WASM builder is a utility for building a project as a WASM binary
//!
//! The WASM builder is a tool that integrates the process of building the WASM binary of your project into the main
//! `cargo` build process.
//!
//! ## Project setup
//!
//! A project that should be compiled as a WASM binary needs to:
//!
//! 1. Add a `build.rs` file.
//! 2. Add `substrate-wasm-builder` as dependency into `build-dependencies`.
//!
//! The `build.rs` file needs to contain the following code:
//!
//! ```ignore
//! use wasm_builder_runner::{build_current_project, WasmBuilderSource};
//!
//! fn main() {
//! build_current_project(
//! // The name of the file being generated in out-dir.
//! "wasm_binary.rs",
//! // How to include wasm-builder, in this case from crates.io.
//! WasmBuilderSource::Crates("1.0.0"),
//! );
//! }
//! ```
//!
//! As the final step, you need to add the following to your project:
//!
//! ```ignore
//! include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
//! ```
//!
//! This will include the generated WASM binary as two constants `WASM_BINARY` and `WASM_BINARY_BLOATY`.
//! The former is a compact WASM binary and the latter is not compacted.
//!
//! ## Environment variables
//!
//! By using environment variables, you can configure which WASM binaries are built and how:
//!
//! - `SKIP_WASM_BUILD` - Skips building any wasm binary. This is useful when only native should be recompiled.
//! - `BUILD_DUMMY_WASM_BINARY` - Builds dummy wasm binaries. These dummy binaries are empty and useful
//! for `cargo check` runs.
//! - `WASM_BUILD_TYPE` - Sets the build type for building wasm binaries. Supported values are `release` or `debug`.
//! By default the build type is equal to the build type used by the main build.
//! - `TRIGGER_WASM_BUILD` - Can be set to trigger a wasm build. On subsequent calls the value of the variable
//! needs to change. As WASM builder instructs `cargo` to watch for file changes
//! this environment variable should only be required in certain circumstances.
//! - `WASM_BUILD_RUSTFLAGS` - Extend `RUSTFLAGS` given to `cargo build` while building the wasm binary.
//! - `WASM_BUILD_NO_COLOR` - Disable color output of the wasm build.
//! - `WASM_TARGET_DIRECTORY` - Will copy any build wasm binary to the given directory. The path needs
//! to be absolute.
//!
//! Each project can be skipped individually by using the environment variable `SKIP_PROJECT_NAME_WASM_BUILD`.
//! Where `PROJECT_NAME` needs to be replaced by the name of the cargo project, e.g. `node-runtime` will
//! be `NODE_RUNTIME`.
//!
//! ## Prerequisites:
//!
//! WASM builder requires the following prerequisities for building the WASM binary:
//!
//! - rust nightly + `wasm32-unknown-unknown` toolchain
//!
use std::{env, fs, path::PathBuf, process::{Command, Stdio, self}};
mod prerequisites;
mod wasm_project;
/// Environment variable that tells us to skip building the wasm binary.
const SKIP_BUILD_ENV: &str = "SKIP_WASM_BUILD";
/// Environment variable to force a certain build type when building the wasm binary.
/// Expects "debug" or "release" as value.
///
/// By default the WASM binary uses the same build type as the main cargo build.
const WASM_BUILD_TYPE_ENV: &str = "WASM_BUILD_TYPE";
/// Environment variable to extend the `RUSTFLAGS` variable given to the wasm build.
const WASM_BUILD_RUSTFLAGS_ENV: &str = "WASM_BUILD_RUSTFLAGS";
/// Environment variable to set the target directory to copy the final wasm binary.
///
/// The directory needs to be an absolute path.
const WASM_TARGET_DIRECTORY: &str = "WASM_TARGET_DIRECTORY";
/// Environment variable to disable color output of the wasm build.
const WASM_BUILD_NO_COLOR: &str = "WASM_BUILD_NO_COLOR";
/// Build the currently built project as wasm binary.
///
/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable.
///
/// `file_name` - The name + path of the file being generated. The file contains the
/// constant `WASM_BINARY`, which contains the built WASM binary.
/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built.
pub fn build_project(file_name: &str, cargo_manifest: &str) {
build_project_with_default_rustflags(file_name, cargo_manifest, "");
}
/// Build the currently built project as wasm binary.
///
/// The current project is determined by using the `CARGO_MANIFEST_DIR` environment variable.
///
/// `file_name` - The name + path of the file being generated. The file contains the
/// constant `WASM_BINARY`, which contains the built WASM binary.
/// `cargo_manifest` - The path to the `Cargo.toml` of the project that should be built.
/// `default_rustflags` - Default `RUSTFLAGS` that will always be set for the build.
pub fn build_project_with_default_rustflags(
file_name: &str,
cargo_manifest: &str,
default_rustflags: &str,
) {
if check_skip_build() {
return;
}
let cargo_manifest = PathBuf::from(cargo_manifest);
if !cargo_manifest.exists() {
panic!("'{}' does not exist!", cargo_manifest.display());
}
if !cargo_manifest.ends_with("Cargo.toml") {
panic!("'{}' no valid path to a `Cargo.toml`!", cargo_manifest.display());
}
if let Some(err_msg) = prerequisites::check() {
eprintln!("{}", err_msg);
process::exit(1);
}
let (wasm_binary, bloaty) = wasm_project::create_and_compile(
&cargo_manifest,
default_rustflags,
);
write_file_if_changed(
file_name.into(),
format!(
r#"
pub const WASM_BINARY: &[u8] = include_bytes!("{wasm_binary}");
pub const WASM_BINARY_BLOATY: &[u8] = include_bytes!("{wasm_binary_bloaty}");
"#,
wasm_binary = wasm_binary.wasm_binary_path(),
wasm_binary_bloaty = bloaty.wasm_binary_bloaty_path(),
),
);
}
/// Checks if the build of the WASM binary should be skipped.
fn check_skip_build() -> bool {
env::var(SKIP_BUILD_ENV).is_ok()
}
/// Write to the given `file` if the `content` is different.
fn write_file_if_changed(file: PathBuf, content: String) {
if fs::read_to_string(&file).ok().as_ref() != Some(&content) {
fs::write(&file, content).expect(&format!("Writing `{}` can not fail!", file.display()));
}
}
/// Get a cargo command that compiles with nightly
fn get_nightly_cargo() -> CargoCommand {
let default_cargo = CargoCommand::new("cargo");
let mut rustup_run_nightly = CargoCommand::new("rustup");
rustup_run_nightly.args(&["run", "nightly", "cargo"]);
if default_cargo.is_nightly() {
default_cargo
} else if rustup_run_nightly.works() {
rustup_run_nightly
} else {
default_cargo
}
}
/// Builder for cargo commands
#[derive(Debug)]
struct CargoCommand {
program: String,
args: Vec<String>,
}
impl CargoCommand {
fn new(program: &str) -> Self {
CargoCommand { program: program.into(), args: Vec::new() }
}
fn arg(&mut self, arg: &str) -> &mut Self {
self.args.push(arg.into());
self
}
fn args(&mut self, args: &[&str]) -> &mut Self {
args.into_iter().for_each(|a| { self.arg(a); });
self
}
fn command(&self) -> Command {
let mut cmd = Command::new(&self.program);
cmd.args(&self.args);
cmd
}
fn works(&self) -> bool {
self.command()
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.map(|s| s.success()).unwrap_or(false)
}
/// Check if the supplied cargo command is a nightly version
fn is_nightly(&self) -> bool {
// `RUSTC_BOOTSTRAP` tells a stable compiler to behave like a nightly. So, when this env
// variable is set, we can assume that whatever rust compiler we have, it is a nightly compiler.
// For "more" information, see:
// https://github.com/rust-lang/rust/blob/fa0f7d0080d8e7e9eb20aa9cbf8013f96c81287f/src/libsyntax/feature_gate/check.rs#L891
env::var("RUSTC_BOOTSTRAP").is_ok() ||
self.command()
.arg("--version")
.output()
.map_err(|_| ())
.and_then(|o| String::from_utf8(o.stdout).map_err(|_| ()))
.unwrap_or_default()
.contains("-nightly")
}
}
@@ -0,0 +1,81 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use std::fs;
use tempfile::tempdir;
/// Checks that all prerequisites are installed.
///
/// # Returns
/// Returns `None` if everything was found and `Some(ERR_MSG)` if something could not be found.
pub fn check() -> Option<&'static str> {
if !check_nightly_installed(){
return Some("Rust nightly not installed, please install it!")
}
check_wasm_toolchain_installed()
}
fn check_nightly_installed() -> bool {
crate::get_nightly_cargo().is_nightly()
}
fn check_wasm_toolchain_installed() -> Option<&'static str> {
let temp = tempdir().expect("Creating temp dir does not fail; qed");
fs::create_dir_all(temp.path().join("src")).expect("Creating src dir does not fail; qed");
let test_file = temp.path().join("src/lib.rs");
let manifest_path = temp.path().join("Cargo.toml");
fs::write(&manifest_path,
r#"
[package]
name = "wasm-test"
version = "1.0.0"
edition = "2018"
[lib]
name = "wasm_test"
crate-type = ["cdylib"]
[workspace]
"#,
).expect("Writing wasm-test manifest does not fail; qed");
fs::write(&test_file, "pub fn test() {}")
.expect("Writing to the test file does not fail; qed");
let err_msg = "Rust WASM toolchain not installed, please install it!";
let manifest_path = manifest_path.display().to_string();
crate::get_nightly_cargo()
.command()
.args(&["build", "--target=wasm32-unknown-unknown", "--manifest-path", &manifest_path])
.output()
.map_err(|_| err_msg)
.and_then(|s|
if s.status.success() {
Ok(())
} else {
match String::from_utf8(s.stderr) {
Ok(ref err) if err.contains("linker `rust-lld` not found") => {
Err("`rust-lld` not found, please install it!")
},
_ => Err(err_msg)
}
}
)
.err()
}
@@ -0,0 +1,428 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::write_file_if_changed;
use std::{fs, path::{Path, PathBuf}, borrow::ToOwned, process, env};
use toml::value::Table;
use build_helper::rerun_if_changed;
use cargo_metadata::MetadataCommand;
use walkdir::WalkDir;
use fs2::FileExt;
/// Holds the path to the bloaty WASM binary.
pub struct WasmBinaryBloaty(PathBuf);
impl WasmBinaryBloaty {
/// Returns the path to the bloaty wasm binary.
pub fn wasm_binary_bloaty_path(&self) -> String {
self.0.display().to_string().replace('\\', "/")
}
}
/// Holds the path to the WASM binary.
pub struct WasmBinary(PathBuf);
impl WasmBinary {
/// Returns the path to the wasm binary.
pub fn wasm_binary_path(&self) -> String {
self.0.display().to_string().replace('\\', "/")
}
}
/// A lock for the WASM workspace.
struct WorkspaceLock(fs::File);
impl WorkspaceLock {
/// Create a new lock
fn new(wasm_workspace_root: &Path) -> Self {
let lock = fs::OpenOptions::new()
.read(true)
.write(true)
.create(true)
.open(wasm_workspace_root.join("wasm_workspace.lock"))
.expect("Opening the lock file does not fail");
lock.lock_exclusive().expect("Locking `wasm_workspace.lock` failed");
WorkspaceLock(lock)
}
}
impl Drop for WorkspaceLock {
fn drop(&mut self) {
let _ = self.0.unlock();
}
}
/// Creates the WASM project, compiles the WASM binary and compacts the WASM binary.
///
/// # Returns
/// The path to the compact WASM binary and the bloaty WASM binary.
pub fn create_and_compile(
cargo_manifest: &Path,
default_rustflags: &str,
) -> (WasmBinary, WasmBinaryBloaty) {
let wasm_workspace_root = get_wasm_workspace_root();
let wasm_workspace = wasm_workspace_root.join("wbuild");
// Lock the workspace exclusively for us
let _lock = WorkspaceLock::new(&wasm_workspace_root);
let project = create_project(cargo_manifest, &wasm_workspace);
create_wasm_workspace_project(&wasm_workspace, cargo_manifest);
build_project(&project, default_rustflags);
let (wasm_binary, bloaty) = compact_wasm_file(
&project,
cargo_manifest,
&wasm_workspace,
);
copy_wasm_to_target_directory(cargo_manifest, &wasm_binary);
generate_rerun_if_changed_instructions(cargo_manifest, &project, &wasm_workspace);
(wasm_binary, bloaty)
}
/// Find the `Cargo.lock` relative to the `OUT_DIR` environment variable.
///
/// If the `Cargo.lock` cannot be found, we emit a warning and return `None`.
fn find_cargo_lock(cargo_manifest: &Path) -> Option<PathBuf> {
fn find_impl(mut path: PathBuf) -> Option<PathBuf> {
loop {
if path.join("Cargo.lock").exists() {
return Some(path.join("Cargo.lock"))
}
if !path.pop() {
return None;
}
}
}
if let Some(path) = find_impl(build_helper::out_dir()) {
return Some(path);
}
if let Some(path) = find_impl(cargo_manifest.to_path_buf()) {
return Some(path);
}
build_helper::warning!(
"Could not find `Cargo.lock` for `{}`, while searching from `{}`.",
cargo_manifest.display(),
build_helper::out_dir().display()
);
None
}
/// Extract the crate name from the given `Cargo.toml`.
fn get_crate_name(cargo_manifest: &Path) -> String {
let cargo_toml: Table = toml::from_str(
&fs::read_to_string(cargo_manifest).expect("File exists as checked before; qed")
).expect("Cargo manifest is a valid toml file; qed");
let package = cargo_toml
.get("package")
.and_then(|t| t.as_table())
.expect("`package` key exists in valid `Cargo.toml`; qed");
package.get("name").and_then(|p| p.as_str()).map(ToOwned::to_owned).expect("Package name exists; qed")
}
/// Returns the name for the wasm binary.
fn get_wasm_binary_name(cargo_manifest: &Path) -> String {
get_crate_name(cargo_manifest).replace('-', "_")
}
/// Returns the root path of the wasm workspace.
fn get_wasm_workspace_root() -> PathBuf {
let mut out_dir = build_helper::out_dir();
loop {
match out_dir.parent() {
Some(parent) if out_dir.ends_with("build") => return parent.to_path_buf(),
_ => if !out_dir.pop() {
break;
}
}
}
panic!("Could not find target dir in: {}", build_helper::out_dir().display())
}
fn create_wasm_workspace_project(wasm_workspace: &Path, cargo_manifest: &Path) {
let members = WalkDir::new(wasm_workspace)
.min_depth(1)
.max_depth(1)
.into_iter()
.filter_map(|p| p.ok())
.map(|d| d.into_path())
.filter(|p| p.is_dir() && !p.ends_with("target"))
.filter_map(|p| p.file_name().map(|f| f.to_owned()).and_then(|s| s.into_string().ok()))
.collect::<Vec<_>>();
let crate_metadata = MetadataCommand::new()
.manifest_path(cargo_manifest)
.exec()
.expect("`cargo metadata` can not fail on project `Cargo.toml`; qed");
let workspace_root_path = crate_metadata.workspace_root;
let mut workspace_toml: Table = toml::from_str(
&fs::read_to_string(
workspace_root_path.join("Cargo.toml"),
).expect("Workspace root `Cargo.toml` exists; qed")
).expect("Workspace root `Cargo.toml` is a valid toml file; qed");
let mut wasm_workspace_toml = Table::new();
// Add `profile` with release and dev
let mut release_profile = Table::new();
release_profile.insert("panic".into(), "abort".into());
release_profile.insert("lto".into(), true.into());
let mut dev_profile = Table::new();
dev_profile.insert("panic".into(), "abort".into());
let mut profile = Table::new();
profile.insert("release".into(), release_profile.into());
profile.insert("dev".into(), dev_profile.into());
wasm_workspace_toml.insert("profile".into(), profile.into());
// Add `workspace` with members
let mut workspace = Table::new();
workspace.insert("members".into(), members.into());
wasm_workspace_toml.insert("workspace".into(), workspace.into());
// Add patch section from the project root `Cargo.toml`
if let Some(mut patch) = workspace_toml.remove("patch").and_then(|p| p.try_into::<Table>().ok()) {
// Iterate over all patches and make the patch path absolute from the workspace root path.
patch.iter_mut()
.filter_map(|p|
p.1.as_table_mut().map(|t| t.iter_mut().filter_map(|t| t.1.as_table_mut()))
)
.flatten()
.for_each(|p|
p.iter_mut()
.filter(|(k, _)| k == &"path")
.for_each(|(_, v)| {
if let Some(path) = v.as_str() {
*v = workspace_root_path.join(path).display().to_string().into();
}
})
);
wasm_workspace_toml.insert("patch".into(), patch.into());
}
fs::write(
wasm_workspace.join("Cargo.toml"),
toml::to_string_pretty(&wasm_workspace_toml).expect("Wasm workspace toml is valid; qed"),
).expect("WASM workspace `Cargo.toml` writing can not fail; qed");
}
/// Create the project used to build the wasm binary.
///
/// # Returns
/// The path to the created project.
fn create_project(cargo_manifest: &Path, wasm_workspace: &Path) -> PathBuf {
let crate_name = get_crate_name(cargo_manifest);
let crate_path = cargo_manifest.parent().expect("Parent path exists; qed");
let wasm_binary = get_wasm_binary_name(cargo_manifest);
let project_folder = wasm_workspace.join(&crate_name);
fs::create_dir_all(project_folder.join("src")).expect("Wasm project dir create can not fail; qed");
write_file_if_changed(
project_folder.join("Cargo.toml"),
format!(
r#"
[package]
name = "{crate_name}-wasm"
version = "1.0.0"
edition = "2018"
[lib]
name = "{wasm_binary}"
crate-type = ["cdylib"]
[dependencies]
wasm_project = {{ package = "{crate_name}", path = "{crate_path}", default-features = false }}
"#,
crate_name = crate_name,
crate_path = crate_path.display(),
wasm_binary = wasm_binary,
)
);
write_file_if_changed(
project_folder.join("src/lib.rs"),
"#![no_std] pub use wasm_project::*;".into(),
);
if let Some(crate_lock_file) = find_cargo_lock(cargo_manifest) {
// Use the `Cargo.lock` of the main project.
fs::copy(crate_lock_file, wasm_workspace.join("Cargo.lock"))
.expect("Copying the `Cargo.lock` can not fail; qed");
}
project_folder
}
/// Returns if the project should be built as a release.
fn is_release_build() -> bool {
if let Ok(var) = env::var(crate::WASM_BUILD_TYPE_ENV) {
match var.as_str() {
"release" => true,
"debug" => false,
var => panic!(
"Unexpected value for `{}` env variable: {}\nOne of the following are expected: `debug` or `release`.",
crate::WASM_BUILD_TYPE_ENV,
var,
),
}
} else {
!build_helper::debug()
}
}
/// Build the project to create the WASM binary.
fn build_project(project: &Path, default_rustflags: &str) {
let manifest_path = project.join("Cargo.toml");
let mut build_cmd = crate::get_nightly_cargo().command();
let rustflags = format!(
"-C link-arg=--export-table {} {}",
default_rustflags,
env::var(crate::WASM_BUILD_RUSTFLAGS_ENV).unwrap_or_default(),
);
build_cmd.args(&["rustc", "--target=wasm32-unknown-unknown"])
.arg(format!("--manifest-path={}", manifest_path.display()))
.env("RUSTFLAGS", rustflags)
// We don't want to call ourselves recursively
.env(crate::SKIP_BUILD_ENV, "");
if env::var(crate::WASM_BUILD_NO_COLOR).is_err() {
build_cmd.arg("--color=always");
}
if is_release_build() {
build_cmd.arg("--release");
};
println!("Executing build command: {:?}", build_cmd);
match build_cmd.status().map(|s| s.success()) {
Ok(true) => {},
// Use `process.exit(1)` to have a clean error output.
_ => process::exit(1),
}
}
/// Compact the WASM binary using `wasm-gc`. Returns the path to the bloaty WASM binary.
fn compact_wasm_file(
project: &Path,
cargo_manifest: &Path,
wasm_workspace: &Path,
) -> (WasmBinary, WasmBinaryBloaty) {
let target = if is_release_build() { "release" } else { "debug" };
let wasm_binary = get_wasm_binary_name(cargo_manifest);
let wasm_file = wasm_workspace.join("target/wasm32-unknown-unknown")
.join(target)
.join(format!("{}.wasm", wasm_binary));
let wasm_compact_file = project.join(format!("{}.compact.wasm", wasm_binary));
wasm_gc::garbage_collect_file(&wasm_file, &wasm_compact_file)
.expect("Failed to compact generated WASM binary.");
(WasmBinary(wasm_compact_file), WasmBinaryBloaty(wasm_file))
}
/// Generate the `rerun-if-changed` instructions for cargo to make sure that the WASM binary is
/// rebuilt when needed.
fn generate_rerun_if_changed_instructions(
cargo_manifest: &Path,
project_folder: &Path,
wasm_workspace: &Path,
) {
// Rerun `build.rs` if the `Cargo.lock` changes
if let Some(cargo_lock) = find_cargo_lock(cargo_manifest) {
rerun_if_changed(cargo_lock);
}
let metadata = MetadataCommand::new()
.manifest_path(project_folder.join("Cargo.toml"))
.exec()
.expect("`cargo metadata` can not fail!");
// Make sure that if any file/folder of a depedency change, we need to rerun the `build.rs`
metadata.packages.into_iter()
.filter(|package| !package.manifest_path.starts_with(wasm_workspace))
.for_each(|package| {
let mut manifest_path = package.manifest_path;
if manifest_path.ends_with("Cargo.toml") {
manifest_path.pop();
}
rerun_if_changed(&manifest_path);
WalkDir::new(manifest_path)
.into_iter()
.filter_map(|p| p.ok())
.for_each(|p| rerun_if_changed(p.path()));
});
// Register our env variables
println!("cargo:rerun-if-env-changed={}", crate::SKIP_BUILD_ENV);
println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_TYPE_ENV);
println!("cargo:rerun-if-env-changed={}", crate::WASM_BUILD_RUSTFLAGS_ENV);
println!("cargo:rerun-if-env-changed={}", crate::WASM_TARGET_DIRECTORY);
}
/// Copy the WASM binary to the target directory set in `WASM_TARGET_DIRECTORY` environment variable.
/// If the variable is not set, this is a no-op.
fn copy_wasm_to_target_directory(cargo_manifest: &Path, wasm_binary: &WasmBinary) {
let target_dir = match env::var(crate::WASM_TARGET_DIRECTORY) {
Ok(path) => PathBuf::from(path),
Err(_) => return,
};
if !target_dir.is_absolute() {
panic!(
"Environment variable `{}` with `{}` is not an absolute path!",
crate::WASM_TARGET_DIRECTORY,
target_dir.display(),
);
}
fs::create_dir_all(&target_dir).expect("Creates `WASM_TARGET_DIRECTORY`.");
fs::copy(
wasm_binary.wasm_binary_path(),
target_dir.join(format!("{}.wasm", get_wasm_binary_name(cargo_manifest))),
).expect("Copies WASM binary to `WASM_TARGET_DIRECTORY`.");
}