mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
try to use in-memory files in linux
This commit is contained in:
parent
e81875cca7
commit
d4e475338d
1 changed files with 99 additions and 53 deletions
152
cli/src/lib.rs
152
cli/src/lib.rs
|
@ -5,13 +5,14 @@ use build::BuiltFile;
|
||||||
use bumpalo::Bump;
|
use bumpalo::Bump;
|
||||||
use clap::{Arg, ArgMatches, Command};
|
use clap::{Arg, ArgMatches, Command};
|
||||||
use roc_build::link::LinkType;
|
use roc_build::link::LinkType;
|
||||||
use roc_error_macros::user_error;
|
use roc_error_macros::{internal_error, user_error};
|
||||||
use roc_load::{LoadingProblem, Threading};
|
use roc_load::{LoadingProblem, Threading};
|
||||||
use roc_mono::ir::OptLevel;
|
use roc_mono::ir::OptLevel;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::ffi::{CString, OsStr};
|
use std::ffi::{CString, OsStr};
|
||||||
use std::io;
|
use std::io::{self, Write};
|
||||||
use std::path::Path;
|
use std::os::unix::prelude::FromRawFd;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
use std::process;
|
use std::process;
|
||||||
use target_lexicon::BinaryFormat;
|
use target_lexicon::BinaryFormat;
|
||||||
use target_lexicon::{
|
use target_lexicon::{
|
||||||
|
@ -160,6 +161,14 @@ pub fn build_app<'a>() -> Command<'a> {
|
||||||
)
|
)
|
||||||
.subcommand(Command::new(CMD_RUN)
|
.subcommand(Command::new(CMD_RUN)
|
||||||
.about("Run a .roc file even if it has build errors")
|
.about("Run a .roc file even if it has build errors")
|
||||||
|
.arg(
|
||||||
|
Arg::new(FLAG_TARGET)
|
||||||
|
.long(FLAG_TARGET)
|
||||||
|
.help("Choose a different target")
|
||||||
|
.default_value(Target::default().as_str())
|
||||||
|
.possible_values(Target::OPTIONS)
|
||||||
|
.required(false),
|
||||||
|
)
|
||||||
.arg(flag_optimize.clone())
|
.arg(flag_optimize.clone())
|
||||||
.arg(flag_max_threads.clone())
|
.arg(flag_max_threads.clone())
|
||||||
.arg(flag_opt_size.clone())
|
.arg(flag_opt_size.clone())
|
||||||
|
@ -504,35 +513,35 @@ fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
|
||||||
) -> io::Result<i32> {
|
) -> io::Result<i32> {
|
||||||
match triple.architecture {
|
match triple.architecture {
|
||||||
Architecture::Wasm32 => {
|
Architecture::Wasm32 => {
|
||||||
todo!("figure out what to do with wasm");
|
let path = roc_run_executable_file_path(cwd, binary_bytes)?;
|
||||||
// // If possible, report the generated executable name relative to the current dir.
|
// If possible, report the generated executable name relative to the current dir.
|
||||||
// let generated_filename = binary_bytes
|
let generated_filename = path
|
||||||
// .strip_prefix(env::current_dir().unwrap())
|
.strip_prefix(env::current_dir().unwrap())
|
||||||
// .unwrap_or(binary_bytes);
|
.unwrap_or(&path);
|
||||||
//
|
|
||||||
// // No need to waste time freeing this memory,
|
// No need to waste time freeing this memory,
|
||||||
// // since the process is about to exit anyway.
|
// since the process is about to exit anyway.
|
||||||
// std::mem::forget(arena);
|
std::mem::forget(arena);
|
||||||
//
|
|
||||||
// if cfg!(target_family = "unix") {
|
if cfg!(target_family = "unix") {
|
||||||
// use std::os::unix::ffi::OsStrExt;
|
use std::os::unix::ffi::OsStrExt;
|
||||||
//
|
|
||||||
// run_with_wasmer(
|
run_with_wasmer(
|
||||||
// generated_filename,
|
generated_filename,
|
||||||
// args.into_iter().map(|os_str| os_str.as_bytes()),
|
args.into_iter().map(|os_str| os_str.as_bytes()),
|
||||||
// );
|
);
|
||||||
// } else {
|
} else {
|
||||||
// run_with_wasmer(
|
run_with_wasmer(
|
||||||
// generated_filename,
|
generated_filename,
|
||||||
// args.into_iter().map(|os_str| {
|
args.into_iter().map(|os_str| {
|
||||||
// os_str.to_str().expect(
|
os_str.to_str().expect(
|
||||||
// "Roc does not currently support passing non-UTF8 arguments to Wasmer.",
|
"Roc does not currently support passing non-UTF8 arguments to Wasmer.",
|
||||||
// )
|
)
|
||||||
// }),
|
}),
|
||||||
// );
|
);
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
if cfg!(target_family = "unix") {
|
if cfg!(target_family = "unix") {
|
||||||
|
@ -546,38 +555,75 @@ fn roc_run<'a, I: IntoIterator<Item = &'a OsStr>>(
|
||||||
|
|
||||||
fn roc_run_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
|
fn roc_run_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
|
||||||
cwd: &Path,
|
cwd: &Path,
|
||||||
args: I,
|
_args: I,
|
||||||
binary_bytes: &mut [u8],
|
binary_bytes: &mut [u8],
|
||||||
) -> ! {
|
) -> std::io::Result<i32> {
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let flags = 0;
|
let path = roc_run_executable_file_path(cwd, binary_bytes)?;
|
||||||
let fd = libc::memfd_create("roc_file_descriptor\0".as_ptr().cast(), flags);
|
let path_cstring = CString::new(path.as_os_str().as_bytes()).unwrap();
|
||||||
|
|
||||||
libc::write(fd, binary_bytes.as_ptr().cast(), binary_bytes.len());
|
|
||||||
|
|
||||||
// use std::path::PathBuf;
|
|
||||||
let path = format!("/proc/self/fd/{}\0", fd);
|
|
||||||
|
|
||||||
let array_with_null_pointer = &[0usize];
|
let array_with_null_pointer = &[0usize];
|
||||||
|
|
||||||
let c = libc::execve(
|
let execve_result = libc::execve(
|
||||||
path.as_ptr().cast(),
|
path_cstring.as_ptr().cast(),
|
||||||
array_with_null_pointer.as_ptr().cast(),
|
array_with_null_pointer.as_ptr().cast(),
|
||||||
array_with_null_pointer.as_ptr().cast(),
|
array_with_null_pointer.as_ptr().cast(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Get the current value of errno
|
if execve_result != 0 {
|
||||||
let e = errno::errno();
|
internal_error!(
|
||||||
|
"libc::execve({:?}, ..., ...) failed: {:?}",
|
||||||
// Extract the error code as an i32
|
path,
|
||||||
let code = e.0;
|
errno::errno()
|
||||||
|
);
|
||||||
// Display a human-friendly error message
|
}
|
||||||
println!("Error {}: {}", code, e);
|
|
||||||
println!("after {:?}", c);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable!()
|
Ok(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn roc_run_executable_file_path(cwd: &Path, binary_bytes: &mut [u8]) -> std::io::Result<PathBuf> {
|
||||||
|
if cfg!(target_os = "linux") {
|
||||||
|
// on linux, we use the `memfd_create` function to create an in-memory anonymous file.
|
||||||
|
let flags = 0;
|
||||||
|
let anonymous_file_name = "roc_file_descriptor\0";
|
||||||
|
let fd = unsafe { libc::memfd_create(anonymous_file_name.as_ptr().cast(), flags) };
|
||||||
|
|
||||||
|
if fd == 0 {
|
||||||
|
internal_error!(
|
||||||
|
"libc::memfd_create({:?}, {}) failed: file descriptor is 0",
|
||||||
|
anonymous_file_name,
|
||||||
|
flags
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: this `fd` is special, using the rust `std::fs::File` functions does not work
|
||||||
|
let write_result =
|
||||||
|
unsafe { libc::write(fd, binary_bytes.as_ptr().cast(), binary_bytes.len()) };
|
||||||
|
|
||||||
|
if write_result != 0 {
|
||||||
|
internal_error!(
|
||||||
|
"libc::write({:?}, ..., {}) failed: {:?}",
|
||||||
|
fd,
|
||||||
|
binary_bytes.len(),
|
||||||
|
errno::errno()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = format!("/proc/self/fd/{}", fd);
|
||||||
|
|
||||||
|
Ok(PathBuf::from(path))
|
||||||
|
} else {
|
||||||
|
// we have not found a way yet to use a virtual file on MacOs. Hence we fall back to just
|
||||||
|
// writing the file to the file system, and using that file.
|
||||||
|
let app_path_buf = cwd.join("roc_app_binary");
|
||||||
|
|
||||||
|
std::fs::write(&app_path_buf, binary_bytes)?;
|
||||||
|
|
||||||
|
Ok(app_path_buf)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn roc_run_non_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
|
fn roc_run_non_unix<I: IntoIterator<Item = S>, S: AsRef<OsStr>>(
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue