mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Get zig host working
This commit is contained in:
parent
e8e7f9cad8
commit
da28b669bb
9 changed files with 157 additions and 90 deletions
|
@ -92,9 +92,9 @@ pub fn build_zig_host_native(
|
||||||
.env("PATH", env_path)
|
.env("PATH", env_path)
|
||||||
.env("HOME", env_home);
|
.env("HOME", env_home);
|
||||||
if let Some(shared_lib_path) = shared_lib_path {
|
if let Some(shared_lib_path) = shared_lib_path {
|
||||||
command.args(&["build-exe", shared_lib_path.to_str().unwrap()]);
|
command.args(&["build-exe", "-fPIE", shared_lib_path.to_str().unwrap()]);
|
||||||
} else {
|
} else {
|
||||||
command.arg("build-obj");
|
command.args(&["build-obj", "-fPIC"]);
|
||||||
}
|
}
|
||||||
command.args(&[
|
command.args(&[
|
||||||
zig_host_src,
|
zig_host_src,
|
||||||
|
@ -108,7 +108,6 @@ pub fn build_zig_host_native(
|
||||||
// include libc
|
// include libc
|
||||||
"--library",
|
"--library",
|
||||||
"c",
|
"c",
|
||||||
"-fPIC",
|
|
||||||
// cross-compile?
|
// cross-compile?
|
||||||
"-target",
|
"-target",
|
||||||
target,
|
target,
|
||||||
|
@ -176,9 +175,9 @@ pub fn build_zig_host_native(
|
||||||
.env("PATH", &env_path)
|
.env("PATH", &env_path)
|
||||||
.env("HOME", &env_home);
|
.env("HOME", &env_home);
|
||||||
if let Some(shared_lib_path) = shared_lib_path {
|
if let Some(shared_lib_path) = shared_lib_path {
|
||||||
command.args(&["build-exe", shared_lib_path.to_str().unwrap()]);
|
command.args(&["build-exe", "-fPIE", shared_lib_path.to_str().unwrap()]);
|
||||||
} else {
|
} else {
|
||||||
command.arg("build-obj");
|
command.args(&["build-obj", "-fPIC"]);
|
||||||
}
|
}
|
||||||
command.args(&[
|
command.args(&[
|
||||||
zig_host_src,
|
zig_host_src,
|
||||||
|
@ -195,7 +194,6 @@ pub fn build_zig_host_native(
|
||||||
// include libc
|
// include libc
|
||||||
"--library",
|
"--library",
|
||||||
"c",
|
"c",
|
||||||
"-fPIC",
|
|
||||||
]);
|
]);
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.args(&["-O", "ReleaseSafe"]);
|
command.args(&["-O", "ReleaseSafe"]);
|
||||||
|
@ -267,10 +265,11 @@ pub fn build_c_host_native(
|
||||||
.env("PATH", &env_path)
|
.env("PATH", &env_path)
|
||||||
.env("HOME", &env_home)
|
.env("HOME", &env_home)
|
||||||
.args(sources)
|
.args(sources)
|
||||||
.args(&["-fPIC", "-o", dest]);
|
.args(&["-o", dest]);
|
||||||
if let Some(shared_lib_path) = shared_lib_path {
|
if let Some(shared_lib_path) = shared_lib_path {
|
||||||
command.args(&[
|
command.args(&[
|
||||||
shared_lib_path.to_str().unwrap(),
|
shared_lib_path.to_str().unwrap(),
|
||||||
|
"-fPIE",
|
||||||
"-lm",
|
"-lm",
|
||||||
"-lpthread",
|
"-lpthread",
|
||||||
"-ldl",
|
"-ldl",
|
||||||
|
@ -278,7 +277,7 @@ pub fn build_c_host_native(
|
||||||
"-lutil",
|
"-lutil",
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
command.arg("-c");
|
command.args(&["-fPIC", "-c"]);
|
||||||
}
|
}
|
||||||
if matches!(opt_level, OptLevel::Optimize) {
|
if matches!(opt_level, OptLevel::Optimize) {
|
||||||
command.arg("-O2");
|
command.arg("-O2");
|
||||||
|
|
|
@ -33,6 +33,8 @@ const Align = extern struct { a: usize, b: usize };
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
||||||
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
||||||
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
||||||
|
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
||||||
|
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
||||||
|
|
||||||
const DEBUG: bool = false;
|
const DEBUG: bool = false;
|
||||||
|
|
||||||
|
@ -74,6 +76,14 @@ export fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void {
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void{
|
||||||
|
return memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void{
|
||||||
|
return memset(dst, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
const Unit = extern struct {};
|
const Unit = extern struct {};
|
||||||
|
|
||||||
pub fn main() u8 {
|
pub fn main() u8 {
|
||||||
|
|
|
@ -32,6 +32,8 @@ extern fn roc__mainForHost_1_Fx_result_size() i64;
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*c_void;
|
extern fn malloc(size: usize) callconv(.C) ?*c_void;
|
||||||
extern fn realloc(c_ptr: [*]align(@alignOf(u128)) u8, size: usize) callconv(.C) ?*c_void;
|
extern fn realloc(c_ptr: [*]align(@alignOf(u128)) u8, size: usize) callconv(.C) ?*c_void;
|
||||||
extern fn free(c_ptr: [*]align(@alignOf(u128)) u8) callconv(.C) void;
|
extern fn free(c_ptr: [*]align(@alignOf(u128)) u8) callconv(.C) void;
|
||||||
|
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
||||||
|
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
||||||
|
|
||||||
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void {
|
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void {
|
||||||
return malloc(size);
|
return malloc(size);
|
||||||
|
@ -52,6 +54,14 @@ export fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void {
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void{
|
||||||
|
return memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void{
|
||||||
|
return memset(dst, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
const Unit = extern struct {};
|
const Unit = extern struct {};
|
||||||
|
|
||||||
pub export fn main() u8 {
|
pub export fn main() u8 {
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
extern int rust_main();
|
extern int rust_main();
|
||||||
|
|
||||||
int main() {
|
int main() { return rust_main(); }
|
||||||
return rust_main();
|
|
||||||
|
void *roc_memcpy(void *dest, const void *src, size_t n) {
|
||||||
|
return memcpy(dest, src, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *roc_memset(void *str, int c, size_t n) { return memset(str, c, n); }
|
|
@ -1,36 +1,38 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
void* roc_alloc(size_t size, unsigned int alignment) {
|
void* roc_alloc(size_t size, unsigned int alignment) { return malloc(size); }
|
||||||
return malloc(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* roc_realloc(void* ptr, size_t old_size, size_t new_size, unsigned int alignment) {
|
void* roc_realloc(void* ptr, size_t old_size, size_t new_size,
|
||||||
|
unsigned int alignment) {
|
||||||
return realloc(ptr, new_size);
|
return realloc(ptr, new_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void roc_dealloc(void* ptr, unsigned int alignment) {
|
void roc_dealloc(void* ptr, unsigned int alignment) { free(ptr); }
|
||||||
free(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void roc_panic(void* ptr, unsigned int alignment) {
|
void roc_panic(void* ptr, unsigned int alignment) {
|
||||||
char* msg = (char*)ptr;
|
char* msg = (char*)ptr;
|
||||||
fprintf(stderr, "Application crashed with message\n\n %s\n\nShutting down\n", msg);
|
fprintf(stderr,
|
||||||
|
"Application crashed with message\n\n %s\n\nShutting down\n", msg);
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* roc_memcpy(void* dest, const void* src, size_t n) {
|
||||||
|
return memcpy(dest, src, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* roc_memset(void* str, int c, size_t n) { return memset(str, c, n); }
|
||||||
|
|
||||||
struct RocStr {
|
struct RocStr {
|
||||||
char* bytes;
|
char* bytes;
|
||||||
size_t len;
|
size_t len;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool is_small_str(struct RocStr str) {
|
bool is_small_str(struct RocStr str) { return ((ssize_t)str.len) < 0; }
|
||||||
return ((ssize_t)str.len) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Determine the length of the string, taking into
|
// Determine the length of the string, taking into
|
||||||
// account the small string optimization
|
// account the small string optimization
|
||||||
|
|
|
@ -23,6 +23,8 @@ const Align = extern struct { a: usize, b: usize };
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
||||||
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
||||||
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
||||||
|
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
||||||
|
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
||||||
|
|
||||||
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void {
|
export fn roc_alloc(size: usize, alignment: u32) callconv(.C) ?*c_void {
|
||||||
_ = alignment;
|
_ = alignment;
|
||||||
|
@ -51,6 +53,14 @@ export fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void {
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void{
|
||||||
|
return memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void{
|
||||||
|
return memset(dst, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
const mem = std.mem;
|
const mem = std.mem;
|
||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@ const Align = extern struct { a: usize, b: usize };
|
||||||
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
extern fn malloc(size: usize) callconv(.C) ?*align(@alignOf(Align)) c_void;
|
||||||
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
extern fn realloc(c_ptr: [*]align(@alignOf(Align)) u8, size: usize) callconv(.C) ?*c_void;
|
||||||
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
extern fn free(c_ptr: [*]align(@alignOf(Align)) u8) callconv(.C) void;
|
||||||
|
extern fn memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void;
|
||||||
|
extern fn memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void;
|
||||||
|
|
||||||
const DEBUG: bool = false;
|
const DEBUG: bool = false;
|
||||||
|
|
||||||
|
@ -67,6 +69,14 @@ export fn roc_panic(c_ptr: *c_void, tag_id: u32) callconv(.C) void {
|
||||||
std.process.exit(0);
|
std.process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export fn roc_memcpy(dst: [*]u8, src: [*]u8, size: usize) callconv(.C) void{
|
||||||
|
return memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn roc_memset(dst: [*]u8, value: i32, size: usize) callconv(.C) void{
|
||||||
|
return memset(dst, value, size);
|
||||||
|
}
|
||||||
|
|
||||||
// warning! the array is currently stack-allocated so don't make this too big
|
// warning! the array is currently stack-allocated so don't make this too big
|
||||||
const NUM_NUMS = 100;
|
const NUM_NUMS = 100;
|
||||||
|
|
||||||
|
|
|
@ -170,17 +170,18 @@ pub fn link_preprocessed_host(
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
let metadata = host_input_path.with_file_name("metadata");
|
let metadata = host_input_path.with_file_name("metadata");
|
||||||
let prehost = host_input_path.with_file_name("preprocessedhost");
|
let prehost = host_input_path.with_file_name("preprocessedhost");
|
||||||
|
std::fs::copy(prehost, binary_path)?;
|
||||||
if surgery_impl(
|
if surgery_impl(
|
||||||
roc_app_obj.to_str().unwrap(),
|
roc_app_obj.to_str().unwrap(),
|
||||||
metadata.to_str().unwrap(),
|
metadata.to_str().unwrap(),
|
||||||
prehost.to_str().unwrap(),
|
binary_path.to_str().unwrap(),
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
)? != 0
|
)? != 0
|
||||||
{
|
{
|
||||||
panic!("Failed to surgically link host");
|
panic!("Failed to surgically link host");
|
||||||
}
|
}
|
||||||
std::fs::rename(prehost, binary_path)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_dynamic_lib(
|
fn generate_dynamic_lib(
|
||||||
|
@ -197,8 +198,15 @@ fn generate_dynamic_lib(
|
||||||
|
|
||||||
let text_section = out_object.section_id(write::StandardSection::Text);
|
let text_section = out_object.section_id(write::StandardSection::Text);
|
||||||
for sym in exposed_to_host {
|
for sym in exposed_to_host {
|
||||||
|
for name in &[
|
||||||
|
format!("roc__{}_1_exposed", sym),
|
||||||
|
format!("roc__{}_1_Fx_caller", sym),
|
||||||
|
format!("roc__{}_1_Fx_size", sym),
|
||||||
|
format!("roc__{}_1_Fx_result_size", sym),
|
||||||
|
format!("roc__{}_size", sym),
|
||||||
|
] {
|
||||||
out_object.add_symbol(write::Symbol {
|
out_object.add_symbol(write::Symbol {
|
||||||
name: format!("roc__{}_1_exposed", sym).as_bytes().to_vec(),
|
name: name.as_bytes().to_vec(),
|
||||||
value: 0,
|
value: 0,
|
||||||
size: 0,
|
size: 0,
|
||||||
kind: SymbolKind::Text,
|
kind: SymbolKind::Text,
|
||||||
|
@ -208,6 +216,7 @@ fn generate_dynamic_lib(
|
||||||
flags: SymbolFlags::None,
|
flags: SymbolFlags::None,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::fs::write(
|
std::fs::write(
|
||||||
&dummy_obj_file,
|
&dummy_obj_file,
|
||||||
out_object.write().expect("failed to build output object"),
|
out_object.write().expect("failed to build output object"),
|
||||||
|
@ -994,16 +1003,22 @@ fn preprocess_impl(
|
||||||
}
|
}
|
||||||
|
|
||||||
let saving_metadata_start = SystemTime::now();
|
let saving_metadata_start = SystemTime::now();
|
||||||
|
// This block ensure that the metadata is fully written and timed before continuing.
|
||||||
|
{
|
||||||
let output = fs::File::create(metadata_filename)?;
|
let output = fs::File::create(metadata_filename)?;
|
||||||
let output = BufWriter::new(output);
|
let output = BufWriter::new(output);
|
||||||
if let Err(err) = serialize_into(output, &md) {
|
if let Err(err) = serialize_into(output, &md) {
|
||||||
println!("Failed to serialize metadata: {}", err);
|
println!("Failed to serialize metadata: {}", err);
|
||||||
return Ok(-1);
|
return Ok(-1);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
let saving_metadata_duration = saving_metadata_start.elapsed().unwrap();
|
let saving_metadata_duration = saving_metadata_start.elapsed().unwrap();
|
||||||
|
|
||||||
let flushing_data_start = SystemTime::now();
|
let flushing_data_start = SystemTime::now();
|
||||||
out_mmap.flush()?;
|
out_mmap.flush()?;
|
||||||
|
// Also drop files to to ensure data is fully written here.
|
||||||
|
drop(out_mmap);
|
||||||
|
drop(out_file);
|
||||||
let flushing_data_duration = flushing_data_start.elapsed().unwrap();
|
let flushing_data_duration = flushing_data_start.elapsed().unwrap();
|
||||||
|
|
||||||
let total_duration = total_start.elapsed().unwrap();
|
let total_duration = total_start.elapsed().unwrap();
|
||||||
|
@ -1523,9 +1538,11 @@ fn surgery_impl(
|
||||||
|
|
||||||
let flushing_data_start = SystemTime::now();
|
let flushing_data_start = SystemTime::now();
|
||||||
exec_mmap.flush()?;
|
exec_mmap.flush()?;
|
||||||
let flushing_data_duration = flushing_data_start.elapsed().unwrap();
|
// Also drop files to to ensure data is fully written here.
|
||||||
|
drop(exec_mmap);
|
||||||
exec_file.set_len(offset as u64 + 1)?;
|
exec_file.set_len(offset as u64 + 1)?;
|
||||||
|
drop(exec_file);
|
||||||
|
let flushing_data_duration = flushing_data_start.elapsed().unwrap();
|
||||||
|
|
||||||
// Make sure the final executable has permision to execute.
|
// Make sure the final executable has permision to execute.
|
||||||
let mut perms = fs::metadata(out_filename)?.permissions();
|
let mut perms = fs::metadata(out_filename)?.permissions();
|
||||||
|
|
4
linker/tests/fib/.gitignore
vendored
4
linker/tests/fib/.gitignore
vendored
|
@ -4,3 +4,7 @@ zig-cache
|
||||||
zig-out
|
zig-out
|
||||||
|
|
||||||
*.o
|
*.o
|
||||||
|
|
||||||
|
dynhost
|
||||||
|
preprocessedhost
|
||||||
|
metadata
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue