2024-11-13 15:58:29 +02:00
|
|
|
use std::{
|
|
|
|
fs,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
process::Command,
|
|
|
|
};
|
|
|
|
|
2024-11-13 16:31:26 +02:00
|
|
|
use crate::{
|
|
|
|
env::BuildEnv,
|
|
|
|
error::Error,
|
|
|
|
util::{self, git_clone},
|
|
|
|
};
|
2024-11-13 15:58:29 +02:00
|
|
|
|
|
|
|
use super::cargo::CargoBuilder;
|
|
|
|
|
2024-11-13 16:31:26 +02:00
|
|
|
pub const OPENLIBM_URL: &str = "https://git.alnyan.me/yggdrasil/openlibm.git";
|
|
|
|
|
2024-11-13 15:58:29 +02:00
|
|
|
pub struct Llvm {
|
|
|
|
root: PathBuf,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Ygglibc {
|
|
|
|
static_lib_file: PathBuf,
|
|
|
|
shared_lib_file: PathBuf,
|
|
|
|
crt0_file: PathBuf,
|
|
|
|
include_paths: Vec<PathBuf>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Openlibm {
|
|
|
|
shared_lib_file: PathBuf,
|
|
|
|
static_lib_file: PathBuf,
|
|
|
|
include_path: 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 clang(&self) -> PathBuf {
|
|
|
|
self.root.join("bin/clang")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_test_c_program(
|
|
|
|
env: &BuildEnv,
|
|
|
|
llvm: &Llvm,
|
|
|
|
install: &mut Vec<(PathBuf, PathBuf)>,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
log::info!("Building a test C program");
|
|
|
|
let target_dir = &env.userspace_output_dir;
|
|
|
|
|
|
|
|
let mut command = llvm.c_clang(env);
|
|
|
|
command
|
|
|
|
.args([
|
|
|
|
"-Bdynamic",
|
|
|
|
"-fpie",
|
|
|
|
"-O0",
|
|
|
|
"-ggdb",
|
|
|
|
"-lm",
|
|
|
|
"-fstack-protector-strong",
|
|
|
|
])
|
|
|
|
.arg("-o")
|
|
|
|
.arg(target_dir.join("c-test"))
|
|
|
|
.arg(env.workspace_root.join("test.c"));
|
|
|
|
|
|
|
|
if !command.status()?.success() {
|
|
|
|
return Err(Error::ExternalCommandFailed);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut command = llvm.c_clang(env);
|
|
|
|
command
|
|
|
|
.args(["-static", "-O0", "-ggdb", "-fstack-protector-strong", "-lm"])
|
|
|
|
.arg("-o")
|
|
|
|
.arg(target_dir.join("c-test-static"))
|
|
|
|
.arg(env.workspace_root.join("test.c"));
|
|
|
|
|
|
|
|
if !command.status()?.success() {
|
|
|
|
return Err(Error::ExternalCommandFailed);
|
|
|
|
}
|
|
|
|
|
|
|
|
install.push((target_dir.join("c-test"), "c-test".into()));
|
|
|
|
install.push((target_dir.join("c-test-static"), "c-test-static".into()));
|
|
|
|
|
|
|
|
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.static_lib_file, dst_lib_dir.join("libygglibc.a"))?;
|
|
|
|
fs::copy(&ygglibc.shared_lib_file, dst_lib_dir.join("libygglibc.so"))?;
|
|
|
|
fs::copy(&ygglibc.crt0_file, dst_lib_dir.join("crt0.o"))?;
|
|
|
|
|
|
|
|
for path in ygglibc.include_paths.iter() {
|
|
|
|
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 static_lib_file = target_dir.join("libygglibc.a");
|
|
|
|
let shared_lib_file = target_dir.join("libygglibc.so");
|
|
|
|
let crt0_file = target_dir.join("crt0.o");
|
|
|
|
let generated_includes = target_dir.join("include");
|
|
|
|
let static_includes = ygglibc_dir.join("include");
|
|
|
|
|
|
|
|
Ok(Ygglibc {
|
|
|
|
static_lib_file,
|
|
|
|
shared_lib_file,
|
|
|
|
crt0_file,
|
|
|
|
include_paths: vec![generated_includes, static_includes],
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO clone openlibm
|
|
|
|
fn build_openlibm(env: &BuildEnv, llvm: &Llvm) -> Result<Openlibm, Error> {
|
|
|
|
fn make(env: &BuildEnv, llvm: &Llvm, libm_path: &Path) -> Command {
|
|
|
|
let mut command = Command::new("make");
|
|
|
|
command.env("SYSROOT", &env.llvm_sysroot);
|
|
|
|
command.env("ARCH", env.arch.name());
|
|
|
|
command.env("TRIPLE", format!("{}-unknown-yggdrasil", env.arch.name()));
|
|
|
|
command.env("USEGCC", "0");
|
|
|
|
command.env("USECLANG", "1");
|
|
|
|
command.env("CC", llvm.clang());
|
|
|
|
command.current_dir(&libm_path);
|
|
|
|
command
|
|
|
|
}
|
|
|
|
|
2024-11-13 16:31:26 +02:00
|
|
|
let libm_path = env
|
|
|
|
.workspace_root
|
|
|
|
.join(format!("toolchain-c/libs/openlibm-{}", env.arch.name()));
|
|
|
|
|
|
|
|
git_clone(&libm_path, OPENLIBM_URL, "alnyan/yggdrasil")?;
|
2024-11-13 15:58:29 +02:00
|
|
|
|
2024-11-13 16:31:26 +02:00
|
|
|
log::info!("Building openlibm");
|
2024-11-13 15:58:29 +02:00
|
|
|
|
|
|
|
let mut command = make(env, llvm, &libm_path);
|
|
|
|
if !command.status()?.success() {
|
|
|
|
return Err(Error::ExternalCommandFailed);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(Openlibm {
|
|
|
|
shared_lib_file: libm_path.join("libopenlibm.so.4.0"),
|
|
|
|
static_lib_file: libm_path.join("libopenlibm.a"),
|
|
|
|
include_path: libm_path.join("include"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn install_openlibm(env: &BuildEnv, libm: &Openlibm) -> Result<(), Error> {
|
|
|
|
fs::copy(&libm.static_lib_file, env.llvm_sysroot.join("lib/libm.a"))?;
|
|
|
|
fs::copy(&libm.shared_lib_file, env.llvm_sysroot.join("lib/libm.so"))?;
|
|
|
|
|
|
|
|
util::copy_dir_recursive(&libm.include_path, env.llvm_sysroot.join("usr/include"))?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn build_llvm(env: &BuildEnv) -> Result<Llvm, Error> {
|
2024-11-13 16:31:26 +02:00
|
|
|
// Configuration:
|
|
|
|
/*
|
|
|
|
cmake -DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" -DLLVM_TARGETS_TO_BUILD=X86 -DCMAKE_SYSTEM_NAME=yggdrasil -DLLVM_USE_LINKER=lld -DBUILD_SHARED_LIBS=false -DLLVM_BUILD_TOOLS=false -DLLVM_CCACHE_BUILD=true -DCMAKE_BUILD_TYPE=Release -DCMAKE_HOST_TRIPLE=x86_64-unknown-linux-gnu -DUNIX=1 -GNinja -DCMAKE_INSTALL_PREFIX=/home/alnyan/build/ygg/toolchain-c/prefix/host ../llvm
|
|
|
|
|
|
|
|
Build:
|
|
|
|
cmake --build . -j 16
|
|
|
|
|
|
|
|
Install:
|
|
|
|
cmake --build . -t install
|
|
|
|
*/
|
|
|
|
|
2024-11-13 15:58:29 +02:00
|
|
|
// TODO actually build and install LLVM
|
|
|
|
Ok(Llvm {
|
|
|
|
root: env.workspace_root.join("toolchain-c/prefix/host"),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_c(env: &BuildEnv, install: &mut Vec<(PathBuf, PathBuf)>) -> Result<(), Error> {
|
|
|
|
let llvm = build_llvm(env)?;
|
|
|
|
let ygglibc = build_ygglibc(env)?;
|
|
|
|
install_ygglibc(env, &ygglibc)?;
|
|
|
|
let libm = build_openlibm(env, &llvm)?;
|
|
|
|
install_openlibm(env, &libm)?;
|
|
|
|
|
|
|
|
build_test_c_program(env, &llvm, install)?;
|
|
|
|
|
|
|
|
install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
|
|
|
|
install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|