libc/wip: add code to install ygglibc

This commit is contained in:
2024-11-11 23:50:38 +02:00
parent e0600c2bf6
commit 98862b1e49
22 changed files with 845 additions and 66 deletions
+3 -3
View File
@@ -1,9 +1,9 @@
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
int main() {
char buf[512];
int v = 1234 + 3;
snprintf(buf, sizeof(buf), "Hello %d\n", v);
printf("Hello!\n");
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
/llvm-project
/prefix
/sysroot
+11
View File
@@ -0,0 +1,11 @@
#ifndef _ASSERT_H
#define _ASSERT_H 1
#define __ASSERT_VOID_CAST (void)
#define assert(expr) \
((expr) ? __ASSERT_VOID_CAST(0) : __assert_fail(__FILE__, __LINE__, #expr))
[[noreturn]] void __assert_fail(const char *file, int line, const char *message);
#endif
@@ -0,0 +1,6 @@
#ifndef _YGGDRASIL_LOCALE_H
#define _YGGDRASIL_LOCALE_H 1
#define LC_GLOBAL_LOCALE ((locale_t) -1L)
#endif
+32 -19
View File
@@ -5,7 +5,7 @@ use core::{
use libyalloc::{allocator::BucketAllocator, sys::PageProvider};
use yggdrasil_rt::{mem::MappingSource, sys as syscall};
use crate::error::EResult;
use crate::{error::EResult, headers::errno};
struct Allocator;
struct PageProviderImpl;
@@ -45,28 +45,41 @@ impl PageProvider for PageProviderImpl {
const MALLOC_HEADER_SIZE: usize = size_of::<usize>();
fn c_alloc(size: usize, mut align: usize, zero: bool) -> EResult<NonNull<c_void>> {
// assert!(align.is_power_of_two());
// if align < align_of::<usize>() {
// align = align_of::<usize>();
// }
// let offset = (MALLOC_HEADER_SIZE + align - 1) & !(align - 1);
// let size = offset + size;
// let layout = Layout::from_size_align(size, align).ok()?;
unsafe fn get_allocation(ptr: NonNull<u8>) -> (NonNull<u8>, Layout) {
assert!(usize::from(ptr.addr()) > 0x10);
let real_ptr = ptr.sub(MALLOC_HEADER_SIZE);
let size = *real_ptr.cast::<usize>().as_ref();
let layout = Layout::from_size_align(size, 16).unwrap();
(real_ptr, layout)
}
// let ptr = unsafe { YALLOC.allocate(layout) }?;
pub fn c_alloc(size: usize, mut align: usize, zero: bool) -> EResult<NonNull<c_void>> {
assert!(align.is_power_of_two());
if align < align_of::<usize>() {
align = align_of::<usize>();
}
if align > 16 {
todo!()
}
let offset = (MALLOC_HEADER_SIZE + align - 1) & !(align - 1);
let size = offset + size;
let layout = Layout::from_size_align(size, align).unwrap();
// if zero {
// // TODO
// }
let ptr = match unsafe { YALLOC.allocate(layout) } {
Some(value) => value,
None => return EResult::Err(errno::ENOMEM),
};
// unsafe {
// // Write the size right below the pointer
// ptr.add(offset - size_of::<usize>()).cast::<usize>().write(size);
// }
if zero {
// TODO
}
todo!()
// unsafe { Some(ptr.cast::<c_void>().add(offset)) }
unsafe {
// Write the size right below the pointer
ptr.add(offset - size_of::<usize>()).cast::<usize>().write(size);
}
unsafe { EResult::Ok(ptr.cast::<c_void>().add(offset)) }
}
pub unsafe fn malloc(size: usize) -> EResult<NonNull<c_void>> {
@@ -0,0 +1,14 @@
language = "C"
style = "Tag"
sys_includes = ["stddef.h"]
no_includes = true
include_guard = "_LOCALE_H"
trailer = "#include <bits/locale.h>"
usize_type = "size_t"
isize_type = "ssize_t"
[export]
include = ["lconv", "locale_t"]
@@ -0,0 +1,88 @@
use core::{
ffi::{c_char, c_int},
ptr::null_mut,
};
#[derive(Clone, Copy)]
#[repr(C)]
pub struct lconv {
pub currency_symbol: *mut c_char,
pub decimal_point: *mut c_char,
pub frac_digits: c_char,
pub grouping: *mut c_char,
pub int_curr_symbol: *mut c_char,
pub int_frac_digits: c_char,
pub int_n_cs_precedes: c_char,
pub int_n_sep_by_space: c_char,
pub int_n_sign_posn: c_char,
pub int_p_cs_precedes: c_char,
pub int_p_sep_by_space: c_char,
pub int_p_sign_posn: c_char,
pub mon_decimal_point: *mut c_char,
pub mon_grouping: *mut c_char,
pub mon_thousands_sep: *mut c_char,
pub negative_sign: *mut c_char,
pub n_cs_precedes: c_char,
pub n_sep_by_space: c_char,
pub n_sign_posn: c_char,
pub positive_sign: *mut c_char,
pub p_cs_precedes: c_char,
pub p_sep_by_space: c_char,
pub p_sign_posn: c_char,
pub thousands_sep: *mut c_char,
}
pub struct __locale_data {}
#[derive(Clone, Copy)]
#[repr(C)]
pub struct __locale_struct {
pub __locales: [*mut __locale_data; __LC_LAST],
}
pub type locale_t = *mut __locale_struct;
pub const LC_COLLATE: c_int = 0;
pub const LC_CTYPE: c_int = 1;
pub const LC_MESSAGES: c_int = 2;
pub const LC_MONETARY: c_int = 3;
pub const LC_NUMERIC: c_int = 4;
pub const LC_TIME: c_int = 5;
pub const LC_ALL: c_int = 6;
pub const __LC_LAST: usize = 6;
#[no_mangle]
unsafe extern "C" fn duplocale(locobj: locale_t) -> locale_t {
todo!()
}
#[no_mangle]
unsafe extern "C" fn freelocale(locobj: locale_t) {
todo!()
}
#[no_mangle]
unsafe extern "C" fn localeconv() -> *mut lconv {
todo!()
}
#[no_mangle]
unsafe extern "C" fn newlocale(
category_mask: c_int,
locale: *const c_char,
base: locale_t,
) -> locale_t {
todo!()
}
#[no_mangle]
unsafe extern "C" fn setlocale(category: c_int, locale: *const c_char) -> *mut c_char {
// TODO
null_mut()
}
#[no_mangle]
unsafe extern "C" fn uselocale(locobj: locale_t) -> locale_t {
todo!()
}
+86
View File
@@ -1,8 +1,94 @@
#![allow(non_camel_case_types)]
// <aio.h> -
// <arpa/inet.h> -
// <assert.h> -
// <complex.h> -
// <cpio.h> -
// <ctype.h> -
// <dirent.h> -
// <dlfcn.h> -
// <errno.h> ~
// <fcntl.h> -
// <fenv.h> -
// <float.h> -
// <fmtmsg.h> -
// <fnmatch.h> -
// <ftw.h> -
// <glob.h> -
// <grp.h> -
// <iconv.h> -
// <inttypes.h> -
// <iso646.h> -
// <langinfo.h> -
// <libgen.h> -
// <limits.h> -
// <locale.h> ~
// <math.h> -
// <monetary.h> -
// <mqueue.h> -
// <ndbm.h> -
// <net/if.h> -
// <netdb.h> -
// <netinet/in.h> -
// <netinet/tcp.h> -
// <nl_types.h> -
// <poll.h> -
// <pthread.h> -
// <pwd.h> -
// <regex.h> -
// <sched.h> -
// <search.h> -
// <semaphore.h> -
// <setjmp.h> -
// <signal.h> -
// <spawn.h> -
// <stdarg.h> -
// <stdbool.h> -
// <stddef.h> -
// <stdint.h> -
// <stdio.h> ~
// <stdlib.h> -
// <string.h> -
// <strings.h> -
// <stropts.h> -
// <sys/ipc.h> -
// <sys/mman.h> -
// <sys/msg.h> -
// <sys/resource.h> -
// <sys/select.h> -
// <sys/sem.h> -
// <sys/shm.h> -
// <sys/socket.h> -
// <sys/stat.h> -
// <sys/statvfs.h> -
// <sys/time.h> -
// <sys/times.h> -
// <sys/types.h> -
// <sys/uio.h> -
// <sys/un.h> -
// <sys/utsname.h> -
// <sys/wait.h> -
// <syslog.h> -
// <tar.h> -
// <termios.h> -
// <tgmath.h> -
// <time.h> -
// <trace.h> -
// <ulimit.h> -
// <unistd.h> ~
// <utime.h> -
// <utmpx.h> -
// <wchar.h> -
// <wctype.h> -
// <wordexp.h> -
pub mod errno;
pub mod locale;
pub mod stdio;
pub mod stdlib;
pub mod string;
pub mod unistd;
pub mod strings;
pub mod sys_types;
@@ -1,9 +1,9 @@
use core::ffi::{c_char, c_int, c_void};
use crate::{
error::CUsizeResult,
io::{managed::FILE, Read, Write},
util::PointerExt,
error::{CEofResult, CUsizeResult},
io::{managed::{stdout, FILE}, Read, Write},
util::{PointerExt, PointerStrExt},
};
#[no_mangle]
@@ -115,8 +115,12 @@ unsafe extern "C" fn putchar_unlocked(ch: c_int) -> c_int {
}
#[no_mangle]
unsafe extern "C" fn puts(str: *const c_char) -> c_int {
todo!()
unsafe extern "C" fn puts(str: *const c_char) -> CEofResult {
let str = str.ensure_cstr();
let out = stdout.ensure_mut();
out.write_all(str.to_bytes())?;
out.write_all(b"\n")?;
CEofResult::success(0)
}
#[no_mangle]
@@ -23,4 +23,3 @@ pub type fpos_t = u64;
pub const BUFSIZ: usize = 8192;
const UNGETC_MAX: usize = 128;
@@ -0,0 +1,12 @@
language = "C"
style = "Type"
sys_includes = ["stddef.h", "locale.h", "strings.h"]
no_includes = true
include_guard = "_STRING_H"
usize_type = "size_t"
isize_type = "ssize_t"
[export]
@@ -0,0 +1,71 @@
use core::{ffi::{c_int, c_void}, ptr::null_mut};
#[no_mangle]
unsafe extern "C" fn memccpy(
dst: *mut c_void,
src: *const c_void,
c: c_int,
mut n: usize,
) -> *mut c_void {
let c = c as u8;
let mut dst = dst as *mut u8;
let mut src = src as *mut u8;
if dst.is_null() || src.is_null() {
panic!();
}
while n != 0 {
let ch = *src;
*dst = ch;
dst = dst.add(1);
if ch == c {
return dst as _;
}
src = src.add(1);
n -= 1;
}
null_mut()
}
#[no_mangle]
unsafe extern "C" fn memchr(s: *const c_void, c: c_int, mut n: usize) -> *mut c_void {
if s.is_null() {
panic!();
}
let c = c as u8;
let mut s = s as *const u8;
while n != 0 {
if *s == c {
return s as _;
}
s = s.add(1);
n -= 1;
}
null_mut()
}
#[no_mangle]
pub(super) unsafe extern "C" fn mempcpy(
dst: *mut c_void,
src: *const c_void,
n: usize,
) -> *mut c_void {
if dst.is_null() || src.is_null() {
panic!();
}
let dst = dst as *mut u8;
let src = src as *const u8;
for i in 0..n {
*dst.add(i) = *src.add(i);
}
dst.add(n) as _
}
@@ -0,0 +1,10 @@
use core::ffi::{c_char, c_int, c_void};
pub mod mem;
pub mod str;
extern "C" {
pub fn strlen(s: *const c_char) -> usize;
pub fn memset(a: *mut c_void, c: c_int, n: usize) -> *mut c_void;
pub fn memcpy(dst: *mut c_void, src: *const c_void, n: usize) -> *mut c_void;
}
@@ -0,0 +1,336 @@
use core::{
cmp::Ordering,
ffi::{c_char, c_int},
ptr::null_mut,
};
use crate::{
allocator,
error::CPtrResult,
headers::{
errno::{self, Errno},
locale::locale_t,
},
};
use super::{mem::mempcpy, memcpy, memset, strlen};
#[no_mangle]
unsafe extern "C" fn stpcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
if dst.is_null() || src.is_null() {
panic!();
}
let ptr = mempcpy(dst as _, src as _, strlen(src)) as *mut c_char;
*ptr = 0;
ptr
}
#[no_mangle]
unsafe extern "C" fn stpncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
if dst.is_null() || src.is_null() {
panic!();
}
memset(dst as _, 0, n);
mempcpy(dst as _, src as _, strnlen(src, n)) as _
}
#[no_mangle]
unsafe extern "C" fn strcat(dst: *mut c_char, src: *const c_char) -> *mut c_char {
if dst.is_null() {
panic!();
}
stpcpy(dst.add(strlen(dst)), src);
dst
}
#[no_mangle]
unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
if s.is_null() {
panic!();
}
loop {
if *s == c as _ {
return s as _;
}
if *s == 0 {
break;
}
s = s.add(1);
}
null_mut()
}
#[no_mangle]
unsafe extern "C" fn strcmp(a: *const c_char, b: *const c_char) -> c_int {
strncmp(a, b, usize::MAX)
}
#[no_mangle]
unsafe extern "C" fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
stpcpy(dst, src);
dst
}
#[no_mangle]
unsafe extern "C" fn strcspn(mut s: *const c_char, reject: *const c_char) -> usize {
if s.is_null() || reject.is_null() {
panic!();
}
let mut n = 0;
while *s != 0 {
if !strchr(reject, *s as _).is_null() {
return n;
}
n += 1;
s = s.add(1);
}
n
}
#[no_mangle]
unsafe extern "C" fn strdup(s: *const c_char) -> CPtrResult<c_char> {
let len = strlen(s);
let data = allocator::c_alloc(len + 1, 1, false)?;
memcpy(data.cast().as_ptr(), s as _, len + 1);
CPtrResult::success(data.cast())
}
unsafe fn strerror_inner(e: c_int) -> *const c_char {
if let Some(errno) = Errno::from_c_int(e) {
errno.to_c_str()
} else {
errno::UNKNOWN_ERROR.as_ptr()
}
}
#[no_mangle]
unsafe extern "C" fn strerror(e: c_int) -> *mut c_char {
static mut BUF: [c_char; 128] = [0; 128];
#[allow(static_mut_refs)]
strerror_r(e, BUF.as_mut_ptr(), BUF.len())
}
#[no_mangle]
unsafe extern "C" fn strerror_r(e: c_int, buf: *mut c_char, n: usize) -> *mut c_char {
let source = strerror_inner(e);
strncpy(buf, source, n)
}
#[no_mangle]
unsafe extern "C" fn strncat(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
if dst.is_null() || src.is_null() {
panic!();
}
let len = strnlen(src, n);
let ptr = dst.add(strlen(dst));
let ptr = mempcpy(ptr as _, src as _, len) as *mut c_char;
*ptr = 0;
dst
}
#[no_mangle]
unsafe extern "C" fn strncmp(mut a: *const c_char, mut b: *const c_char, mut n: usize) -> c_int {
if a.is_null() {
panic!();
}
if b.is_null() {
panic!();
}
if a == b {
return 0;
}
while n != 0 {
match Ord::cmp(&*a, &*b) {
Ordering::Less => return -1,
Ordering::Greater => return 1,
Ordering::Equal => (),
}
if *a == 0 {
break;
}
a = a.add(1);
b = b.add(1);
n -= 1;
}
0
}
#[no_mangle]
unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
stpncpy(dst, src, n);
dst
}
#[no_mangle]
unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strnlen(s: *const c_char, n: usize) -> usize {
if s.is_null() {
panic!();
}
for i in 0..n {
if *s.add(i) == 0 {
return i;
}
}
n
}
#[no_mangle]
unsafe extern "C" fn strpbrk(mut a: *const c_char, b: *const c_char) -> *mut c_char {
if a.is_null() || b.is_null() {
return null_mut();
}
loop {
let c = *a;
if c == 0 {
break;
}
if !strchr(b, c as _).is_null() {
return a as _;
}
a = a.add(1);
}
null_mut()
}
#[no_mangle]
unsafe extern "C" fn strrchr(a: *const c_char, c: c_int) -> *mut c_char {
if a.is_null() {
return null_mut();
}
let n = strnlen(a, usize::MAX);
for i in (0..n).rev() {
if *a.add(i) == c as _ {
return a.add(i) as _;
}
}
null_mut()
}
#[no_mangle]
unsafe extern "C" fn strsignal(signum: c_int) -> *mut c_char {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strspn(mut s: *const c_char, accept: *const c_char) -> usize {
if s.is_null() || accept.is_null() {
panic!();
}
let mut n = 0;
while *s != 0 {
if strchr(accept, *s as _).is_null() {
return n;
}
n += 1;
s = s.add(1);
}
n
}
#[no_mangle]
unsafe extern "C" fn strstr(mut a: *const c_char, b: *const c_char) -> *mut c_char {
if a.is_null() || b.is_null() {
panic!();
}
let n = strnlen(b, usize::MAX);
if *a == 0 && *b == 0 {
return a as _;
}
while *a != 0 {
if strncmp(a, b, n) == 0 {
return a as _;
}
a = a.add(1);
}
null_mut()
}
#[no_mangle]
unsafe extern "C" fn strtok(str: *mut c_char, delim: *const c_char) -> *mut c_char {
static mut STRTOK_BUF: *mut c_char = null_mut();
if !str.is_null() {
STRTOK_BUF = null_mut();
}
strtok_r(str, delim, &raw mut STRTOK_BUF)
}
#[no_mangle]
unsafe extern "C" fn strtok_r(
mut str: *mut c_char,
delim: *const c_char,
saveptr: *mut *mut c_char,
) -> *mut c_char {
if saveptr.is_null() || delim.is_null() {
panic!();
}
if str.is_null() {
str = *saveptr;
}
str = str.add(strspn(str, delim));
if *str == 0 {
*saveptr = null_mut();
return null_mut();
}
let len = strcspn(str, delim);
if *str.add(len) != 0 {
*saveptr = str.add(len + 1);
} else {
*saveptr = null_mut();
}
*str.add(len) = 0;
str as _
}
// TODO locales
#[no_mangle]
unsafe extern "C" fn strcoll(a: *const c_char, b: *const c_char) -> c_int {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strcoll_l(a: *const c_char, b: *const c_char, l: locale_t) -> c_int {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strerror_l(e: c_int, l: locale_t) -> *mut c_char {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strxfrm(a: *mut c_char, b: *const c_char, n: usize) -> usize {
todo!()
}
#[no_mangle]
unsafe extern "C" fn strxfrm_l(a: *mut c_char, b: *const c_char, n: usize, l: locale_t) -> usize {
todo!()
}
@@ -0,0 +1,13 @@
language = "C"
style = "Type"
sys_includes = ["stddef.h"]
no_includes = true
include_guard = "_STRINGS_H"
usize_type = "size_t"
isize_type = "ssize_t"
[export]
exclude = []
@@ -0,0 +1,29 @@
use core::{
cmp::Ordering,
ffi::{c_char, c_int},
};
#[no_mangle]
unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int {
strncasecmp(s1, s2, usize::MAX)
}
#[no_mangle]
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
for i in 0..n {
let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
let c1 = (*s2.add(i) as u8).to_ascii_lowercase();
match c0.cmp(&c1) {
Ordering::Less => return -1,
Ordering::Equal => (),
Ordering::Greater => return 1,
}
if c0 == 0 {
break;
}
}
0
}
+7 -2
View File
@@ -1,8 +1,7 @@
#![allow(non_upper_case_globals)]
use core::{
ops::{Deref, DerefMut},
ptr::{null_mut, NonNull},
fmt, ops::{Deref, DerefMut}, ptr::{null_mut, NonNull}
};
use alloc::{boxed::Box, collections::btree_set::BTreeSet};
@@ -331,6 +330,12 @@ impl FileOpenSource for &Path {
}
}
impl fmt::Write for FILE {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write_all(s.as_bytes()).into_result(|_| fmt::Error, true)
}
}
#[no_mangle]
pub static mut stdout: *mut FILE = null_mut();
#[no_mangle]
+25 -2
View File
@@ -1,8 +1,8 @@
use core::{ffi::c_int, time::Duration};
use core::{ffi::{c_char, c_int, CStr}, ptr::NonNull, time::Duration};
use yggdrasil_rt::{process::ExitCode, sys as syscall};
use crate::{error::EResult, headers::sys_types::pid_t, io};
use crate::{error::EResult, headers::sys_types::pid_t, io::{self, managed::stderr}};
pub fn getpid() -> pid_t {
let pid = unsafe { syscall::get_pid() };
@@ -19,6 +19,10 @@ pub fn sleep(duration: Duration) -> EResult<()> {
EResult::Ok(())
}
pub fn abort() -> ! {
todo!()
}
pub fn c_exit_immediately(status: c_int) -> ! {
let code = ExitCode::Exited(status);
unsafe { syscall::exit_process(code) };
@@ -34,3 +38,22 @@ pub fn c_exit(status: c_int) -> ! {
unsafe fn pre_exit() {
io::cleanup();
}
#[no_mangle]
unsafe extern "C" fn __assert_fail(file: *const c_char, line: c_int, message: *const c_char) -> ! {
use core::fmt::Write;
let err = stderr.as_mut().unwrap();
let file = match file.is_null() {
false => CStr::from_ptr(file).to_str().ok(),
true => None
}.unwrap_or("???");
let expr = match message.is_null() {
false => CStr::from_ptr(message).to_str().ok(),
true => None
}.unwrap_or("???");
writeln!(err, "Assertion failed: '{}' at {}:{}", expr, file, line).ok();
abort()
}
+23
View File
@@ -0,0 +1,23 @@
use std::{path::PathBuf, process::Command};
use crate::{env::BuildEnv, error::Error};
pub struct Llvm {
root: PathBuf,
}
impl Llvm {
pub fn c_clang(&self, env: &BuildEnv) -> Command {
let mut command = Command::new(self.root.join("bin/clang"));
command.arg(format!("--target={}-unknown-yggdrasil", env.arch.name()));
command.arg(format!("--sysroot={}", env.llvm_sysroot.display()));
command
}
}
pub fn build_llvm(env: &BuildEnv) -> Result<Llvm, Error> {
// TODO actually build and install LLVM
Ok(Llvm {
root: env.workspace_root.join("toolchain-c/prefix/host"),
})
}
+1
View File
@@ -14,6 +14,7 @@ pub mod i686;
pub mod x86_64;
mod cargo;
pub mod llvm;
mod module;
pub mod toolchain;
mod userspace;
+54 -31
View File
@@ -2,20 +2,24 @@ use std::{
fs::{self, File},
io::BufWriter,
path::{Path, PathBuf},
process::Command,
};
use walkdir::WalkDir;
use crate::{
build::cargo::CargoBuilder,
build::{cargo::CargoBuilder, llvm},
check::AllOk,
env::{Arch, BuildEnv},
env::BuildEnv,
error::Error,
util,
};
use super::InitrdGenerated;
use super::{llvm::Llvm, InitrdGenerated};
pub struct Ygglibc {
lib_file: PathBuf,
include_paths: Vec<PathBuf>,
}
const PROGRAMS: &[(&str, &str)] = &[
// init
@@ -66,36 +70,15 @@ const PROGRAMS: &[(&str, &str)] = &[
("c-test", "c-test"),
];
fn build_test_c_program(env: &BuildEnv) -> Result<(), Error> {
fn build_test_c_program(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
log::info!("Building a test C program");
let mut command = Command::new("clang");
match env.arch {
Arch::aarch64 => todo!(),
Arch::i686 => todo!(),
Arch::x86_64 => {
command.args(["-target", "x86_64-unknown-none"]);
}
}
let ygglibc_target = format!("{:?}-unknown-none", env.arch);
let ygglibc_target_dir = env
.workspace_root
.join("userspace/lib/ygglibc/target")
.join(ygglibc_target)
.join(env.profile.dir());
let target_dir = &env.userspace_output_dir;
let mut command = llvm.c_clang(env);
command
.args(["-nostdlib", "-ffreestanding", "-static", "-Og", "-ggdb"])
.arg("-I")
.arg("userspace/lib/ygglibc/include")
.arg("-I")
.arg(ygglibc_target_dir.join("include"))
.args(["-static", "-Og", "-ggdb"])
.arg("-o")
.arg(target_dir.join("c-test"))
.arg(ygglibc_target_dir.join("libygglibc.a"))
.arg(env.workspace_root.join("test.c"))
.arg(ygglibc_target_dir.join("libygglibc.a"));
.arg(env.workspace_root.join("test.c"));
if !command.status()?.success() {
return Err(Error::ExternalCommandFailed);
@@ -104,12 +87,52 @@ fn build_test_c_program(env: &BuildEnv) -> Result<(), Error> {
Ok(())
}
fn install_ygglibc(env: &BuildEnv, ygglibc: Ygglibc) -> Result<(), Error> {
log::info!("Installing ygglibc into LLVM sysroot");
let dst_lib_dir = env.llvm_sysroot.join("lib");
let dst_include_dir = env.llvm_sysroot.join("usr/include");
fs::create_dir_all(&dst_lib_dir)?;
fs::create_dir_all(&dst_include_dir)?;
fs::copy(ygglibc.lib_file, dst_lib_dir.join("libygglibc.a"))?;
for path in ygglibc.include_paths {
util::copy_dir_recursive(&path, &dst_include_dir)?;
}
Ok(())
}
fn build_ygglibc(env: &BuildEnv) -> Result<Ygglibc, Error> {
let ygglibc_dir = env.workspace_root.join("userspace/lib/ygglibc");
let target_dir = ygglibc_dir.join(format!(
"target/{}-unknown-none/{}",
env.arch.name(),
env.profile.dir()
));
CargoBuilder::Ygglibc(env).build(&ygglibc_dir)?;
let lib_file = target_dir.join("libygglibc.a");
let generated_includes = target_dir.join("include");
let static_includes = ygglibc_dir.join("include");
Ok(Ygglibc {
lib_file,
include_paths: vec![generated_includes, static_includes],
})
}
fn build_userspace(env: &BuildEnv, _: AllOk) -> Result<(), Error> {
log::info!("Building userspace");
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace"))?;
CargoBuilder::Userspace(env).build(env.workspace_root.join("userspace/dynload-program"))?;
CargoBuilder::Ygglibc(env).build(env.workspace_root.join("userspace/lib/ygglibc"))?;
build_test_c_program(env)?;
let ygglibc = build_ygglibc(env)?;
let llvm = llvm::build_llvm(env)?;
install_ygglibc(env, ygglibc)?;
build_test_c_program(env, &llvm)?;
Ok(())
}
+12 -3
View File
@@ -28,7 +28,7 @@ pub enum Arch {
#[default]
aarch64,
x86_64,
i686
i686,
}
#[derive(Debug)]
@@ -45,6 +45,8 @@ pub struct BuildEnv {
pub kernel_output_dir: PathBuf,
pub userspace_output_dir: PathBuf,
pub kernel_symbol_file: PathBuf,
pub llvm_sysroot: PathBuf,
}
impl Default for ToolchainConfig {
@@ -73,6 +75,11 @@ impl BuildEnv {
let kernel_symbol_file = kernel_output_dir.join("symbols.dat");
let host = env!("TARGET");
let llvm_sysroot = workspace_root.join(format!(
"toolchain-c/sysroot/{}-unknown-yggdrasil",
arch.name()
));
Self {
config,
verbose,
@@ -86,6 +93,8 @@ impl BuildEnv {
kernel_symbol_file,
kernel_output_dir,
userspace_output_dir,
llvm_sysroot,
}
}
}
@@ -108,7 +117,7 @@ impl Arch {
match self {
Self::aarch64 => "aarch64-unknown-qemu",
Self::x86_64 => "x86_64-unknown-none",
Self::i686 => "i686-unknown-none"
Self::i686 => "i686-unknown-none",
}
}
@@ -116,7 +125,7 @@ impl Arch {
match self {
Self::aarch64 => "aarch64-unknown-yggdrasil",
Self::x86_64 => "x86_64-unknown-yggdrasil",
Self::i686 => "i686-unknown-yggdrasil"
Self::i686 => "i686-unknown-yggdrasil",
}
}