mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
split up bitcode building to reduce dependency chains
This commit is contained in:
parent
24c7bded35
commit
d5e191d083
18 changed files with 418 additions and 140 deletions
22
Cargo.lock
generated
22
Cargo.lock
generated
|
@ -3032,6 +3032,22 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_bitcode"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"dunce",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "roc_bitcode_bc"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"dunce",
|
||||||
|
"tempfile",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "roc_build"
|
name = "roc_build"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
|
@ -3040,7 +3056,7 @@ dependencies = [
|
||||||
"indoc",
|
"indoc",
|
||||||
"inkwell",
|
"inkwell",
|
||||||
"libloading",
|
"libloading",
|
||||||
"roc_builtins",
|
"roc_bitcode",
|
||||||
"roc_can",
|
"roc_can",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_constrain",
|
"roc_constrain",
|
||||||
|
@ -3073,7 +3089,6 @@ dependencies = [
|
||||||
name = "roc_builtins"
|
name = "roc_builtins"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dunce",
|
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_module",
|
"roc_module",
|
||||||
"roc_region",
|
"roc_region",
|
||||||
|
@ -3366,6 +3381,7 @@ dependencies = [
|
||||||
"inkwell",
|
"inkwell",
|
||||||
"morphic_lib",
|
"morphic_lib",
|
||||||
"roc_alias_analysis",
|
"roc_alias_analysis",
|
||||||
|
"roc_bitcode_bc",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_debug_flags",
|
"roc_debug_flags",
|
||||||
|
@ -3715,6 +3731,7 @@ dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"getrandom",
|
"getrandom",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
"roc_bitcode",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
"roc_collections",
|
"roc_collections",
|
||||||
"roc_gen_wasm",
|
"roc_gen_wasm",
|
||||||
|
@ -4525,6 +4542,7 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"libloading",
|
"libloading",
|
||||||
|
"roc_bitcode",
|
||||||
"roc_build",
|
"roc_build",
|
||||||
"roc_builtins",
|
"roc_builtins",
|
||||||
"roc_can",
|
"roc_can",
|
||||||
|
|
|
@ -8,7 +8,7 @@ license.workspace = true
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
roc_builtins = { path = "../builtins" }
|
roc_bitcode = { path = "../builtins/bitcode" }
|
||||||
roc_can = { path = "../can" }
|
roc_can = { path = "../can" }
|
||||||
roc_collections = { path = "../collections" }
|
roc_collections = { path = "../collections" }
|
||||||
roc_constrain = { path = "../constrain" }
|
roc_constrain = { path = "../constrain" }
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::target::{arch_str, target_zig_str};
|
use crate::target::{arch_str, target_zig_str};
|
||||||
use libloading::{Error, Library};
|
use libloading::{Error, Library};
|
||||||
use roc_builtins::bitcode;
|
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use roc_utils::{cargo, clang, zig};
|
use roc_utils::{cargo, clang, zig};
|
||||||
|
@ -556,7 +555,7 @@ pub fn rebuild_host(
|
||||||
let env_cpath = env::var("CPATH").unwrap_or_else(|_| "".to_string());
|
let env_cpath = env::var("CPATH").unwrap_or_else(|_| "".to_string());
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile =
|
||||||
bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
if zig_host_src.exists() {
|
if zig_host_src.exists() {
|
||||||
// Compile host.zig
|
// Compile host.zig
|
||||||
|
@ -1435,8 +1434,8 @@ pub fn preprocess_host_wasm32(host_input_path: &Path, preprocessed_host_path: &P
|
||||||
(but seems to be an unofficial API)
|
(but seems to be an unofficial API)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile()
|
||||||
bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
let mut zig_cmd = zig();
|
let mut zig_cmd = zig();
|
||||||
let args = &[
|
let args = &[
|
||||||
|
|
|
@ -3,7 +3,6 @@ use crate::link::{
|
||||||
};
|
};
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use inkwell::memory_buffer::MemoryBuffer;
|
use inkwell::memory_buffer::MemoryBuffer;
|
||||||
use roc_builtins::bitcode;
|
|
||||||
use roc_error_macros::internal_error;
|
use roc_error_macros::internal_error;
|
||||||
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
|
use roc_gen_llvm::llvm::build::{module_from_builtins, LlvmBackendMode};
|
||||||
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
use roc_gen_llvm::llvm::externs::add_default_roc_externs;
|
||||||
|
@ -938,8 +937,8 @@ fn build_loaded_file<'a>(
|
||||||
|
|
||||||
std::fs::write(app_o_file, &*roc_app_bytes).unwrap();
|
std::fs::write(app_o_file, &*roc_app_bytes).unwrap();
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile = roc_bitcode::host_tempfile()
|
||||||
bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
let mut inputs = vec![app_o_file.to_str().unwrap()];
|
let mut inputs = vec![app_o_file.to_str().unwrap()];
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,3 @@ roc_utils = { path = "../../utils" }
|
||||||
|
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
roc_utils = { path = "../../utils" }
|
|
||||||
|
|
||||||
# dunce can be removed once ziglang/zig#5109 is fixed
|
|
||||||
dunce = "1.0.3"
|
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.build-dependencies]
|
|
||||||
tempfile.workspace = true
|
|
||||||
|
|
18
crates/compiler/builtins/bitcode/Cargo.toml
Normal file
18
crates/compiler/builtins/bitcode/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[package]
|
||||||
|
name = "roc_bitcode"
|
||||||
|
description = "Compiles the zig bitcode to `.o` for builtins"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
tempfile.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
# dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
|
dunce = "1.0.3"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.build-dependencies]
|
||||||
|
tempfile.workspace = true
|
15
crates/compiler/builtins/bitcode/bc/Cargo.toml
Normal file
15
crates/compiler/builtins/bitcode/bc/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "roc_bitcode_bc"
|
||||||
|
description = "Compiles the zig bitcode to `.bc` for llvm"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
# dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
|
dunce = "1.0.3"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.build-dependencies]
|
||||||
|
tempfile.workspace = true
|
217
crates/compiler/builtins/bitcode/bc/build.rs
Normal file
217
crates/compiler/builtins/bitcode/bc/build.rs
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
use std::fs;
|
||||||
|
use std::io;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::str;
|
||||||
|
use std::{
|
||||||
|
env::{self, VarError},
|
||||||
|
path::PathBuf,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
use tempfile::tempdir;
|
||||||
|
|
||||||
|
/// To debug the zig code with debug prints, we need to disable the wasm code gen
|
||||||
|
const DEBUG: bool = false;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=build.rs");
|
||||||
|
|
||||||
|
// "." is relative to where "build.rs" is
|
||||||
|
// dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
|
let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap().join("..");
|
||||||
|
|
||||||
|
// workaround for github.com/ziglang/zig/issues/9711
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let zig_cache_dir = tempdir().expect("Failed to create temp directory for zig cache");
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
std::env::set_var("ZIG_GLOBAL_CACHE_DIR", zig_cache_dir.path().as_os_str());
|
||||||
|
|
||||||
|
// LLVM .bc FILES
|
||||||
|
|
||||||
|
generate_bc_file(&bitcode_path, "ir", "builtins-host");
|
||||||
|
|
||||||
|
if !DEBUG {
|
||||||
|
generate_bc_file(&bitcode_path, "ir-wasm32", "builtins-wasm32");
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_bc_file(&bitcode_path, "ir-i386", "builtins-i386");
|
||||||
|
generate_bc_file(&bitcode_path, "ir-x86_64", "builtins-x86_64");
|
||||||
|
generate_bc_file(
|
||||||
|
&bitcode_path,
|
||||||
|
"ir-windows-x86_64",
|
||||||
|
"builtins-windows-x86_64",
|
||||||
|
);
|
||||||
|
|
||||||
|
get_zig_files(bitcode_path.as_path(), &|path| {
|
||||||
|
let path: &Path = path;
|
||||||
|
println!(
|
||||||
|
"cargo:rerun-if-changed={}",
|
||||||
|
path.to_str().expect("Failed to convert path to str")
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
zig_cache_dir
|
||||||
|
.close()
|
||||||
|
.expect("Failed to delete temp dir zig_cache_dir.");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) {
|
||||||
|
let mut ll_path = bitcode_path.join(file_name);
|
||||||
|
ll_path.set_extension("ll");
|
||||||
|
let dest_ir_host = ll_path.to_str().expect("Invalid dest ir path");
|
||||||
|
|
||||||
|
println!("Compiling host ir to: {}", dest_ir_host);
|
||||||
|
|
||||||
|
let mut bc_path = bitcode_path.join(file_name);
|
||||||
|
bc_path.set_extension("bc");
|
||||||
|
let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path");
|
||||||
|
println!("Compiling 64-bit bitcode to: {}", dest_bc_64bit);
|
||||||
|
|
||||||
|
// workaround for github.com/ziglang/zig/issues/9711
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
let _ = fs::remove_dir_all("./zig-cache");
|
||||||
|
|
||||||
|
let mut zig_cmd = zig();
|
||||||
|
|
||||||
|
zig_cmd
|
||||||
|
.current_dir(bitcode_path)
|
||||||
|
.args(["build", zig_object, "-Drelease=true"]);
|
||||||
|
|
||||||
|
run_command(zig_cmd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_lib_dir() -> PathBuf {
|
||||||
|
// Currently we have the OUT_DIR variable which points to `/target/debug/build/roc_builtins-*/out/`.
|
||||||
|
// So we just need to add "/bitcode" to that.
|
||||||
|
let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
|
||||||
|
// create dir if it does not exist
|
||||||
|
fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/ dir.");
|
||||||
|
|
||||||
|
dir
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command(mut command: Command, flaky_fail_counter: usize) {
|
||||||
|
let command_str = pretty_command_string(&command);
|
||||||
|
let command_str = command_str.to_string_lossy();
|
||||||
|
|
||||||
|
let output_result = command.output();
|
||||||
|
|
||||||
|
match output_result {
|
||||||
|
Ok(output) => match output.status.success() {
|
||||||
|
true => (),
|
||||||
|
false => {
|
||||||
|
let error_str = match str::from_utf8(&output.stderr) {
|
||||||
|
Ok(stderr) => stderr.to_string(),
|
||||||
|
Err(_) => format!("Failed to run \"{}\"", command_str),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Flaky test errors that only occur sometimes on MacOS ci server.
|
||||||
|
if error_str.contains("FileNotFound")
|
||||||
|
|| error_str.contains("unable to save cached ZIR code")
|
||||||
|
|| error_str.contains("LLVM failed to emit asm")
|
||||||
|
{
|
||||||
|
if flaky_fail_counter == 10 {
|
||||||
|
panic!("{} failed 10 times in a row. The following error is unlikely to be a flaky error: {}", command_str, error_str);
|
||||||
|
} else {
|
||||||
|
run_command(command, flaky_fail_counter + 1)
|
||||||
|
}
|
||||||
|
} else if error_str
|
||||||
|
.contains("lld-link: error: failed to write the output file: Permission denied")
|
||||||
|
{
|
||||||
|
panic!("{} failed with:\n\n {}\n\nWorkaround:\n\n Re-run the cargo command that triggered this build.\n\n", command_str, error_str);
|
||||||
|
} else {
|
||||||
|
panic!("{} failed with:\n\n {}\n", command_str, error_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(reason) => panic!("{} failed: {}", command_str, reason),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> {
|
||||||
|
if dir.is_dir() {
|
||||||
|
for entry in fs::read_dir(dir)? {
|
||||||
|
let entry = entry?;
|
||||||
|
let path_buf = entry.path();
|
||||||
|
if path_buf.is_dir() {
|
||||||
|
if !path_buf.ends_with("zig-cache") {
|
||||||
|
get_zig_files(&path_buf, cb).unwrap();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let path = path_buf.as_path();
|
||||||
|
|
||||||
|
match path.extension() {
|
||||||
|
Some(osstr) if osstr == "zig" => {
|
||||||
|
cb(path);
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gives a friendly error if zig is not installed.
|
||||||
|
/// Also makes it easy to track where we use zig in the codebase.
|
||||||
|
pub fn zig() -> Command {
|
||||||
|
let command_str = match std::env::var("ROC_ZIG") {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(_) => "zig".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if check_command_available(&command_str) {
|
||||||
|
Command::new(command_str)
|
||||||
|
} else {
|
||||||
|
panic!("I could not find the zig command.\nPlease install zig, see instructions at https://ziglang.org/learn/getting-started/.",)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_command_available(command_name: &str) -> bool {
|
||||||
|
if cfg!(target_family = "unix") {
|
||||||
|
let unparsed_path = match std::env::var("PATH") {
|
||||||
|
Ok(var) => var,
|
||||||
|
Err(VarError::NotPresent) => return false,
|
||||||
|
Err(VarError::NotUnicode(_)) => {
|
||||||
|
panic!("found PATH, but it included invalid unicode data!")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::env::split_paths(&unparsed_path).any(|dir| dir.join(command_name).exists())
|
||||||
|
} else if cfg!(target = "windows") {
|
||||||
|
let mut cmd = Command::new("Get-Command");
|
||||||
|
|
||||||
|
cmd.args([command_name]);
|
||||||
|
|
||||||
|
let cmd_str = format!("{:?}", cmd);
|
||||||
|
|
||||||
|
let cmd_out = cmd.output().unwrap_or_else(|err| {
|
||||||
|
panic!(
|
||||||
|
"Failed to execute `{}` to check if {} is available:\n {}",
|
||||||
|
cmd_str, command_name, err
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
cmd_out.status.success()
|
||||||
|
} else {
|
||||||
|
// We're in uncharted waters, best not to panic if
|
||||||
|
// things may end up working out down the line.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_command_string(command: &Command) -> std::ffi::OsString {
|
||||||
|
let mut command_string = std::ffi::OsString::new();
|
||||||
|
command_string.push(command.get_program());
|
||||||
|
|
||||||
|
for arg in command.get_args() {
|
||||||
|
command_string.push(" ");
|
||||||
|
command_string.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
command_string
|
||||||
|
}
|
0
crates/compiler/builtins/bitcode/bc/src/lib.rs
Normal file
0
crates/compiler/builtins/bitcode/bc/src/lib.rs
Normal file
|
@ -1,11 +1,12 @@
|
||||||
use roc_utils::zig;
|
|
||||||
use std::env;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::process::Command;
|
|
||||||
use std::str;
|
use std::str;
|
||||||
|
use std::{
|
||||||
|
env::{self, VarError},
|
||||||
|
path::PathBuf,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use tempfile::tempdir;
|
use tempfile::tempdir;
|
||||||
|
@ -18,8 +19,7 @@ fn main() {
|
||||||
|
|
||||||
// "." is relative to where "build.rs" is
|
// "." is relative to where "build.rs" is
|
||||||
// dunce can be removed once ziglang/zig#5109 is fixed
|
// dunce can be removed once ziglang/zig#5109 is fixed
|
||||||
let build_script_dir_path = dunce::canonicalize(Path::new(".")).unwrap();
|
let bitcode_path = dunce::canonicalize(Path::new(".")).unwrap();
|
||||||
let bitcode_path = build_script_dir_path.join("bitcode");
|
|
||||||
|
|
||||||
// workaround for github.com/ziglang/zig/issues/9711
|
// workaround for github.com/ziglang/zig/issues/9711
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -27,22 +27,6 @@ fn main() {
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
std::env::set_var("ZIG_GLOBAL_CACHE_DIR", zig_cache_dir.path().as_os_str());
|
std::env::set_var("ZIG_GLOBAL_CACHE_DIR", zig_cache_dir.path().as_os_str());
|
||||||
|
|
||||||
// LLVM .bc FILES
|
|
||||||
|
|
||||||
generate_bc_file(&bitcode_path, "ir", "builtins-host");
|
|
||||||
|
|
||||||
if !DEBUG {
|
|
||||||
generate_bc_file(&bitcode_path, "ir-wasm32", "builtins-wasm32");
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_bc_file(&bitcode_path, "ir-i386", "builtins-i386");
|
|
||||||
generate_bc_file(&bitcode_path, "ir-x86_64", "builtins-x86_64");
|
|
||||||
generate_bc_file(
|
|
||||||
&bitcode_path,
|
|
||||||
"ir-windows-x86_64",
|
|
||||||
"builtins-windows-x86_64",
|
|
||||||
);
|
|
||||||
|
|
||||||
// OBJECT FILES
|
// OBJECT FILES
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
const BUILTINS_HOST_FILE: &str = "builtins-host.obj";
|
const BUILTINS_HOST_FILE: &str = "builtins-host.obj";
|
||||||
|
@ -107,38 +91,13 @@ fn generate_object_file(bitcode_path: &Path, zig_object: &str, object_file_name:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_bc_file(bitcode_path: &Path, zig_object: &str, file_name: &str) {
|
|
||||||
let mut ll_path = bitcode_path.join(file_name);
|
|
||||||
ll_path.set_extension("ll");
|
|
||||||
let dest_ir_host = ll_path.to_str().expect("Invalid dest ir path");
|
|
||||||
|
|
||||||
println!("Compiling host ir to: {}", dest_ir_host);
|
|
||||||
|
|
||||||
let mut bc_path = bitcode_path.join(file_name);
|
|
||||||
bc_path.set_extension("bc");
|
|
||||||
let dest_bc_64bit = bc_path.to_str().expect("Invalid dest bc path");
|
|
||||||
println!("Compiling 64-bit bitcode to: {}", dest_bc_64bit);
|
|
||||||
|
|
||||||
// workaround for github.com/ziglang/zig/issues/9711
|
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
let _ = fs::remove_dir_all("./bitcode/zig-cache");
|
|
||||||
|
|
||||||
let mut zig_cmd = zig();
|
|
||||||
|
|
||||||
zig_cmd
|
|
||||||
.current_dir(bitcode_path)
|
|
||||||
.args(["build", zig_object, "-Drelease=true"]);
|
|
||||||
|
|
||||||
run_command(zig_cmd, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_lib_dir() -> PathBuf {
|
pub fn get_lib_dir() -> PathBuf {
|
||||||
// Currently we have the OUT_DIR variable which points to `/target/debug/build/roc_builtins-*/out/`.
|
// Currently we have the OUT_DIR variable which points to `/target/debug/build/roc_builtins-*/out/`.
|
||||||
// So we just need to add "/bitcode" to that.
|
// So we just need to add "/bitcode" to that.
|
||||||
let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()).join("bitcode");
|
let dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||||
|
|
||||||
// create dir if it does not exist
|
// create dir if it does not exist
|
||||||
fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/bitcode dir.");
|
fs::create_dir_all(&dir).expect("Failed to make $OUT_DIR/ dir.");
|
||||||
|
|
||||||
dir
|
dir
|
||||||
}
|
}
|
||||||
|
@ -192,7 +151,7 @@ fn cp_unless_zig_cache(src_dir: &Path, target_dir: &Path) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_command(mut command: Command, flaky_fail_counter: usize) {
|
fn run_command(mut command: Command, flaky_fail_counter: usize) {
|
||||||
let command_str = roc_utils::pretty_command_string(&command);
|
let command_str = pretty_command_string(&command);
|
||||||
let command_str = command_str.to_string_lossy();
|
let command_str = command_str.to_string_lossy();
|
||||||
|
|
||||||
let output_result = command.output();
|
let output_result = command.output();
|
||||||
|
@ -252,3 +211,63 @@ fn get_zig_files(dir: &Path, cb: &dyn Fn(&Path)) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gives a friendly error if zig is not installed.
|
||||||
|
/// Also makes it easy to track where we use zig in the codebase.
|
||||||
|
pub fn zig() -> Command {
|
||||||
|
let command_str = match std::env::var("ROC_ZIG") {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(_) => "zig".into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if check_command_available(&command_str) {
|
||||||
|
Command::new(command_str)
|
||||||
|
} else {
|
||||||
|
panic!("I could not find the zig command.\nPlease install zig, see instructions at https://ziglang.org/learn/getting-started/.",)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_command_available(command_name: &str) -> bool {
|
||||||
|
if cfg!(target_family = "unix") {
|
||||||
|
let unparsed_path = match std::env::var("PATH") {
|
||||||
|
Ok(var) => var,
|
||||||
|
Err(VarError::NotPresent) => return false,
|
||||||
|
Err(VarError::NotUnicode(_)) => {
|
||||||
|
panic!("found PATH, but it included invalid unicode data!")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::env::split_paths(&unparsed_path).any(|dir| dir.join(command_name).exists())
|
||||||
|
} else if cfg!(target = "windows") {
|
||||||
|
let mut cmd = Command::new("Get-Command");
|
||||||
|
|
||||||
|
cmd.args([command_name]);
|
||||||
|
|
||||||
|
let cmd_str = format!("{:?}", cmd);
|
||||||
|
|
||||||
|
let cmd_out = cmd.output().unwrap_or_else(|err| {
|
||||||
|
panic!(
|
||||||
|
"Failed to execute `{}` to check if {} is available:\n {}",
|
||||||
|
cmd_str, command_name, err
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
cmd_out.status.success()
|
||||||
|
} else {
|
||||||
|
// We're in uncharted waters, best not to panic if
|
||||||
|
// things may end up working out down the line.
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pretty_command_string(command: &Command) -> std::ffi::OsString {
|
||||||
|
let mut command_string = std::ffi::OsString::new();
|
||||||
|
command_string.push(command.get_program());
|
||||||
|
|
||||||
|
for arg in command.get_args() {
|
||||||
|
command_string.push(" ");
|
||||||
|
command_string.push(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
command_string
|
||||||
|
}
|
65
crates/compiler/builtins/bitcode/src/lib.rs
Normal file
65
crates/compiler/builtins/bitcode/src/lib.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
const HOST_WASM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/builtins-wasm32.o"));
|
||||||
|
// TODO: in the future, we should use Zig's cross-compilation to generate and store these
|
||||||
|
// for all targets, so that we can do cross-compilation!
|
||||||
|
#[cfg(unix)]
|
||||||
|
const HOST_UNIX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/builtins-host.o"));
|
||||||
|
#[cfg(windows)]
|
||||||
|
const HOST_WINDOWS: &[u8] =
|
||||||
|
include_bytes!(concat!(env!("OUT_DIR"), "/builtins-windows-x86_64.obj"));
|
||||||
|
|
||||||
|
pub fn host_wasm_tempfile() -> std::io::Result<NamedTempFile> {
|
||||||
|
let tempfile = tempfile::Builder::new()
|
||||||
|
.prefix("host_bitcode")
|
||||||
|
.suffix(".wasm")
|
||||||
|
.rand_bytes(8)
|
||||||
|
.tempfile()?;
|
||||||
|
|
||||||
|
std::fs::write(tempfile.path(), HOST_WASM)?;
|
||||||
|
|
||||||
|
Ok(tempfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn host_unix_tempfile() -> std::io::Result<NamedTempFile> {
|
||||||
|
let tempfile = tempfile::Builder::new()
|
||||||
|
.prefix("host_bitcode")
|
||||||
|
.suffix(".o")
|
||||||
|
.rand_bytes(8)
|
||||||
|
.tempfile()?;
|
||||||
|
|
||||||
|
std::fs::write(tempfile.path(), HOST_UNIX)?;
|
||||||
|
|
||||||
|
Ok(tempfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
fn host_windows_tempfile() -> std::io::Result<NamedTempFile> {
|
||||||
|
let tempfile = tempfile::Builder::new()
|
||||||
|
.prefix("host_bitcode")
|
||||||
|
.suffix(".obj")
|
||||||
|
.rand_bytes(8)
|
||||||
|
.tempfile()?;
|
||||||
|
|
||||||
|
std::fs::write(tempfile.path(), HOST_WINDOWS)?;
|
||||||
|
|
||||||
|
Ok(tempfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn host_tempfile() -> std::io::Result<NamedTempFile> {
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
host_unix_tempfile()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
|
host_windows_tempfile()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(windows, unix)))]
|
||||||
|
{
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,73 +1,6 @@
|
||||||
use roc_module::symbol::Symbol;
|
use roc_module::symbol::Symbol;
|
||||||
use roc_target::TargetInfo;
|
use roc_target::TargetInfo;
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
use tempfile::NamedTempFile;
|
|
||||||
|
|
||||||
pub const HOST_WASM: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/bitcode/builtins-wasm32.o"));
|
|
||||||
// TODO: in the future, we should use Zig's cross-compilation to generate and store these
|
|
||||||
// for all targets, so that we can do cross-compilation!
|
|
||||||
#[cfg(unix)]
|
|
||||||
pub const HOST_UNIX: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/bitcode/builtins-host.o"));
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub const HOST_WINDOWS: &[u8] = include_bytes!(concat!(
|
|
||||||
env!("OUT_DIR"),
|
|
||||||
"/bitcode/builtins-windows-x86_64.obj"
|
|
||||||
));
|
|
||||||
|
|
||||||
pub fn host_wasm_tempfile() -> std::io::Result<NamedTempFile> {
|
|
||||||
let tempfile = tempfile::Builder::new()
|
|
||||||
.prefix("host_bitcode")
|
|
||||||
.suffix(".wasm")
|
|
||||||
.rand_bytes(8)
|
|
||||||
.tempfile()?;
|
|
||||||
|
|
||||||
std::fs::write(tempfile.path(), HOST_WASM)?;
|
|
||||||
|
|
||||||
Ok(tempfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
|
||||||
fn host_unix_tempfile() -> std::io::Result<NamedTempFile> {
|
|
||||||
let tempfile = tempfile::Builder::new()
|
|
||||||
.prefix("host_bitcode")
|
|
||||||
.suffix(".o")
|
|
||||||
.rand_bytes(8)
|
|
||||||
.tempfile()?;
|
|
||||||
|
|
||||||
std::fs::write(tempfile.path(), HOST_UNIX)?;
|
|
||||||
|
|
||||||
Ok(tempfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
fn host_windows_tempfile() -> std::io::Result<NamedTempFile> {
|
|
||||||
let tempfile = tempfile::Builder::new()
|
|
||||||
.prefix("host_bitcode")
|
|
||||||
.suffix(".obj")
|
|
||||||
.rand_bytes(8)
|
|
||||||
.tempfile()?;
|
|
||||||
|
|
||||||
std::fs::write(tempfile.path(), HOST_WINDOWS)?;
|
|
||||||
|
|
||||||
Ok(tempfile)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn host_tempfile() -> std::io::Result<NamedTempFile> {
|
|
||||||
#[cfg(unix)]
|
|
||||||
{
|
|
||||||
host_unix_tempfile()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
{
|
|
||||||
host_windows_tempfile()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(any(windows, unix)))]
|
|
||||||
{
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Default, Copy, Clone)]
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
pub struct IntrinsicName {
|
pub struct IntrinsicName {
|
||||||
|
|
|
@ -10,6 +10,7 @@ version.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
morphic_lib = { path = "../../vendor/morphic_lib" }
|
morphic_lib = { path = "../../vendor/morphic_lib" }
|
||||||
roc_alias_analysis = { path = "../alias_analysis" }
|
roc_alias_analysis = { path = "../alias_analysis" }
|
||||||
|
roc_bitcode_bc = { path = "../builtins/bitcode/bc" }
|
||||||
roc_builtins = { path = "../builtins" }
|
roc_builtins = { path = "../builtins" }
|
||||||
roc_collections = { path = "../collections" }
|
roc_collections = { path = "../collections" }
|
||||||
roc_debug_flags = { path = "../debug_flags" }
|
roc_debug_flags = { path = "../debug_flags" }
|
||||||
|
|
|
@ -19,6 +19,7 @@ wasi_libc_sys = { path = "../../wasi-libc-sys" }
|
||||||
tempfile.workspace = true
|
tempfile.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
roc_bitcode = { path = "../builtins/bitcode" }
|
||||||
roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] }
|
roc_build = { path = "../build", features = ["target-aarch64", "target-x86_64", "target-wasm32"] }
|
||||||
roc_builtins = { path = "../builtins" }
|
roc_builtins = { path = "../builtins" }
|
||||||
roc_can = { path = "../can" }
|
roc_can = { path = "../can" }
|
||||||
|
|
|
@ -100,8 +100,8 @@ fn build_wasm_test_host() {
|
||||||
let mut outfile = PathBuf::from(&out_dir).join(PLATFORM_FILENAME);
|
let mut outfile = PathBuf::from(&out_dir).join(PLATFORM_FILENAME);
|
||||||
outfile.set_extension("wasm");
|
outfile.set_extension("wasm");
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile()
|
||||||
bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
run_zig(&[
|
run_zig(&[
|
||||||
"wasm-ld",
|
"wasm-ld",
|
||||||
|
|
|
@ -208,7 +208,7 @@ pub fn helper(
|
||||||
std::fs::write(&app_o_file, module_out).expect("failed to write object to file");
|
std::fs::write(&app_o_file, module_out).expect("failed to write object to file");
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile =
|
||||||
bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
roc_bitcode::host_tempfile().expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
if false {
|
if false {
|
||||||
std::fs::copy(&app_o_file, "/tmp/app.o").unwrap();
|
std::fs::copy(&app_o_file, "/tmp/app.o").unwrap();
|
||||||
|
|
|
@ -11,6 +11,7 @@ version = "0.0.1"
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
|
roc_bitcode = { path = "../compiler/builtins/bitcode" }
|
||||||
roc_builtins = { path = "../compiler/builtins" }
|
roc_builtins = { path = "../compiler/builtins" }
|
||||||
wasi_libc_sys = { path = "../wasi-libc-sys" }
|
wasi_libc_sys = { path = "../wasi-libc-sys" }
|
||||||
|
|
||||||
|
|
|
@ -29,8 +29,8 @@ fn main() {
|
||||||
pre_linked_binary_path.extend(["pre_linked_binary"]);
|
pre_linked_binary_path.extend(["pre_linked_binary"]);
|
||||||
pre_linked_binary_path.set_extension(OBJECT_EXTENSION);
|
pre_linked_binary_path.set_extension(OBJECT_EXTENSION);
|
||||||
|
|
||||||
let builtins_host_tempfile =
|
let builtins_host_tempfile = roc_bitcode::host_wasm_tempfile()
|
||||||
bitcode::host_wasm_tempfile().expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
let output = Command::new(&zig_executable())
|
let output = Command::new(&zig_executable())
|
||||||
.args([
|
.args([
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue