mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Make sure tempfiles don't get dropped too early
This commit is contained in:
parent
6b446fe592
commit
0b73ea69af
6 changed files with 46 additions and 25 deletions
|
@ -14,7 +14,6 @@ use roc_target::TargetInfo;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
use std::{path::PathBuf, thread::JoinHandle};
|
use std::{path::PathBuf, thread::JoinHandle};
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
use tempfile::Builder;
|
|
||||||
|
|
||||||
fn report_timing(buf: &mut String, label: &str, duration: Duration) {
|
fn report_timing(buf: &mut String, label: &str, duration: Duration) {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
@ -328,7 +327,7 @@ pub fn build_file<'a>(
|
||||||
problems
|
problems
|
||||||
}
|
}
|
||||||
(LinkingStrategy::Legacy, _) => {
|
(LinkingStrategy::Legacy, _) => {
|
||||||
let app_o_file = Builder::new()
|
let app_o_file = tempfile::Builder::new()
|
||||||
.prefix("roc_app")
|
.prefix("roc_app")
|
||||||
.suffix(&format!(".{}", app_extension))
|
.suffix(&format!(".{}", app_extension))
|
||||||
.tempfile()
|
.tempfile()
|
||||||
|
@ -342,17 +341,17 @@ pub fn build_file<'a>(
|
||||||
app_o_file.to_str().unwrap(),
|
app_o_file.to_str().unwrap(),
|
||||||
];
|
];
|
||||||
|
|
||||||
let builtins_host_file = tempfile::Builder::new()
|
let builtins_host_tempfile = tempfile::Builder::new()
|
||||||
.prefix("host_bitcode")
|
.prefix("host_bitcode")
|
||||||
.suffix(".o")
|
.suffix(".o")
|
||||||
.rand_bytes(5)
|
.rand_bytes(5)
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
std::fs::write(builtins_host_file.path(), bitcode::HOST_UNIX)
|
std::fs::write(builtins_host_tempfile.path(), bitcode::HOST_UNIX)
|
||||||
.expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
if matches!(code_gen_options.backend, program::CodeGenBackend::Assembly) {
|
if matches!(code_gen_options.backend, program::CodeGenBackend::Assembly) {
|
||||||
inputs.push(builtins_host_file.path().to_str().unwrap());
|
inputs.push(builtins_host_tempfile.path().to_str().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut child, _) = // TODO use lld
|
let (mut child, _) = // TODO use lld
|
||||||
|
@ -363,6 +362,10 @@ pub fn build_file<'a>(
|
||||||
.wait()
|
.wait()
|
||||||
.map_err(|_| todo!("gracefully handle error after `ld` spawned"))?;
|
.map_err(|_| todo!("gracefully handle error after `ld` spawned"))?;
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the child process is done using it!
|
||||||
|
let _ = builtins_host_tempfile;
|
||||||
|
|
||||||
if exit_status.success() {
|
if exit_status.success() {
|
||||||
problems
|
problems
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1417,19 +1417,19 @@ 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_file = tempfile::Builder::new()
|
let builtins_host_tempfile = tempfile::Builder::new()
|
||||||
.prefix("host_bitcode")
|
.prefix("host_bitcode")
|
||||||
.suffix(".wasm")
|
.suffix(".wasm")
|
||||||
.rand_bytes(5)
|
.rand_bytes(5)
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
std::fs::write(builtins_host_file.path(), bitcode::HOST_WASM)
|
std::fs::write(builtins_host_tempfile.path(), bitcode::HOST_WASM)
|
||||||
.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 = &[
|
||||||
"wasm-ld",
|
"wasm-ld",
|
||||||
builtins_host_file.path().to_str().unwrap(),
|
builtins_host_tempfile.path().to_str().unwrap(),
|
||||||
host_input,
|
host_input,
|
||||||
WASI_LIBC_PATH,
|
WASI_LIBC_PATH,
|
||||||
WASI_COMPILER_RT_PATH, // builtins need __multi3, __udivti3, __fixdfti
|
WASI_COMPILER_RT_PATH, // builtins need __multi3, __udivti3, __fixdfti
|
||||||
|
@ -1446,7 +1446,11 @@ pub fn preprocess_host_wasm32(host_input_path: &Path, preprocessed_host_path: &P
|
||||||
// println!("\npreprocess_host_wasm32");
|
// println!("\npreprocess_host_wasm32");
|
||||||
// println!("zig {}\n", args.join(" "));
|
// println!("zig {}\n", args.join(" "));
|
||||||
|
|
||||||
run_build_command(zig_cmd, output_file, 0)
|
run_build_command(zig_cmd, output_file, 0);
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the Zig process is done using it!
|
||||||
|
let _ = builtins_host_tempfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_build_command(mut command: Command, file_to_build: &str, flaky_fail_counter: usize) {
|
fn run_build_command(mut command: Command, file_to_build: &str, flaky_fail_counter: usize) {
|
||||||
|
|
|
@ -100,18 +100,18 @@ 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_file = tempfile::Builder::new()
|
let builtins_host_tempfile = tempfile::Builder::new()
|
||||||
.prefix("host_bitcode")
|
.prefix("host_bitcode")
|
||||||
.suffix(".wasm")
|
.suffix(".wasm")
|
||||||
.rand_bytes(5)
|
.rand_bytes(5)
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
std::fs::write(builtins_host_file.path(), bitcode::HOST_WASM)
|
std::fs::write(builtins_host_tempfile.path(), bitcode::HOST_WASM)
|
||||||
.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",
|
||||||
builtins_host_file.path().to_str().unwrap(),
|
builtins_host_tempfile.path().to_str().unwrap(),
|
||||||
platform_path.to_str().unwrap(),
|
platform_path.to_str().unwrap(),
|
||||||
WASI_COMPILER_RT_PATH,
|
WASI_COMPILER_RT_PATH,
|
||||||
WASI_LIBC_PATH,
|
WASI_LIBC_PATH,
|
||||||
|
@ -120,6 +120,10 @@ fn build_wasm_test_host() {
|
||||||
"--no-entry",
|
"--no-entry",
|
||||||
"--relocatable",
|
"--relocatable",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the Zig process is done using it!
|
||||||
|
let _ = builtins_host_tempfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_wasm_platform(out_dir: &str, source_path: &str) -> PathBuf {
|
fn build_wasm_platform(out_dir: &str, source_path: &str) -> PathBuf {
|
||||||
|
|
|
@ -193,13 +193,13 @@ pub fn helper(
|
||||||
.expect("failed to build output object");
|
.expect("failed to build output object");
|
||||||
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_file = tempfile::Builder::new()
|
let builtins_host_tempfile = tempfile::Builder::new()
|
||||||
.prefix("host_bitcode")
|
.prefix("host_bitcode")
|
||||||
.suffix(".o")
|
.suffix(".o")
|
||||||
.rand_bytes(5)
|
.rand_bytes(5)
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
std::fs::write(builtins_host_file.path(), bitcode::HOST_UNIX)
|
std::fs::write(builtins_host_tempfile.path(), bitcode::HOST_UNIX)
|
||||||
.expect("failed to write host builtins object to tempfile");
|
.expect("failed to write host builtins object to tempfile");
|
||||||
|
|
||||||
let (mut child, dylib_path) = link(
|
let (mut child, dylib_path) = link(
|
||||||
|
@ -209,7 +209,7 @@ pub fn helper(
|
||||||
// With the current method all methods are kept and it adds about 100k to all outputs.
|
// With the current method all methods are kept and it adds about 100k to all outputs.
|
||||||
&[
|
&[
|
||||||
app_o_file.to_str().unwrap(),
|
app_o_file.to_str().unwrap(),
|
||||||
builtins_host_file.path().to_str().unwrap(),
|
builtins_host_tempfile.path().to_str().unwrap(),
|
||||||
],
|
],
|
||||||
LinkType::Dylib,
|
LinkType::Dylib,
|
||||||
)
|
)
|
||||||
|
@ -217,6 +217,10 @@ pub fn helper(
|
||||||
|
|
||||||
child.wait().unwrap();
|
child.wait().unwrap();
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the linking process is done using it!
|
||||||
|
let _ = builtins_host_tempfile;
|
||||||
|
|
||||||
// Load the dylib
|
// Load the dylib
|
||||||
let path = dylib_path.as_path().to_str().unwrap();
|
let path = dylib_path.as_path().to_str().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,17 @@ use roc_error_macros::internal_error;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use target_lexicon::Triple;
|
use target_lexicon::Triple;
|
||||||
use tempfile::Builder;
|
|
||||||
|
|
||||||
// TODO: Eventually do this from scratch and in memory instead of with ld.
|
// TODO: Eventually do this from scratch and in memory instead of with ld.
|
||||||
pub fn create_dylib_macho(
|
pub fn create_dylib_macho(
|
||||||
custom_names: &[String],
|
custom_names: &[String],
|
||||||
triple: &Triple,
|
triple: &Triple,
|
||||||
) -> object::read::Result<Vec<u8>> {
|
) -> object::read::Result<Vec<u8>> {
|
||||||
let dummy_obj_file = Builder::new()
|
let dummy_obj_file = tempfile::Builder::new()
|
||||||
.prefix("roc_lib")
|
.prefix("roc_lib")
|
||||||
.suffix(".o")
|
.suffix(".o")
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap_or_else(|e| internal_error!("{}", e));
|
.unwrap_or_else(|e| internal_error!("{}", e));
|
||||||
let dummy_obj_file = dummy_obj_file.path();
|
|
||||||
let tmp = tempfile::tempdir().unwrap_or_else(|e| internal_error!("{}", e));
|
let tmp = tempfile::tempdir().unwrap_or_else(|e| internal_error!("{}", e));
|
||||||
let dummy_lib_file = tmp.path().to_path_buf().with_file_name("libapp.so");
|
let dummy_lib_file = tmp.path().to_path_buf().with_file_name("libapp.so");
|
||||||
|
|
||||||
|
@ -47,7 +45,7 @@ pub fn create_dylib_macho(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
dummy_obj_file,
|
dummy_obj_file.path(),
|
||||||
out_object.write().expect("failed to build output object"),
|
out_object.write().expect("failed to build output object"),
|
||||||
)
|
)
|
||||||
.expect("failed to write object to file");
|
.expect("failed to write object to file");
|
||||||
|
@ -70,13 +68,17 @@ pub fn create_dylib_macho(
|
||||||
.args([
|
.args([
|
||||||
ld_flag_soname,
|
ld_flag_soname,
|
||||||
dummy_lib_file.file_name().unwrap().to_str().unwrap(),
|
dummy_lib_file.file_name().unwrap().to_str().unwrap(),
|
||||||
dummy_obj_file.to_str().unwrap(),
|
dummy_obj_file.path().to_str().unwrap(),
|
||||||
"-o",
|
"-o",
|
||||||
dummy_lib_file.to_str().unwrap(),
|
dummy_lib_file.to_str().unwrap(),
|
||||||
])
|
])
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the linker process is done using it!
|
||||||
|
let _ = dummy_obj_file;
|
||||||
|
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
match std::str::from_utf8(&output.stderr) {
|
match std::str::from_utf8(&output.stderr) {
|
||||||
Ok(stderr) => panic!(
|
Ok(stderr) => panic!(
|
||||||
|
|
|
@ -23,19 +23,19 @@ fn main() {
|
||||||
pre_linked_binary_path.extend(["pre_linked_binary"]);
|
pre_linked_binary_path.extend(["pre_linked_binary"]);
|
||||||
pre_linked_binary_path.set_extension("o");
|
pre_linked_binary_path.set_extension("o");
|
||||||
|
|
||||||
let builtins_host_file = tempfile::Builder::new()
|
let builtins_host_tempfile = tempfile::Builder::new()
|
||||||
.prefix("host_bitcode")
|
.prefix("host_bitcode")
|
||||||
.suffix(".wasm")
|
.suffix(".wasm")
|
||||||
.rand_bytes(5)
|
.rand_bytes(5)
|
||||||
.tempfile()
|
.tempfile()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
std::fs::write(builtins_host_file.path(), bitcode::HOST_WASM)
|
std::fs::write(builtins_host_tempfile.path(), bitcode::HOST_WASM)
|
||||||
.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([
|
||||||
"wasm-ld",
|
"wasm-ld",
|
||||||
builtins_host_file.path().to_str().unwrap(),
|
builtins_host_tempfile.path().to_str().unwrap(),
|
||||||
platform_obj.to_str().unwrap(),
|
platform_obj.to_str().unwrap(),
|
||||||
WASI_COMPILER_RT_PATH,
|
WASI_COMPILER_RT_PATH,
|
||||||
WASI_LIBC_PATH,
|
WASI_LIBC_PATH,
|
||||||
|
@ -48,6 +48,10 @@ fn main() {
|
||||||
.output()
|
.output()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
// Extend the lifetime of the tempfile so it doesn't get dropped
|
||||||
|
// (and thus deleted) before the Zig process is done using it!
|
||||||
|
let _ = builtins_host_tempfile;
|
||||||
|
|
||||||
assert!(output.status.success(), "{:#?}", output);
|
assert!(output.status.success(), "{:#?}", output);
|
||||||
assert!(output.stdout.is_empty(), "{:#?}", output);
|
assert!(output.stdout.is_empty(), "{:#?}", output);
|
||||||
assert!(output.stderr.is_empty(), "{:#?}", output);
|
assert!(output.stderr.is_empty(), "{:#?}", output);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue