ports: nicer build system for C/C++ ports

This commit is contained in:
Mark Poliakov 2025-03-06 20:41:16 +02:00
parent f30cafb3bd
commit 9f2ad4f2c9
47 changed files with 2734 additions and 601 deletions

View File

@ -22,7 +22,7 @@ use abi::{
use libk::{
module, random,
task::thread::Thread,
time::{monotonic_time, real_time},
time::{monotonic_time, real_time, set_real_seconds},
};
use libk_mm::phys;
@ -67,6 +67,25 @@ pub(crate) fn get_clock(ty: ClockType, value: &mut MaybeUninit<SystemTime>) -> R
Ok(())
}
pub(crate) fn set_clock(ty: ClockType, value: &SystemTime) -> Result<(), Error> {
match ty {
ClockType::RealTime => {
let time = chrono::DateTime::<chrono::Utc>::from_timestamp(
value.seconds() as i64,
value.subsec_nanos() as u32,
);
if let Some(time) = time {
log::info!("Set real time from userspace: {time}");
} else {
log::info!("Set real time from userspace: {value:?}");
};
set_real_seconds(value.seconds(), true);
Ok(())
}
ClockType::Monotonic => Err(Error::ReadOnly),
}
}
pub(crate) fn get_system_info(option: u32, buffer: &mut [u8]) -> Result<usize, Error> {
let option = SystemInfoVariant::try_from(option)?;
match option {

View File

@ -74,6 +74,7 @@ enum TraceLevel(u32) {
syscall get_random(buffer: &mut [u8]);
syscall get_clock(clock: ClockType, out: &mut MaybeUninit<SystemTime>) -> Result<()>;
syscall set_clock(clock: ClockType, value: &SystemTime) -> Result<()>;
syscall mount(opts: &MountOptions<'_>) -> Result<()>;
syscall unmount(opts: &UnmountOptions) -> Result<()>;
syscall load_module(path: &str) -> Result<()>;

View File

@ -13,6 +13,12 @@ pub fn get_clock(clock_type: ClockType) -> Result<SystemTime, Error> {
Ok(unsafe { time.assume_init() })
}
/// Updates the system clock value
#[inline]
pub fn set_clock(clock_type: ClockType, time: SystemTime) -> Result<(), Error> {
unsafe { crate::sys::set_clock(clock_type, &time) }
}
/// Returns the "real world" time.
#[inline]
pub fn get_real_time() -> Result<SystemTime, Error> {

5
ports/c-tests/port.toml Normal file
View File

@ -0,0 +1,5 @@
description = "Test C/C++ programs"
version = "0.0.1"
[dependencies]
runtime = ["meta-libc", "libc++"]

35
ports/compiler-rt/compile.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/sh
LLVM_SOURCE_DIR=$Y_WORKSPACE_ROOT/userspace/target/ports/meta-llvm/source/llvm-project-${Y_PORT_VERSION}.src
CMAKE_TOOLCHAIN=$Y_PORT_UTILS/toolchain-${Y_ARCH}.cmake
build_dir=$3
set -e
mkdir -p $build_dir
cd $build_dir
if [ ! -f build.ninja ]; then
cmake \
--toolchain=$CMAKE_TOOLCHAIN \
-DCOMPILER_RT_BUILD_BUILTINS=ON \
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
-DCOMPILER_RT_BUILD_PROFILE=OFF \
-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-DCOMPILER_RT_BUILD_XRAY=OFF \
-DCOMPILER_RT_BUILD_STANDALONE_LIBATOMIC=ON \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
-DCOMPILER_RT_BAREMETAL_BUILD=ON \
-DCOMPILER_RT_BUILTINS_ENABLE_PIC=ON \
-DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=OFF \
-DDEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY=ON \
-DCMAKE_EXE_LINKER_FLAGS=-nostdlib \
-DCMAKE_SYSROOT=${Y_SYSROOT} \
-DCMAKE_INSTALL_PREFIX=${Y_SYSROOT} \
-GNinja \
$LLVM_SOURCE_DIR/compiler-rt
fi
cmake --build . -j

6
ports/compiler-rt/install.sh Executable file
View File

@ -0,0 +1,6 @@
#!/bin/sh
build_dir=$3
cd $build_dir
cmake --build . -t install -j >/dev/null

View File

@ -0,0 +1,5 @@
description = "LLVM's compiler-rt"
version = "19.1.3"
[dependencies]
runtime = ["meta-libc"]

41
ports/libc++/compile.sh Executable file
View File

@ -0,0 +1,41 @@
#!/bin/sh
LLVM_SOURCE_DIR=$Y_WORKSPACE_ROOT/userspace/target/ports/meta-llvm/source/llvm-project-${Y_PORT_VERSION}.src
CMAKE_TOOLCHAIN=$Y_PORT_UTILS/toolchain-${Y_ARCH}.cmake
set -e
build_dir=$3
mkdir -p $build_dir
cd $build_dir
if [ ! -f build.ninja ]; then
cmake \
--toolchain=$CMAKE_TOOLCHAIN \
-GNinja \
-DCMAKE_BUILD_TYPE=RelWithDebInfo \
-DLLVM_ENABLE_RUNTIMES="libcxxabi;libcxx" \
-DLIBCXXABI_ENABLE_STATIC=ON \
-DLIBCXXABI_ENABLE_SHARED=OFF \
-DLIBCXXABI_USE_COMPILER_RT=ON \
-DLIBCXXABI_ENABLE_THREADS=ON \
-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF \
-DLIBCXXABI_USE_LLVM_UNWINDER=OFF \
-DLIBCXX_CXX_ABI=libcxxabi \
-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON \
-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=ON \
-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON \
-DLIBCXX_ENABLE_FILESYSTEM=ON \
-DLIBCXX_ENABLE_THREADS=ON \
-DLIBCXX_ENABLE_EXCEPTIONS=OFF \
-DLIBCXX_ENABLE_SHARED=ON \
-DLIBCXX_ENABLE_STATIC=ON \
-DLIBCXX_INCLUDE_BENCHMARKS=OFF \
-DCMAKE_EXE_LINKER_FLAGS=-nostdlib \
-DCMAKE_SYSROOT=$Y_SYSROOT \
-DCMAKE_INSTALL_PREFIX=$Y_SYSROOT \
-DLLVM_DEFAULT_TARGET_TRIPLE=$Y_TRIPLE \
$LLVM_SOURCE_DIR/runtimes
fi
cmake --build . -j

8
ports/libc++/install.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
set -e
build_dir=$3
cd $build_dir
cmake --build . -t install -j >/dev/null

5
ports/libc++/port.toml Normal file
View File

@ -0,0 +1,5 @@
description = "LLVM's libc++/libc++abi"
version = "19.1.3"
[dependencies]
runtime = ["meta-llvm", "compiler-rt", "meta-libc", "openlibm"]

55
ports/llvm/compile.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/sh
LLVM_SOURCE_DIR=$Y_WORKSPACE_ROOT/userspace/target/ports/meta-llvm/source/llvm-project-${Y_PORT_VERSION}.src
CMAKE_TOOLCHAIN=$Y_PORT_UTILS/toolchain-${Y_ARCH}.cmake
set -e
build_dir=$3
case $Y_ARCH in
x86_64)
LLVM_TARGET_NAME=X86
;;
aarch64)
LLVM_TARGET_NAME=AArch64
;;
riscv64)
LLVM_TARGET_NAME=RISCV
;;
**)
echo "Unsupported LLVM Yggdrasil target: $Y_ARCH" >&2
exit 1
;;
esac
mkdir -p $build_dir
cd $build_dir
if [ ! -f build.ninja ]; then
cmake \
--toolchain=$CMAKE_TOOLCHAIN \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_SYSROOT=$Y_SYSROOT \
-DCMAKE_INSTALL_PREFIX=$Y_SYSROOT \
-DLLVM_HOST_TRIPLE=$Y_TRIPLE \
-DLLVM_TARGETS_TO_BUILD=$LLVM_TARGET_NAME \
-DLLVM_ENABLE_PROJECTS="lld;clang" \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_TOOLS=ON \
-DLLVM_ENABLE_THREADS=OFF \
-DLLVM_ENABLE_RTTI=OFF \
-DLLVM_ENABLE_ASSERTIONS=ON \
-DLLVM_ENABLE_LIBXML2=OFF \
-DLLVM_CCACHE_BUILD=ON \
-DLLVM_BUILD_TESTS=OFF \
-DLLVM_BUILD_EXAMPLES=OFF \
-DLLVM_BUILD_BENCHMARKS=OFF \
-DLLVM_BUILD_DOCS=OFF \
-DLLVM_USE_LINKER=lld \
-GNinja \
$LLVM_SOURCE_DIR/llvm
fi
cmake --build . -j

7
ports/llvm/install.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/sh
set -e
build_dir=$3
cd $build_dir
cmake --build . -t install -j >/dev/null

5
ports/llvm/port.toml Normal file
View File

@ -0,0 +1,5 @@
description = "clang + LLVM tools"
version = "19.1.3"
[dependencies]
runtime = ["meta-llvm", "compiler-rt", "meta-libc", "openlibm", "libc++"]

36
ports/meta-llvm/compile.sh Executable file
View File

@ -0,0 +1,36 @@
#!/bin/sh
set -e
source_dir=$2
src=$source_dir/llvm-project-${Y_PORT_VERSION}.src
build_dir=${Y_WORKSPACE_ROOT}/userspace/target/ports/meta-llvm
mkdir -p $build_dir
cd $build_dir
# Configure
if command -v ccache >/dev/null; then
EXTRA_OPTS="-DLLVM_CCACHE_BUILD=true"
fi
if [ ! -f build.ninja ]; then
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=/usr/bin/clang \
-DCMAKE_CXX_COMPILER=/usr/bin/clang++ \
-DBUILD_SHARED_LIBS=false \
-DLLVM_ENABLE_PROJECTS="clang;lld;compiler-rt" \
-DLLVM_INCLUDE_BENCHMARKS=false \
-DLLVM_INCLUDE_TESTS=false \
-DLLVM_USE_LINKER=lld \
-DLLVM_BUILD_TOOLS=true \
-DLLVM_TARGETS_TO_BUILD="X86;AArch64;RISCV" \
-DCMAKE_INSTALL_PREFIX=$Y_HOST_PREFIX \
$EXTRA_OPTS \
-GNinja \
$src/llvm
fi
cmake --build . -j

31
ports/meta-llvm/fetch.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
. $Y_PORT_UTILS/sig.sh
set -e
SRC_FILENAME="llvm-project-${Y_PORT_VERSION}.src.tar.xz"
SRC_SHA256="324d483ff0b714c8ce7819a1b679dd9e4706cf91c6caf7336dc4ac0c1d3bf636"
RELEASE_BASE="https://github.com/llvm/llvm-project/releases/download/llvmorg-${Y_PORT_VERSION}"
RELEASE_URL="$RELEASE_BASE/$SRC_FILENAME"
source_dir=$2
build_dir=$3
if [ ! -f $source_dir/.source-ready ]; then
mkdir -p $source_dir
cd $source_dir
curl -LO $RELEASE_URL
verify_sha256 $SRC_SHA256 $SRC_FILENAME
tar xf $SRC_FILENAME
cd llvm-project-${Y_PORT_VERSION}.src
for patch in $1/patches/*.patch; do
echo Apply $patch
patch -p1 <$patch
done
touch $source_dir/.source-ready
fi

10
ports/meta-llvm/install.sh Executable file
View File

@ -0,0 +1,10 @@
#!/bin/sh
set -e
source_dir=$2
build_dir=${Y_WORKSPACE_ROOT}/userspace/target/ports/meta-llvm
cd $build_dir
cmake --build . -t install -j >/dev/null

View File

@ -0,0 +1,622 @@
From 0b21467e6102cbad5b7652c06abac42be4cf0a04 Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Mon, 11 Nov 2024 23:18:27 +0200
Subject: [PATCH 1/2] alnyan/yggdrasil: Yggdrasil target support
---
clang/lib/Basic/Targets.cpp | 6 +
clang/lib/Basic/Targets/OSTargets.h | 19 ++
clang/lib/Driver/CMakeLists.txt | 1 +
clang/lib/Driver/Driver.cpp | 4 +
clang/lib/Driver/ToolChains/Yggdrasil.cpp | 255 +++++++++++++++++++++
clang/lib/Driver/ToolChains/Yggdrasil.h | 98 ++++++++
compiler-rt/lib/builtins/cpu_model/x86.c | 3 +
libcxx/include/__locale | 4 +-
libcxx/include/ios | 4 +
libcxx/src/atomic.cpp | 12 +
libcxx/src/locale.cpp | 2 +-
llvm/cmake/modules/HandleLLVMOptions.cmake | 2 +-
llvm/include/llvm/TargetParser/Triple.h | 1 +
llvm/lib/TargetParser/Triple.cpp | 2 +
14 files changed, 409 insertions(+), 4 deletions(-)
create mode 100644 clang/lib/Driver/ToolChains/Yggdrasil.cpp
create mode 100644 clang/lib/Driver/ToolChains/Yggdrasil.h
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index 29133f9ee8fc..b116c06e86bc 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -142,6 +142,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
return std::make_unique<DarwinAArch64TargetInfo>(Triple, Opts);
switch (os) {
+ case llvm::Triple::Yggdrasil:
+ return std::make_unique<YggdrasilTargetInfo<AArch64leTargetInfo>>(Triple, Opts);
case llvm::Triple::FreeBSD:
return std::make_unique<FreeBSDTargetInfo<AArch64leTargetInfo>>(Triple,
Opts);
@@ -578,6 +580,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
}
case llvm::Triple::Haiku:
return std::make_unique<HaikuX86_32TargetInfo>(Triple, Opts);
+ case llvm::Triple::Yggdrasil:
+ return std::make_unique<YggdrasilTargetInfo<X86_32TargetInfo>>(Triple, Opts);
case llvm::Triple::RTEMS:
return std::make_unique<RTEMSX86_32TargetInfo>(Triple, Opts);
case llvm::Triple::NaCl:
@@ -638,6 +642,8 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
}
case llvm::Triple::Haiku:
return std::make_unique<HaikuTargetInfo<X86_64TargetInfo>>(Triple, Opts);
+ case llvm::Triple::Yggdrasil:
+ return std::make_unique<YggdrasilTargetInfo<X86_64TargetInfo>>(Triple, Opts);
case llvm::Triple::NaCl:
return std::make_unique<NaClTargetInfo<X86_64TargetInfo>>(Triple, Opts);
case llvm::Triple::PS4:
diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h
index 357c1965057c..339eb218f830 100644
--- a/clang/lib/Basic/Targets/OSTargets.h
+++ b/clang/lib/Basic/Targets/OSTargets.h
@@ -878,6 +878,25 @@ public:
}
};
+// Yggdrasil Target
+template <typename Target>
+class LLVM_LIBRARY_VISIBILITY YggdrasilTargetInfo : public OSTargetInfo<Target> {
+protected:
+ void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
+ MacroBuilder &Builder) const override {
+ Builder.defineMacro("__yggdrasil__");
+ Builder.defineMacro("__FLOAT128__");
+ this->PlatformName = "yggdrasil";
+ }
+public:
+ YggdrasilTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
+ : OSTargetInfo<Target>(Triple, Opts) {
+ this->WIntType = TargetInfo::UnsignedInt;
+ this->MCountName = "__mcount";
+ this->HasFloat128 = true;
+ }
+};
+
// WebAssembly target
template <typename Target>
class LLVM_LIBRARY_VISIBILITY WebAssemblyOSTargetInfo
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 32a4378ab499..42dcc9037620 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -85,6 +85,7 @@ add_clang_library(clangDriver
ToolChains/PPCFreeBSD.cpp
ToolChains/InterfaceStubs.cpp
ToolChains/ZOS.cpp
+ ToolChains/Yggdrasil.cpp
Types.cpp
XRayArgs.cpp
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ecae475f75da..18604cc8ed75 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -21,6 +21,7 @@
#include "ToolChains/DragonFly.h"
#include "ToolChains/FreeBSD.h"
#include "ToolChains/Fuchsia.h"
+#include "ToolChains/Yggdrasil.h"
#include "ToolChains/Gnu.h"
#include "ToolChains/HIPAMD.h"
#include "ToolChains/HIPSPV.h"
@@ -6351,6 +6352,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Haiku:
TC = std::make_unique<toolchains::Haiku>(*this, Target, Args);
break;
+ case llvm::Triple::Yggdrasil:
+ TC = std::make_unique<toolchains::Yggdrasil>(*this, Target, Args);
+ break;
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
diff --git a/clang/lib/Driver/ToolChains/Yggdrasil.cpp b/clang/lib/Driver/ToolChains/Yggdrasil.cpp
new file mode 100644
index 000000000000..d45945abbd99
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Yggdrasil.cpp
@@ -0,0 +1,255 @@
+#include "Yggdrasil.h"
+#include "CommonArgs.h"
+#include "clang/Config/config.h"
+#include "clang/Driver/Compilation.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/MultilibBuilder.h"
+#include "clang/Driver/Options.h"
+#include "clang/Driver/SanitizerArgs.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/ProfileData/InstrProf.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/VirtualFileSystem.h"
+
+#include <iostream>
+
+using namespace clang::driver;
+using namespace clang::driver::toolchains;
+using namespace clang::driver::tools;
+using namespace clang;
+using namespace llvm::opt;
+
+using tools::addMultilibFlag;
+
+
+void yggdrasil::Linker::ConstructJob(
+ Compilation &C,
+ const JobAction &JA,
+ const InputInfo &Output,
+ const InputInfoList &Inputs,
+ const ArgList &Args,
+ const char *LinkingOutput
+) const {
+ const toolchains::Yggdrasil &ToolChain = static_cast<const toolchains::Yggdrasil &>(getToolChain());
+ const Driver &D = ToolChain.getDriver();
+
+ ArgStringList CmdArgs;
+
+ // Silence warning for "clang -g foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_g_Group);
+ // and "clang -emit-llvm foo.o -o foo"
+ Args.ClaimAllArgs(options::OPT_emit_llvm);
+ // and for "clang -w foo.o -o foo". Other warning options are already
+ // handled somewhere else.
+ Args.ClaimAllArgs(options::OPT_w);
+
+ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
+
+ CmdArgs.push_back("-z");
+ CmdArgs.push_back("max-page-size=4096");
+
+ CmdArgs.push_back("--eh-frame-hdr");
+
+ if (!Args.hasArg(options::OPT_shared) &&
+ !Args.hasArg(options::OPT_static) &&
+ !Args.hasArg(options::OPT_r)) {
+ CmdArgs.push_back("-pie");
+ }
+
+ if (Args.hasArg(options::OPT_r)) {
+ CmdArgs.push_back("-r");
+ } else {
+ CmdArgs.push_back("--build-id");
+ CmdArgs.push_back("--hash-style=gnu");
+ }
+
+ if (!D.SysRoot.empty()) {
+ CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
+ }
+
+ if (Args.hasArg(options::OPT_s)) {
+ CmdArgs.push_back("-s");
+ }
+
+ if (Args.hasArg(options::OPT_static)) {
+ CmdArgs.push_back("-Bstatic");
+ } else {
+ if (Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back("-shared");
+ }
+
+ CmdArgs.push_back("--dynamic-linker=/libexec/dyn-loader");
+ }
+
+ CmdArgs.push_back("-o");
+ CmdArgs.push_back(Output.getFilename());
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, options::OPT_r)) {
+ if (!Args.hasArg(options::OPT_shared)) {
+ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o")));
+ }
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_L);
+ Args.AddAllArgs(CmdArgs, options::OPT_u);
+
+ ToolChain.AddFilePathLibArgs(Args, CmdArgs);
+
+ // if (D.isUsingLTO()) {
+ // assert(!Inputs.empty() && "Must have at least one input.");
+ // addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
+ // D.getLTOMode() == LTOK_Thin);
+ // }
+
+ if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
+ AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
+
+ if (!Args.hasArg(options::OPT_nolibc)) {
+ CmdArgs.push_back("-lygglibc");
+ }
+
+ if (D.CCCIsCXX()) {
+ if (ToolChain.ShouldLinkCXXStdlib(Args)) {
+ ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
+ // CmdArgs.push_back("-lm");
+ // CmdArgs.push_back("-lpthread");
+ }
+ }
+ }
+
+ AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
+
+ C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
+ Exec, CmdArgs, Inputs, Output));
+}
+
+/// Yggdrasil - Yggdrasil OS tool chain which can call as(1) and ld(1) directly.
+
+Yggdrasil::Yggdrasil(
+ const Driver &D,
+ const llvm::Triple &Triple,
+ const ArgList &Args
+): ToolChain(D, Triple, Args) {
+ getProgramPaths().push_back(getDriver().Dir);
+
+ if (!D.SysRoot.empty()) {
+ SmallString<128> P(D.SysRoot);
+ llvm::sys::path::append(P, "lib");
+ getFilePaths().push_back(std::string(P));
+ }
+}
+
+std::string Yggdrasil::ComputeEffectiveClangTriple(const ArgList &Args,
+ types::ID InputType) const {
+ llvm::Triple Triple(ComputeLLVMTriple(Args, InputType));
+ return Triple.str();
+}
+
+Tool *Yggdrasil::buildLinker() const {
+ return new tools::yggdrasil::Linker(*this);
+}
+
+ToolChain::RuntimeLibType Yggdrasil::GetRuntimeLibType(const ArgList &Args) const {
+ return ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::RuntimeLibType Yggdrasil::GetDefaultRuntimeLibType() const {
+ return ToolChain::RLT_CompilerRT;
+}
+
+ToolChain::CXXStdlibType Yggdrasil::GetDefaultCXXStdlibType() const {
+ return ToolChain::CST_Libcxx;
+}
+
+ToolChain::UnwindLibType Yggdrasil::GetUnwindLibType(const ArgList &Args) const {
+ return ToolChain::UNW_None;
+}
+
+ToolChain::CXXStdlibType Yggdrasil::GetCXXStdlibType(const ArgList &Args) const {
+ return ToolChain::CST_Libcxx;
+}
+
+ToolChain::UnwindTableLevel Yggdrasil::getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const {
+ return ToolChain::UnwindTableLevel::None;
+}
+
+void Yggdrasil::addClangTargetOptions(const ArgList &DriverArgs,
+ ArgStringList &CC1Args,
+ Action::OffloadKind) const {
+ if (getArch() == llvm::Triple::x86) {
+ CC1Args.push_back("-mstack-alignment=16");
+ }
+ // if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
+ // options::OPT_fno_use_init_array, true))
+ // CC1Args.push_back("-fno-use-init-array");
+
+ // CC1Args.push_back("-mlong-double-64"); // for newlib + libc++ compat
+
+ // CC1Args.push_back("-ffunction-sections"); // better to optimize binary sizes
+ // CC1Args.push_back("-fdata-sections");
+}
+
+void Yggdrasil::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ const Driver &D = getDriver();
+
+ if (DriverArgs.hasArg(options::OPT_nostdinc)) {
+ return;
+ }
+
+ if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
+ SmallString<128> P(D.ResourceDir);
+ llvm::sys::path::append(P, "include");
+ addSystemInclude(DriverArgs, CC1Args, P);
+ }
+
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc)) {
+ return;
+ }
+
+ if (!D.SysRoot.empty()) {
+ SmallString<128> P(D.SysRoot);
+ llvm::sys::path::append(P, "include");
+ addExternCSystemInclude(DriverArgs, CC1Args, P.str());
+ }
+}
+
+void Yggdrasil::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+ ArgStringList &CC1Args) const {
+ if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+ DriverArgs.hasArg(options::OPT_nostdincxx)) {
+ return;
+ }
+
+ switch (GetCXXStdlibType(DriverArgs)) {
+ case ToolChain::CST_Libcxx: {
+ SmallString<128> P(getDriver().SysRoot);
+ llvm::sys::path::append(P, "include", "c++", "v1");
+ addSystemInclude(DriverArgs, CC1Args, P.str());
+ break;
+ }
+
+ default:
+ llvm_unreachable("invalid stdlib name");
+ }
+}
+
+void Yggdrasil::AddCXXStdlibLibArgs(const ArgList &Args,
+ ArgStringList &CmdArgs) const {
+ switch (GetCXXStdlibType(Args)) {
+ case ToolChain::CST_Libcxx:
+ CmdArgs.push_back("-lc++");
+ break;
+
+ case ToolChain::CST_Libstdcxx:
+ llvm_unreachable("invalid stdlib name");
+ }
+}
+
+std::string Yggdrasil::getCompilerRTPath() const {
+ SmallString<128> Path(getDriver().SysRoot);
+ llvm::sys::path::append(Path, "lib", getOSLibName());
+ return std::string(Path.str());
+}
diff --git a/clang/lib/Driver/ToolChains/Yggdrasil.h b/clang/lib/Driver/ToolChains/Yggdrasil.h
new file mode 100644
index 000000000000..985bbc06ce27
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/Yggdrasil.h
@@ -0,0 +1,98 @@
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_YGGDRASIL_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_YGGDRASIL_H
+
+#include "Gnu.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
+#include "llvm/MC/MCTargetOptions.h"
+
+namespace clang {
+namespace driver {
+namespace tools {
+namespace yggdrasil {
+
+class LLVM_LIBRARY_VISIBILITY Linker final : public Tool {
+public:
+ Linker(const ToolChain &TC) : Tool("yggdrasil::Linker", "ld.lld", TC) {}
+
+ bool hasIntegratedCPP() const override { return false; }
+ bool isLinkJob() const override { return true; }
+
+ void ConstructJob(Compilation &C, const JobAction &JA,
+ const InputInfo &Output, const InputInfoList &Inputs,
+ const llvm::opt::ArgList &TCArgs,
+ const char *LinkingOutput) const override;
+};
+
+} // end yggdrasil
+} // end tools
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY Yggdrasil : public ToolChain {
+public:
+ Yggdrasil(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args);
+
+ bool HasNativeLLVMSupport() const override { return true; }
+ bool IsIntegratedAssemblerDefault() const override { return true; }
+ bool IsMathErrnoDefault() const override { return false; }
+ bool useRelaxRelocations() const override { return true; }
+ UnwindTableLevel getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override;
+ RuntimeLibType GetDefaultRuntimeLibType() const override;
+ CXXStdlibType GetDefaultCXXStdlibType() const override;
+ bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const {
+ return true;
+ }
+ llvm::ExceptionHandling GetExceptionModel(const llvm::opt::ArgList &Args) const override {
+ return llvm::ExceptionHandling::DwarfCFI;
+ }
+ bool isPICDefault() const override { return false; }
+ bool isPIEDefault(const llvm::opt::ArgList &Args) const override { return false; }
+ bool isPICDefaultForced() const override { return false; }
+
+ llvm::DebuggerKind getDefaultDebuggerTuning() const override {
+ return llvm::DebuggerKind::GDB;
+ }
+
+ LangOptions::StackProtectorMode GetDefaultStackProtectorLevel(bool KernelOrKext) const override {
+ return LangOptions::SSPStrong;
+ }
+ std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+ types::ID InputType) const override;
+
+ RuntimeLibType
+ GetRuntimeLibType(const llvm::opt::ArgList &Args) const override;
+ UnwindLibType
+ GetUnwindLibType(const llvm::opt::ArgList &Args) const override;
+ CXXStdlibType
+ GetCXXStdlibType(const llvm::opt::ArgList &Args) const override;
+
+ void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args,
+ Action::OffloadKind DeviceOffloadKind) const override;
+ void
+ AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void
+ AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
+ llvm::opt::ArgStringList &CC1Args) const override;
+ void AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
+ llvm::opt::ArgStringList &CmdArgs) const override;
+
+ const char *getDefaultLinker() const override {
+ return "ld.lld";
+ }
+
+ virtual std::string getCompilerRTPath() const override;
+
+protected:
+ Tool *buildLinker() const override;
+};
+
+} // end toolchains
+
+} // end driver
+} // end clang
+
+#endif
diff --git a/compiler-rt/lib/builtins/cpu_model/x86.c b/compiler-rt/lib/builtins/cpu_model/x86.c
index b1c4abd9d11d..05939e079f66 100644
--- a/compiler-rt/lib/builtins/cpu_model/x86.c
+++ b/compiler-rt/lib/builtins/cpu_model/x86.c
@@ -1157,8 +1157,11 @@ int CONSTRUCTOR_ATTRIBUTE __cpu_indicator_init(void) {
unsigned Vendor;
unsigned Model, Family;
unsigned Features[(CPU_FEATURE_MAX + 31) / 32] = {0};
+// TODO static_assert is not defined
+#if !defined(__yggdrasil__)
static_assert(sizeof(Features) / sizeof(Features[0]) == 4, "");
static_assert(sizeof(__cpu_features2) / sizeof(__cpu_features2[0]) == 3, "");
+#endif
// This function needs to run just once.
if (__cpu_model.__cpu_vendor)
diff --git a/libcxx/include/__locale b/libcxx/include/__locale
index 4b382764b446..dd047eaceae0 100644
--- a/libcxx/include/__locale
+++ b/libcxx/include/__locale
@@ -314,7 +314,7 @@ public:
# else
static const mask __regex_word = 1 << 10;
# endif // defined(__BIONIC__)
-#elif defined(__GLIBC__)
+#elif defined(__GLIBC__) || defined(__yggdrasil__)
typedef unsigned short mask;
static const mask space = _ISspace;
static const mask print = _ISprint;
@@ -326,7 +326,7 @@ public:
static const mask punct = _ISpunct;
static const mask xdigit = _ISxdigit;
static const mask blank = _ISblank;
-# if defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN)
+# if !defined(__yggdrasil__) && (defined(__mips__) || (BYTE_ORDER == BIG_ENDIAN))
static const mask __regex_word = static_cast<mask>(_ISbit(15));
# else
static const mask __regex_word = 0x80;
diff --git a/libcxx/include/ios b/libcxx/include/ios
index d8a3643c7ad5..b13c474a72af 100644
--- a/libcxx/include/ios
+++ b/libcxx/include/ios
@@ -244,7 +244,11 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
+#if defined(__yggdrasil__)
+typedef ssize_t streamsize;
+#else
typedef ptrdiff_t streamsize;
+#endif
class _LIBCPP_EXPORTED_FROM_ABI ios_base {
public:
diff --git a/libcxx/src/atomic.cpp b/libcxx/src/atomic.cpp
index ae062155661e..3906f8d1f589 100644
--- a/libcxx/src/atomic.cpp
+++ b/libcxx/src/atomic.cpp
@@ -101,6 +101,18 @@ static void __libcpp_platform_wake_by_address(__cxx_atomic_contention_t const vo
_umtx_op(const_cast<__cxx_atomic_contention_t*>(__ptr), UMTX_OP_WAKE, __notify_one ? 1 : INT_MAX, NULL, NULL);
}
+#elif defined(__yggdrasil__)
+
+static void __libcpp_platform_wait_on_address(
+ __cxx_atomic_contention_t const volatile* __ptr,
+ __cxx_contention_t __val
+) {}
+
+static void __libcpp_platform_wake_by_address(
+ __cxx_atomic_contention_t const volatile*,
+ bool
+) {}
+
#else // <- Add other operating systems here
// Baseline is just a timed backoff
diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp
index 4efdc63c0966..86a08de694de 100644
--- a/libcxx/src/locale.cpp
+++ b/libcxx/src/locale.cpp
@@ -985,7 +985,7 @@ const ctype<char>::mask* ctype<char>::classic_table() noexcept {
return _LIBCPP_GET_C_LOCALE->__ctype_b;
# elif defined(_LIBCPP_MSVCRT) || defined(__MINGW32__)
return __pctype_func();
-# elif defined(__EMSCRIPTEN__)
+# elif defined(__EMSCRIPTEN__) || defined(__yggdrasil__)
return *__ctype_b_loc();
# elif defined(_NEWLIB_VERSION)
// Newlib has a 257-entry table in ctype_.c, where (char)0 starts at [1].
diff --git a/llvm/cmake/modules/HandleLLVMOptions.cmake b/llvm/cmake/modules/HandleLLVMOptions.cmake
index 5ca580fbb59c..1fed40a04091 100644
--- a/llvm/cmake/modules/HandleLLVMOptions.cmake
+++ b/llvm/cmake/modules/HandleLLVMOptions.cmake
@@ -217,7 +217,7 @@ elseif(FUCHSIA OR UNIX)
else()
set(LLVM_HAVE_LINK_VERSION_SCRIPT 1)
endif()
-elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic")
+elseif(CMAKE_SYSTEM_NAME STREQUAL "Generic" OR CMAKE_SYSTEM_NAME STREQUAL "yggdrasil")
set(LLVM_ON_WIN32 0)
set(LLVM_ON_UNIX 0)
set(LLVM_HAVE_LINK_VERSION_SCRIPT 0)
diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h
index d2126a03db90..63fb1124ff43 100644
--- a/llvm/include/llvm/TargetParser/Triple.h
+++ b/llvm/include/llvm/TargetParser/Triple.h
@@ -238,6 +238,7 @@ public:
ShaderModel, // DirectX ShaderModel
LiteOS,
Serenity,
+ Yggdrasil,
Vulkan, // Vulkan SPIR-V
LastOSType = Vulkan
};
diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp
index 21d6c74b5956..be4f1180f750 100644
--- a/llvm/lib/TargetParser/Triple.cpp
+++ b/llvm/lib/TargetParser/Triple.cpp
@@ -292,6 +292,7 @@ StringRef Triple::getOSTypeName(OSType Kind) {
case RTEMS: return "rtems";
case Solaris: return "solaris";
case Serenity: return "serenity";
+ case Yggdrasil: return "yggdrasil";
case TvOS: return "tvos";
case UEFI: return "uefi";
case WASI: return "wasi";
@@ -686,6 +687,7 @@ static Triple::OSType parseOS(StringRef OSName) {
.StartsWith("shadermodel", Triple::ShaderModel)
.StartsWith("liteos", Triple::LiteOS)
.StartsWith("serenity", Triple::Serenity)
+ .StartsWith("yggdrasil", Triple::Yggdrasil)
.StartsWith("vulkan", Triple::Vulkan)
.Default(Triple::UnknownOS);
}
--
2.48.1

View File

@ -0,0 +1,739 @@
From 05e94c67399dfb7924aa42f1f3f9a820ac1b16e9 Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Mon, 16 Dec 2024 15:39:04 +0200
Subject: [PATCH 2/2] alnyan/yggdrasil: Yggdrasil host support
---
clang/lib/Basic/Targets.cpp | 3 +++
clang/lib/Driver/Driver.cpp | 7 +++++++
clang/lib/Driver/ToolChains/Yggdrasil.cpp | 9 +++++++--
libcxx/include/__config | 3 ++-
libcxx/src/chrono.cpp | 2 +-
lld/Common/Filesystem.cpp | 2 +-
llvm/CMakeLists.txt | 2 +-
llvm/include/llvm/ADT/GenericCycleImpl.h | 4 ++++
llvm/include/llvm/Support/FileSystem.h | 12 ++++++------
llvm/include/llvm/Support/Program.h | 2 +-
llvm/include/llvm/Support/thread.h | 4 ++--
llvm/lib/IR/Constants.cpp | 6 +++---
llvm/lib/IR/DebugInfoMetadata.cpp | 4 ++--
llvm/lib/IR/Value.cpp | 6 +++---
llvm/lib/Support/CMakeLists.txt | 4 ++++
llvm/lib/Support/COM.cpp | 2 +-
llvm/lib/Support/Chrono.cpp | 4 ++--
llvm/lib/Support/CrashRecoveryContext.cpp | 16 ++++++++++++++--
llvm/lib/Support/Memory.cpp | 2 +-
llvm/lib/Support/Path.cpp | 2 +-
llvm/lib/Support/Process.cpp | 2 +-
llvm/lib/Support/Program.cpp | 2 +-
llvm/lib/Support/Signals.cpp | 2 +-
llvm/lib/Support/ThreadPool.cpp | 2 ++
llvm/lib/Support/Threading.cpp | 2 +-
llvm/lib/Support/Unix/Path.inc | 5 ++++-
llvm/lib/Support/Unix/Process.inc | 4 +++-
llvm/lib/Support/Unix/Program.inc | 4 ++--
llvm/lib/Support/Unix/Signals.inc | 9 ++++++++-
llvm/lib/Support/VirtualFileSystem.cpp | 4 ++++
llvm/lib/Support/Watchdog.cpp | 2 +-
llvm/lib/Support/raw_socket_stream.cpp | 4 ++++
llvm/lib/Support/regengine.inc | 4 ++--
llvm/lib/TargetParser/Host.cpp | 2 +-
34 files changed, 101 insertions(+), 43 deletions(-)
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp
index b116c06e86bc..adb84d46305e 100644
--- a/clang/lib/Basic/Targets.cpp
+++ b/clang/lib/Basic/Targets.cpp
@@ -441,6 +441,9 @@ std::unique_ptr<TargetInfo> AllocateTarget(const llvm::Triple &Triple,
case llvm::Triple::riscv64:
switch (os) {
+ case llvm::Triple::Yggdrasil:
+ return std::make_unique<YggdrasilTargetInfo<RISCV64TargetInfo>>(Triple,
+ Opts);
case llvm::Triple::FreeBSD:
return std::make_unique<FreeBSDTargetInfo<RISCV64TargetInfo>>(Triple,
Opts);
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 18604cc8ed75..0e68650219ab 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -1966,10 +1966,17 @@ int Driver::ExecuteCompilation(
// llvm/lib/Support/*/Signals.inc will exit with a special return code
// for SIGPIPE. Do not print diagnostics for this case.
+#if defined(__yggdrasil__)
+ if (CommandRes == -1) {
+ Res = CommandRes;
+ continue;
+ }
+#else
if (CommandRes == EX_IOERR) {
Res = CommandRes;
continue;
}
+#endif
// Print extra information about abnormal failures, if possible.
//
diff --git a/clang/lib/Driver/ToolChains/Yggdrasil.cpp b/clang/lib/Driver/ToolChains/Yggdrasil.cpp
index d45945abbd99..0589a026a79d 100644
--- a/clang/lib/Driver/ToolChains/Yggdrasil.cpp
+++ b/clang/lib/Driver/ToolChains/Yggdrasil.cpp
@@ -113,7 +113,7 @@ void yggdrasil::Linker::ConstructJob(
if (D.CCCIsCXX()) {
if (ToolChain.ShouldLinkCXXStdlib(Args)) {
ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs);
- // CmdArgs.push_back("-lm");
+ CmdArgs.push_back("-lm");
// CmdArgs.push_back("-lpthread");
}
}
@@ -139,6 +139,9 @@ Yggdrasil::Yggdrasil(
llvm::sys::path::append(P, "lib");
getFilePaths().push_back(std::string(P));
}
+
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/lib"));
+ getFilePaths().push_back(concat(getDriver().SysRoot, "/usr/lib"));
}
std::string Yggdrasil::ComputeEffectiveClangTriple(const ArgList &Args,
@@ -178,7 +181,7 @@ ToolChain::UnwindTableLevel Yggdrasil::getDefaultUnwindTableLevel(const llvm::op
void Yggdrasil::addClangTargetOptions(const ArgList &DriverArgs,
ArgStringList &CC1Args,
Action::OffloadKind) const {
- if (getArch() == llvm::Triple::x86) {
+ if (getArch() == llvm::Triple::x86 || getArch() == llvm::Triple::riscv64) {
CC1Args.push_back("-mstack-alignment=16");
}
// if (!DriverArgs.hasFlag(options::OPT_fuse_init_array,
@@ -214,6 +217,8 @@ void Yggdrasil::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
llvm::sys::path::append(P, "include");
addExternCSystemInclude(DriverArgs, CC1Args, P.str());
}
+
+ addSystemInclude(DriverArgs, CC1Args, concat(getDriver().SysRoot, "/usr/include"));
}
void Yggdrasil::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
diff --git a/libcxx/include/__config b/libcxx/include/__config
index ecb21a705c51..af49b7e359fb 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -817,7 +817,8 @@ typedef __char32_t char32_t;
defined(__APPLE__) || \
defined(__MVS__) || \
defined(_AIX) || \
- defined(__EMSCRIPTEN__)
+ defined(__EMSCRIPTEN__) || \
+ defined(__yggdrasil__)
// clang-format on
# define _LIBCPP_HAS_THREAD_API_PTHREAD
# elif defined(__Fuchsia__)
diff --git a/libcxx/src/chrono.cpp b/libcxx/src/chrono.cpp
index 83e8a64504ae..23c041c3857f 100644
--- a/libcxx/src/chrono.cpp
+++ b/libcxx/src/chrono.cpp
@@ -33,7 +33,7 @@
// OpenBSD does not have a fully conformant suite of POSIX timers, but
// it does have clock_gettime and CLOCK_MONOTONIC which is all we need.
-#if defined(__APPLE__) || defined(__gnu_hurd__) || defined(__OpenBSD__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
+#if defined(__APPLE__) || defined(__gnu_hurd__) || defined(__OpenBSD__) || defined(__yggdrasil__) || (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
# define _LIBCPP_HAS_CLOCK_GETTIME
#endif
diff --git a/lld/Common/Filesystem.cpp b/lld/Common/Filesystem.cpp
index c2d3644191c9..3fb66c892f12 100644
--- a/lld/Common/Filesystem.cpp
+++ b/lld/Common/Filesystem.cpp
@@ -18,7 +18,7 @@
#include "llvm/Support/Parallel.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/TimeProfiler.h"
-#if LLVM_ON_UNIX
+#if LLVM_ON_UNIX || defined(__yggdrasil__)
#include <unistd.h>
#endif
#include <thread>
diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt
index 12618966c4ad..cd310e22ef3b 100644
--- a/llvm/CMakeLists.txt
+++ b/llvm/CMakeLists.txt
@@ -1238,7 +1238,7 @@ if( LLVM_INCLUDE_UTILS )
if( LLVM_INCLUDE_TESTS )
set(LLVM_SUBPROJECT_TITLE "Third-Party/Google Test")
add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest)
- set(LLVM_SUBPROJECT_TITLE)
+ set(LLVM_SUBPROJECT_TITLE)
endif()
else()
if ( LLVM_INCLUDE_TESTS )
diff --git a/llvm/include/llvm/ADT/GenericCycleImpl.h b/llvm/include/llvm/ADT/GenericCycleImpl.h
index ab9c421a4469..1c3a23ba609d 100644
--- a/llvm/include/llvm/ADT/GenericCycleImpl.h
+++ b/llvm/include/llvm/ADT/GenericCycleImpl.h
@@ -393,7 +393,9 @@ void GenericCycleInfo<ContextT>::compute(FunctionT &F) {
<< "\n");
Compute.run(&F.front());
+#if !defined(NDEBUG)
assert(validateTree());
+#endif
}
template <typename ContextT>
@@ -406,7 +408,9 @@ void GenericCycleInfo<ContextT>::splitCriticalEdge(BlockT *Pred, BlockT *Succ,
return;
addBlockToCycle(NewBlock, Cycle);
+#if !defined(NDEBUG)
assert(validateTree());
+#endif
}
/// \brief Find the innermost cycle containing a given block.
diff --git a/llvm/include/llvm/Support/FileSystem.h b/llvm/include/llvm/Support/FileSystem.h
index 9cf53360b4e9..dbd25abf766b 100644
--- a/llvm/include/llvm/Support/FileSystem.h
+++ b/llvm/include/llvm/Support/FileSystem.h
@@ -135,7 +135,7 @@ inline perms operator~(perms x) {
/// represents the information provided by Windows FileFirstFile/FindNextFile.
class basic_file_status {
protected:
- #if defined(LLVM_ON_UNIX)
+ #if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
time_t fs_st_atime = 0;
time_t fs_st_mtime = 0;
uint32_t fs_st_atime_nsec = 0;
@@ -159,7 +159,7 @@ public:
explicit basic_file_status(file_type Type) : Type(Type) {}
- #if defined(LLVM_ON_UNIX)
+ #if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
basic_file_status(file_type Type, perms Perms, time_t ATime,
uint32_t ATimeNSec, time_t MTime, uint32_t MTimeNSec,
uid_t UID, gid_t GID, off_t Size)
@@ -198,7 +198,7 @@ public:
/// same machine.
TimePoint<> getLastModificationTime() const;
- #if defined(LLVM_ON_UNIX)
+ #if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
uint32_t getUser() const { return fs_st_uid; }
uint32_t getGroup() const { return fs_st_gid; }
uint64_t getSize() const { return fs_st_size; }
@@ -225,7 +225,7 @@ public:
class file_status : public basic_file_status {
friend bool equivalent(file_status A, file_status B);
- #if defined(LLVM_ON_UNIX)
+ #if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
dev_t fs_st_dev = 0;
nlink_t fs_st_nlinks = 0;
ino_t fs_st_ino = 0;
@@ -240,7 +240,7 @@ public:
explicit file_status(file_type Type) : basic_file_status(Type) {}
- #if defined(LLVM_ON_UNIX)
+ #if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
file_status(file_type Type, perms Perms, dev_t Dev, nlink_t Links, ino_t Ino,
time_t ATime, uint32_t ATimeNSec,
time_t MTime, uint32_t MTimeNSec,
@@ -1209,7 +1209,7 @@ std::error_code unlockFile(int FD);
/// means that the filesystem may have failed to perform some buffered writes.
std::error_code closeFile(file_t &F);
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
/// @brief Change ownership of a file.
///
/// @param Owner The owner of the file to change to.
diff --git a/llvm/include/llvm/Support/Program.h b/llvm/include/llvm/Support/Program.h
index 9df94eb604c7..f9266dddf4d2 100644
--- a/llvm/include/llvm/Support/Program.h
+++ b/llvm/include/llvm/Support/Program.h
@@ -28,7 +28,7 @@ namespace sys {
/// This is the OS-specific separator for PATH like environment variables:
// a colon on Unix or a semicolon on Windows.
-#if defined(LLVM_ON_UNIX)
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
const char EnvPathSeparator = ':';
#elif defined (_WIN32)
const char EnvPathSeparator = ';';
diff --git a/llvm/include/llvm/Support/thread.h b/llvm/include/llvm/Support/thread.h
index 69c06c050aac..ebb04812fae8 100644
--- a/llvm/include/llvm/Support/thread.h
+++ b/llvm/include/llvm/Support/thread.h
@@ -31,7 +31,7 @@ typedef PVOID HANDLE;
namespace llvm {
-#if LLVM_ON_UNIX || _WIN32
+#if LLVM_ON_UNIX || defined(__yggdrasil__) || _WIN32
/// LLVM thread following std::thread interface with added constructor to
/// specify stack size.
@@ -46,7 +46,7 @@ class thread {
}
public:
-#if LLVM_ON_UNIX
+#if LLVM_ON_UNIX || defined(__yggdrasil__)
using native_handle_type = pthread_t;
using id = pthread_t;
using start_routine_type = void *(*)(void *);
diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp
index 70803c153d8c..3eb34d7d8fc2 100644
--- a/llvm/lib/IR/Constants.cpp
+++ b/llvm/lib/IR/Constants.cpp
@@ -716,7 +716,7 @@ static bool constantIsDead(const Constant *C, bool RemoveDeadUsers) {
ReplaceableMetadataImpl::SalvageDebugInfo(*C);
const_cast<Constant *>(C)->destroyConstant();
}
-
+
return true;
}
@@ -2239,10 +2239,10 @@ Constant *ConstantExpr::getPointerBitCastOrAddrSpaceCast(Constant *S,
}
Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) {
-#ifndef NDEBUG
+// #ifndef NDEBUG
bool fromVec = isa<VectorType>(C->getType());
bool toVec = isa<VectorType>(Ty);
-#endif
+// #endif
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
assert(C->getType()->isIntOrIntVectorTy() && "Trunc operand must be integer");
assert(Ty->isIntOrIntVectorTy() && "Trunc produces only integral");
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index 3440fcf711c7..e1e5e899d4c2 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -382,11 +382,11 @@ StringRef DIScope::getName() const {
return "";
}
-#ifndef NDEBUG
+// #ifndef NDEBUG
static bool isCanonical(const MDString *S) {
return !S || !S->getString().empty();
}
-#endif
+// #endif
dwarf::Tag GenericDINode::getTag() const { return (dwarf::Tag)SubclassData16; }
GenericDINode *GenericDINode::getImpl(LLVMContext &Context, unsigned Tag,
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index b2ee75811fbb..701c2d78fb88 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -465,7 +465,7 @@ void Value::assertModuleIsMaterializedImpl() const {
#endif
}
-#ifndef NDEBUG
+// #ifndef NDEBUG
static bool contains(SmallPtrSetImpl<ConstantExpr *> &Cache, ConstantExpr *Expr,
Constant *C) {
if (!Cache.insert(Expr).second)
@@ -498,7 +498,7 @@ static bool contains(Value *Expr, Value *V) {
SmallPtrSet<ConstantExpr *, 4> Cache;
return contains(Cache, CE, C);
}
-#endif // NDEBUG
+// #endif // NDEBUG
void Value::doRAUW(Value *New, ReplaceMetadataUses ReplaceMetaUses) {
assert(New && "Value::replaceAllUsesWith(<null>) is invalid!");
@@ -827,7 +827,7 @@ bool Value::canBeFreed() const {
// which is why we need the explicit opt in on a per collector basis.
if (!F->hasGC())
return true;
-
+
const auto &GCName = F->getGC();
if (GCName == "statepoint-example") {
auto *PT = cast<PointerType>(this->getType());
diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt
index f653379e3033..bbc934d1460b 100644
--- a/llvm/lib/Support/CMakeLists.txt
+++ b/llvm/lib/Support/CMakeLists.txt
@@ -37,6 +37,10 @@ if(LLVM_ENABLE_ZSTD)
list(APPEND imported_libs ${zstd_target})
endif()
+if (CMAKE_SYSTEM_NAME STREQUAL "yggdrasil")
+ set(system_libs ${system_libs} m)
+endif()
+
if( WIN32 )
# libuuid required for FOLDERID_Profile usage in lib/Support/Windows/Path.inc.
# advapi32 required for CryptAcquireContextW in lib/Support/Windows/Path.inc.
diff --git a/llvm/lib/Support/COM.cpp b/llvm/lib/Support/COM.cpp
index f37b95ba8651..d3d80db52a70 100644
--- a/llvm/lib/Support/COM.cpp
+++ b/llvm/lib/Support/COM.cpp
@@ -15,7 +15,7 @@
#include "llvm/Config/llvm-config.h"
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/COM.inc"
#elif defined(_WIN32)
#include "Windows/COM.inc"
diff --git a/llvm/lib/Support/Chrono.cpp b/llvm/lib/Support/Chrono.cpp
index 993d200675fe..6e00d5dd79b3 100644
--- a/llvm/lib/Support/Chrono.cpp
+++ b/llvm/lib/Support/Chrono.cpp
@@ -26,7 +26,7 @@ static inline struct tm getStructTM(TimePoint<> TP) {
struct tm Storage;
std::time_t OurTime = toTimeT(TP);
-#if defined(LLVM_ON_UNIX)
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
struct tm *LT = ::localtime_r(&OurTime, &Storage);
assert(LT);
(void)LT;
@@ -44,7 +44,7 @@ static inline struct tm getStructTMUtc(UtcTime<> TP) {
struct tm Storage;
std::time_t OurTime = toTimeT(TP);
-#if defined(LLVM_ON_UNIX)
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
struct tm *LT = ::gmtime_r(&OurTime, &Storage);
assert(LT);
(void)LT;
diff --git a/llvm/lib/Support/CrashRecoveryContext.cpp b/llvm/lib/Support/CrashRecoveryContext.cpp
index f53aea177d61..e8d97aedc0c1 100644
--- a/llvm/lib/Support/CrashRecoveryContext.cpp
+++ b/llvm/lib/Support/CrashRecoveryContext.cpp
@@ -344,8 +344,16 @@ static void uninstallExceptionOrSignalHandlers() {
#include <signal.h>
-static const int Signals[] =
- { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP };
+static const int Signals[] = {
+ SIGABRT,
+ SIGBUS,
+ SIGFPE,
+#if !defined(__yggdrasil__)
+ SIGILL,
+#endif
+ SIGSEGV,
+ SIGTRAP
+};
static const unsigned NumSignals = std::size(Signals);
static struct sigaction PrevActions[NumSignals];
@@ -372,10 +380,12 @@ static void CrashRecoverySignalHandler(int Signal) {
}
// Unblock the signal we received.
+#if !defined(__yggdrasil__)
sigset_t SigMask;
sigemptyset(&SigMask);
sigaddset(&SigMask, Signal);
sigprocmask(SIG_UNBLOCK, &SigMask, nullptr);
+#endif
// Return the same error code as if the program crashed, as mentioned in the
// section "Exit Status for Commands":
@@ -383,8 +393,10 @@ static void CrashRecoverySignalHandler(int Signal) {
int RetCode = 128 + Signal;
// Don't consider a broken pipe as a crash (see clang/lib/Driver/Driver.cpp)
+#if !defined(__yggdrasil__)
if (Signal == SIGPIPE)
RetCode = EX_IOERR;
+#endif
if (CRCI)
const_cast<CrashRecoveryContextImpl *>(CRCI)->HandleCrash(RetCode, Signal);
diff --git a/llvm/lib/Support/Memory.cpp b/llvm/lib/Support/Memory.cpp
index f1ba2d0cfe3a..ad8c64b31984 100644
--- a/llvm/lib/Support/Memory.cpp
+++ b/llvm/lib/Support/Memory.cpp
@@ -19,7 +19,7 @@
#endif // ifndef NDEBUG
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Memory.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 4db9bc80b415..ec8c656bf8e2 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -1196,7 +1196,7 @@ Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl<char> &Buffer,
} // end namespace llvm
// Include the truly platform-specific parts.
-#if defined(LLVM_ON_UNIX)
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Path.inc"
#endif
#if defined(_WIN32)
diff --git a/llvm/lib/Support/Process.cpp b/llvm/lib/Support/Process.cpp
index 54462f23c842..535057f7fd45 100644
--- a/llvm/lib/Support/Process.cpp
+++ b/llvm/lib/Support/Process.cpp
@@ -119,7 +119,7 @@ bool Process::AreCoreFilesPrevented() { return coreFilesPrevented; }
}
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Process.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/Program.cpp b/llvm/lib/Support/Program.cpp
index 181f68cfbb8c..ac52cf126030 100644
--- a/llvm/lib/Support/Program.cpp
+++ b/llvm/lib/Support/Program.cpp
@@ -100,7 +100,7 @@ void sys::printArg(raw_ostream &OS, StringRef Arg, bool Quote) {
}
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Program.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/Signals.cpp b/llvm/lib/Support/Signals.cpp
index 9f9030e79d10..cb68f8010d7e 100644
--- a/llvm/lib/Support/Signals.cpp
+++ b/llvm/lib/Support/Signals.cpp
@@ -273,7 +273,7 @@ static bool printMarkupStackTrace(StringRef Argv0, void **StackTrace, int Depth,
}
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Signals.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/ThreadPool.cpp b/llvm/lib/Support/ThreadPool.cpp
index 27e0f220ac4e..edfc20fbcfee 100644
--- a/llvm/lib/Support/ThreadPool.cpp
+++ b/llvm/lib/Support/ThreadPool.cpp
@@ -158,8 +158,10 @@ void StdThreadPool::wait(ThreadPoolTaskGroup &Group) {
return;
}
// Make sure to not deadlock waiting for oneself.
+#ifndef NDEBUG
assert(CurrentThreadTaskGroups == nullptr ||
!llvm::is_contained(*CurrentThreadTaskGroups, &Group));
+#endif
// Handle the case of recursive call from another task in a different group,
// in which case process tasks while waiting to keep the thread busy and avoid
// possible deadlock.
diff --git a/llvm/lib/Support/Threading.cpp b/llvm/lib/Support/Threading.cpp
index 7cc7ba44cc72..0deae08a3962 100644
--- a/llvm/lib/Support/Threading.cpp
+++ b/llvm/lib/Support/Threading.cpp
@@ -65,7 +65,7 @@ unsigned llvm::ThreadPoolStrategy::compute_thread_count() const {
}
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Threading.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index cf05db546e02..502408f1cb04 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -112,7 +112,7 @@ typedef uint_t uint;
#endif
#if defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__) || \
- defined(__MVS__)
+ defined(__MVS__) || defined(__yggdrasil__)
#define STATVFS_F_FLAG(vfs) (vfs).f_flag
#else
#define STATVFS_F_FLAG(vfs) (vfs).f_flags
@@ -505,6 +505,9 @@ static bool is_local_impl(struct STATVFS &Vfs) {
#elif defined(__Fuchsia__)
// Fuchsia doesn't yet support remote filesystem mounts.
return true;
+#elif defined(__yggdrasil__)
+ // Yggdrasil doesn't yet support remote filesystem mounts.
+ return true;
#elif defined(__EMSCRIPTEN__)
// Emscripten doesn't currently support remote filesystem mounts.
return true;
diff --git a/llvm/lib/Support/Unix/Process.inc b/llvm/lib/Support/Unix/Process.inc
index 84b10ff5d1d0..90edcb2ea177 100644
--- a/llvm/lib/Support/Unix/Process.inc
+++ b/llvm/lib/Support/Unix/Process.inc
@@ -92,7 +92,9 @@ Expected<unsigned> Process::getPageSize() {
}
size_t Process::GetMallocUsage() {
-#if defined(HAVE_MALLINFO2)
+#if defined(__yggdrasil__)
+ return 1;
+#elif defined(HAVE_MALLINFO2)
struct mallinfo2 mi;
mi = ::mallinfo2();
return mi.uordblks;
diff --git a/llvm/lib/Support/Unix/Program.inc b/llvm/lib/Support/Unix/Program.inc
index 2742734bb11e..e6486805e3f5 100644
--- a/llvm/lib/Support/Unix/Program.inc
+++ b/llvm/lib/Support/Unix/Program.inc
@@ -426,7 +426,7 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI,
// Parent process: Wait for the child process to terminate.
int status = 0;
ProcessInfo WaitResult;
-#ifndef __Fuchsia__
+#if !defined(__Fuchsia__)
rusage Info;
if (ProcStat)
ProcStat->reset();
@@ -473,7 +473,7 @@ ProcessInfo llvm::sys::Wait(const ProcessInfo &PI,
sigaction(SIGALRM, &Old, nullptr);
}
-#ifndef __Fuchsia__
+#if !defined(__Fuchsia__) && !defined(__yggdrasil__)
if (ProcStat) {
std::chrono::microseconds UserT = toDuration(Info.ru_utime);
std::chrono::microseconds KernelT = toDuration(Info.ru_stime);
diff --git a/llvm/lib/Support/Unix/Signals.inc b/llvm/lib/Support/Unix/Signals.inc
index 298fde1a387c..a0bc42e70acc 100644
--- a/llvm/lib/Support/Unix/Signals.inc
+++ b/llvm/lib/Support/Unix/Signals.inc
@@ -213,7 +213,10 @@ static const int IntSigs[] = {SIGHUP, SIGINT, SIGTERM, SIGUSR2};
/// Signals that represent that we have a bug, and our prompt termination has
/// been ordered.
-static const int KillSigs[] = {SIGILL,
+static const int KillSigs[] = {
+#if !defined(__yggdrasil__)
+ SIGILL,
+#endif
SIGTRAP,
SIGABRT,
SIGFPE,
@@ -437,7 +440,11 @@ void llvm::sys::SetOneShotPipeSignalFunction(void (*Handler)()) {
void llvm::sys::DefaultOneShotPipeSignalHandler() {
// Send a special return code that drivers can check for, from sysexits.h.
+#if defined(__yggdrasil__)
+ exit(-1);
+#else
exit(EX_IOERR);
+#endif
}
// The public API
diff --git a/llvm/lib/Support/VirtualFileSystem.cpp b/llvm/lib/Support/VirtualFileSystem.cpp
index ce2bf2b4193a..469686a20616 100644
--- a/llvm/lib/Support/VirtualFileSystem.cpp
+++ b/llvm/lib/Support/VirtualFileSystem.cpp
@@ -2323,9 +2323,11 @@ RedirectingFileSystem::lookupPathImpl(
sys::path::const_iterator Start, sys::path::const_iterator End,
RedirectingFileSystem::Entry *From,
llvm::SmallVectorImpl<Entry *> &Entries) const {
+#ifndef NDEBUG
assert(!isTraversalComponent(*Start) &&
!isTraversalComponent(From->getName()) &&
"Paths should not contain traversal components");
+#endif
StringRef FromName = From->getName();
@@ -2725,7 +2727,9 @@ void YAMLVFSWriter::addEntry(StringRef VirtualPath, StringRef RealPath,
bool IsDirectory) {
assert(sys::path::is_absolute(VirtualPath) && "virtual path not absolute");
assert(sys::path::is_absolute(RealPath) && "real path not absolute");
+#ifndef NDEBUG
assert(!pathHasTraversal(VirtualPath) && "path traversal is not supported");
+#endif
Mappings.emplace_back(VirtualPath, RealPath, IsDirectory);
}
diff --git a/llvm/lib/Support/Watchdog.cpp b/llvm/lib/Support/Watchdog.cpp
index 246f3dc7a0ca..4f0f5b1db2d8 100644
--- a/llvm/lib/Support/Watchdog.cpp
+++ b/llvm/lib/Support/Watchdog.cpp
@@ -14,7 +14,7 @@
#include "llvm/Config/llvm-config.h"
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Watchdog.inc"
#endif
#ifdef _WIN32
diff --git a/llvm/lib/Support/raw_socket_stream.cpp b/llvm/lib/Support/raw_socket_stream.cpp
index 04b3233084a4..887eaed86f41 100644
--- a/llvm/lib/Support/raw_socket_stream.cpp
+++ b/llvm/lib/Support/raw_socket_stream.cpp
@@ -11,6 +11,8 @@
//
//===----------------------------------------------------------------------===//
+#if !defined(__yggdrasil__)
+
#include "llvm/Support/raw_socket_stream.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Error.h"
@@ -339,3 +341,5 @@ ssize_t raw_socket_stream::read(char *Ptr, size_t Size,
}
return raw_fd_stream::read(Ptr, Size);
}
+
+#endif // defined(__yggdrasil__)
diff --git a/llvm/lib/Support/regengine.inc b/llvm/lib/Support/regengine.inc
index f23993abc6e7..3fa0c28bb6d8 100644
--- a/llvm/lib/Support/regengine.inc
+++ b/llvm/lib/Support/regengine.inc
@@ -120,8 +120,8 @@ static char *pchar(int);
#define SP(t, s, c) print(m, t, s, c, stdout)
#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2)
#define NOTE(str) { if (m->eflags&REG_TRACE) (void)printf("=%s\n", (str)); }
-static int nope = 0;
#else
+static int nope = 0;
#define SP(t, s, c) /* nothing */
#define AT(t, p1, p2, s1, s2) /* nothing */
#define NOTE(s) /* nothing */
@@ -1047,7 +1047,7 @@ print(struct match *m, const char *caption, states st, int ch, FILE *d)
(void)fprintf(d, "\n");
}
-/*
+/*
- at - print current situation
*/
static void
diff --git a/llvm/lib/TargetParser/Host.cpp b/llvm/lib/TargetParser/Host.cpp
index 865b6a44adbb..94d061504f26 100644
--- a/llvm/lib/TargetParser/Host.cpp
+++ b/llvm/lib/TargetParser/Host.cpp
@@ -23,7 +23,7 @@
#include <string.h>
// Include the platform-specific parts of this class.
-#ifdef LLVM_ON_UNIX
+#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__)
#include "Unix/Host.inc"
#include <sched.h>
#endif
--
2.48.1

11
ports/meta-llvm/port.toml Normal file
View File

@ -0,0 +1,11 @@
description = """
Host side of the LLVM compiler, required by most of other ports
Has a bit of a special handling from xtask, because it is not intended to be installed
to a sysroot, and instead lives in userspace/target/ports-prefix
"""
version = "19.1.3"
[dependencies]
build = []
runtime = []
c-compiler = false

View File

@ -0,0 +1,11 @@
#!/bin/sh
verify_sha256_file() {
echo Verify SHA256: $2
echo "$(cat $1) $2" | sha256sum --check --status
}
verify_sha256() {
echo Verify SHA256: $2
echo "$1 $2" | sha256sum --check --status
}

View File

@ -1,8 +1,8 @@
if (NOT DEFINED ENV{CROSS_TOOLCHAIN_PREFIX})
message(FATAL_ERROR "CROSS_TOOLCHAIN_PREFIX=... must be specified.")
if (NOT DEFINED ENV{Y_HOST_PREFIX})
message(FATAL_ERROR "Y_HOST_PREFIX=... must be specified.")
endif()
set(CROSS_TOOLCHAIN_PREFIX "$ENV{CROSS_TOOLCHAIN_PREFIX}")
set(CROSS_TOOLCHAIN_PREFIX "$ENV{Y_HOST_PREFIX}")
set(CMAKE_SYSTEM_NAME yggdrasil)
set(CMAKE_C_COMPILER "${CROSS_TOOLCHAIN_PREFIX}/bin/clang")
@ -17,6 +17,6 @@ set(CMAKE_ASM_COMPILER_TARGET "aarch64-unknown-yggdrasil")
# set(CMAKE_SHARED_LINKER_FLAGS "-v")
set(CMAKE_C_FLAGS "--target=aarch64-unknown-yggdrasil -fPIC")
set(CMAKE_CXX_FLAGS "--target=aarch64-unknown-yggdrasil -nostdlib++ -fPIC -D_LIBCPP_HAS_NO_TREE_BARRIER")
set(CMAKE_CXX_FLAGS "--target=aarch64-unknown-yggdrasil -fPIC -D_LIBCPP_HAS_NO_TREE_BARRIER")
# Specify any additional include paths or linker flags as needed

View File

@ -1,8 +1,8 @@
if (NOT DEFINED ENV{CROSS_TOOLCHAIN_PREFIX})
message(FATAL_ERROR "CROSS_TOOLCHAIN_PREFIX=... must be specified.")
if (NOT DEFINED ENV{Y_HOST_PREFIX})
message(FATAL_ERROR "Y_HOST_PREFIX=... must be specified.")
endif()
set(CROSS_TOOLCHAIN_PREFIX "$ENV{CROSS_TOOLCHAIN_PREFIX}")
set(CROSS_TOOLCHAIN_PREFIX "$ENV{Y_HOST_PREFIX}")
set(CMAKE_SYSTEM_NAME yggdrasil)
set(CMAKE_C_COMPILER "${CROSS_TOOLCHAIN_PREFIX}/bin/clang")

View File

@ -1,8 +1,8 @@
if (NOT DEFINED ENV{CROSS_TOOLCHAIN_PREFIX})
message(FATAL_ERROR "CROSS_TOOLCHAIN_PREFIX=... must be specified.")
if (NOT DEFINED ENV{Y_HOST_PREFIX})
message(FATAL_ERROR "Y_HOST_PREFIX=... must be specified.")
endif()
set(CROSS_TOOLCHAIN_PREFIX "$ENV{CROSS_TOOLCHAIN_PREFIX}")
set(CROSS_TOOLCHAIN_PREFIX "$ENV{Y_HOST_PREFIX}")
set(CMAKE_SYSTEM_NAME yggdrasil)
set(CMAKE_C_COMPILER "${CROSS_TOOLCHAIN_PREFIX}/bin/clang")

14
ports/openlibm/compile.sh Executable file
View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
source_dir=$2
build_dir=$3
cd $build_dir/openlibm-${Y_PORT_VERSION}
make \
SYSROOT=$Y_SYSROOT \
ARCH=$Y_ARCH \
TRIPLE=${Y_ARCH}-unknown-yggdrasil \
USECLANG=1 \
CC=clang

31
ports/openlibm/fetch.sh Executable file
View File

@ -0,0 +1,31 @@
#!/bin/sh
. $Y_PORT_UTILS/sig.sh
set -e
SRC_FILENAME="v${Y_PORT_VERSION}.tar.gz"
SRC_SHA256="c0bac12a6596f2315341790a7f386f9162a5b1f98db9ec40d883fce64e231942"
URL_BASE="https://github.com/JuliaMath/openlibm/archive/refs/tags"
RELEASE_URL="$URL_BASE/$SRC_FILENAME"
source_dir=$2
build_dir=$3
if [ ! -f $build_dir/.source-ready ]; then
mkdir -p $build_dir
cd $build_dir
curl -LO $RELEASE_URL
verify_sha256 $SRC_SHA256 $SRC_FILENAME
tar xf $SRC_FILENAME
cd openlibm-${Y_PORT_VERSION}
for patch in $1/patches/*.patch; do
echo Apply $patch
patch -p1 <$patch
done
touch $build_dir/.source-ready
fi

16
ports/openlibm/install.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
build_dir=$3
cd $build_dir/openlibm-${Y_PORT_VERSION}
make install \
DESTDIR=$Y_SYSROOT \
SYSROOT=$Y_SYSROOT \
ARCH=$Y_ARCH \
TRIPLE=${Y_ARCH}-unknown-yggdrasil \
USECLANG=1 \
CC=clang \
prefix=/usr \
>/dev/null
ln -sf libopenlibm.so.4.0 $Y_SYSROOT/usr/lib/libm.so

View File

@ -0,0 +1,44 @@
From 8840f9fe4825e5ad30e54477bfffc1c6750e3d61 Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Wed, 13 Nov 2024 16:17:30 +0200
Subject: [PATCH 1/4] alnyan/yggdrasil: force cross-compilation for clang
---
Make.inc | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/Make.inc b/Make.inc
index df8fbf0..35eda23 100644
--- a/Make.inc
+++ b/Make.inc
@@ -47,7 +47,7 @@ AR := $(TOOLPREFIX)ar
ifeq ($(USECLANG),1)
USEGCC ?= 0
-CC = clang
+CC ?= clang
CFLAGS_add += -fno-builtin -fno-strict-aliasing
endif
@@ -144,6 +144,9 @@ ifeq ($(ARCH),wasm32)
CFLAGS_arch += -ffreestanding -nostdlib -nostdinc --target=wasm32-unknown-unknown
endif
+LDFLAGS_arch += --sysroot=$(SYSROOT) --target=$(TRIPLE)
+CFLAGS_arch += --target=$(TRIPLE) -ffreestanding
+
# Add our "arch"-related FLAGS in. We separate arch-related flags out so that
# we can conveniently get at them for targets that don't want the rest of
# *FLAGS_add, such as the testing Makefile targets
@@ -163,7 +166,7 @@ endif
ifneq ($(filter $(ARCH),i387 amd64),)
# Determines whether `long double` is the same as `double` on this arch.
# linux x86_64, for instance, `long double` is 80 bits wide, whereas on macOS aarch64,
-# `long double` is the same as `double`.
+# `long double` is the same as `double`.
LONG_DOUBLE_NOT_DOUBLE := 1
else ifeq ($(ARCH), aarch64 riscv64)
ifeq ($(filter $(OS),Darwin WINNT),)
--
2.48.1

View File

@ -0,0 +1,34 @@
From 42f9cd9675361c51b8d32eef6cbc59ac6fd55755 Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Mon, 18 Nov 2024 19:28:31 +0200
Subject: [PATCH 2/4] alnyan/yggdrasil: fix build for aarch64
---
Make.inc | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Make.inc b/Make.inc
index 35eda23..ad38fab 100644
--- a/Make.inc
+++ b/Make.inc
@@ -3,7 +3,7 @@
# Default build rule for any Makefile in this project: all
default: all
-OS := $(shell uname)
+OS ?= $(shell uname)
# Do not forget to bump SOMINOR when changing VERSION,
# and SOMAJOR when breaking ABI in a backward-incompatible way
VERSION = 0.8.0
@@ -168,7 +168,7 @@ ifneq ($(filter $(ARCH),i387 amd64),)
# linux x86_64, for instance, `long double` is 80 bits wide, whereas on macOS aarch64,
# `long double` is the same as `double`.
LONG_DOUBLE_NOT_DOUBLE := 1
-else ifeq ($(ARCH), aarch64 riscv64)
+else ifneq ($(filter $(ARCH),aarch64 riscv64),)
ifeq ($(filter $(OS),Darwin WINNT),)
LONG_DOUBLE_NOT_DOUBLE := 1
endif
--
2.48.1

View File

@ -0,0 +1,38 @@
From 4413af583b2bff5e9da46ef7cbf168bfa1c9947e Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Wed, 26 Feb 2025 18:14:08 +0200
Subject: [PATCH 3/4] alnyan/yggdrasil: fix riscv64 build
---
Make.inc | 1 +
Makefile | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/Make.inc b/Make.inc
index ad38fab..48efddf 100644
--- a/Make.inc
+++ b/Make.inc
@@ -92,6 +92,7 @@ override ARCH := mips
endif
ifeq ($(findstring riscv64,$(ARCH)),riscv64)
override ARCH := riscv64
+MARCH ?= rv64gc
endif
ifeq ($(findstring loongarch64,$(ARCH)),loongarch64)
override ARCH := loongarch64
diff --git a/Makefile b/Makefile
index 17e03a0..b096cf3 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ ifeq ($(LONG_DOUBLE_NOT_DOUBLE),1)
ifneq ($(filter $(ARCH),i387 amd64),)
SUBDIRS += ld80
else
-ifneq ($(filter $(ARCH),aarch64),)
+ifneq ($(filter $(ARCH),aarch64 riscv64),)
SUBDIRS += ld128
else
endif
--
2.48.1

View File

@ -0,0 +1,91 @@
From 2d97808b68f81bc35ea4688e625222d5215305ae Mon Sep 17 00:00:00 2001
From: Mark Poliakov <mark@alnyan.me>
Date: Thu, 6 Mar 2025 14:04:50 +0200
Subject: [PATCH 4/4] alnyan/yggdrasil: fix includes
---
include/openlibm.h | 6 +++---
include/openlibm_fenv.h | 16 ++++++++--------
include/openlibm_fenv_amd64.h | 2 +-
include/openlibm_math.h | 2 +-
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/openlibm.h b/include/openlibm.h
index d851945..704a579 100644
--- a/include/openlibm.h
+++ b/include/openlibm.h
@@ -1,8 +1,8 @@
#ifndef OPENLIBM_H
#define OPENLIBM_H
-#include <openlibm_complex.h>
-#include <openlibm_fenv.h>
-#include <openlibm_math.h>
+#include "openlibm_complex.h"
+#include "openlibm_fenv.h"
+#include "openlibm_math.h"
#endif /* !OPENLIBM_H */
diff --git a/include/openlibm_fenv.h b/include/openlibm_fenv.h
index 145e960..33453f3 100644
--- a/include/openlibm_fenv.h
+++ b/include/openlibm_fenv.h
@@ -3,21 +3,21 @@
#else /* !OPENLIBM_USE_HOST_FENV_H */
#if defined(__aarch64__) || defined(__arm__)
-#include <openlibm_fenv_arm.h>
+#include "openlibm_fenv_arm.h"
#elif defined(__x86_64__)
-#include <openlibm_fenv_amd64.h>
+#include "openlibm_fenv_amd64.h"
#elif defined(__i386__)
-#include <openlibm_fenv_i387.h>
+#include "openlibm_fenv_i387.h"
#elif defined(__powerpc__) || defined(__POWERPC__)
-#include <openlibm_fenv_powerpc.h>
+#include "openlibm_fenv_powerpc.h"
#elif defined(__mips__)
-#include <openlibm_fenv_mips.h>
+#include "openlibm_fenv_mips.h"
#elif defined(__s390__)
-#include <openlibm_fenv_s390.h>
+#include "openlibm_fenv_s390.h"
#elif defined(__riscv)
-#include <openlibm_fenv_riscv.h>
+#include "openlibm_fenv_riscv.h"
#elif defined(__loongarch64)
-#include <openlibm_fenv_loongarch64.h>
+#include "openlibm_fenv_loongarch64.h"
#else
#error "Unsupported platform"
#endif
diff --git a/include/openlibm_fenv_amd64.h b/include/openlibm_fenv_amd64.h
index c6db210..6cb3ed5 100644
--- a/include/openlibm_fenv_amd64.h
+++ b/include/openlibm_fenv_amd64.h
@@ -29,7 +29,7 @@
#ifndef _FENV_H_
#define _FENV_H_
-#include <openlibm_defs.h>
+#include "openlibm_defs.h"
#include "cdefs-compat.h"
#include "types-compat.h"
diff --git a/include/openlibm_math.h b/include/openlibm_math.h
index 701ad70..e548f36 100644
--- a/include/openlibm_math.h
+++ b/include/openlibm_math.h
@@ -18,7 +18,7 @@
#include <math.h>
#else /* !OPENLIBM_USE_HOST_MATH_H */
-#include <openlibm_defs.h>
+#include "openlibm_defs.h"
#ifndef OPENLIBM_MATH_H
#define OPENLIBM_MATH_H
--
2.48.1

5
ports/openlibm/port.toml Normal file
View File

@ -0,0 +1,5 @@
description = ""
version = "0.8.4"
[dependencies]
runtime = ["meta-libc", "compiler-rt"]

View File

@ -1,22 +0,0 @@
if (NOT DEFINED ENV{CROSS_TOOLCHAIN_PREFIX})
message(FATAL_ERROR "CROSS_TOOLCHAIN_PREFIX=... must be specified.")
endif()
set(CROSS_TOOLCHAIN_PREFIX "$ENV{CROSS_TOOLCHAIN_PREFIX}")
set(CMAKE_SYSTEM_NAME yggdrasil)
set(CMAKE_C_COMPILER "${CROSS_TOOLCHAIN_PREFIX}/bin/clang")
set(CMAKE_CXX_COMPILER "${CROSS_TOOLCHAIN_PREFIX}/bin/clang++")
# Specify the target triple for your custom OS.
set(CMAKE_C_COMPILER_TARGET "i686-unknown-yggdrasil")
set(CMAKE_ASM_COMPILER_TARGET "i686-unknown-yggdrasil")
# Disable default system libraries
# set(CMAKE_EXE_LINKER_FLAGS "-nostdlib")
# set(CMAKE_SHARED_LINKER_FLAGS "-v")
set(CMAKE_C_FLAGS "--target=i686-unknown-yggdrasil -fPIC -m32")
set(CMAKE_CXX_FLAGS "--target=i686-unknown-yggdrasil -m32 -nostdlib++ -fPIC -D_LIBCPP_HAS_NO_TREE_BARRIER")
# Specify any additional include paths or linker flags as needed

View File

@ -8,4 +8,7 @@ pub mod io;
pub mod mem;
pub mod net;
pub mod signal;
pub mod time;
pub mod time {
pub use crate::sys::time::set_real_time;
}

View File

@ -1,16 +1,10 @@
use std::io;
use runtime::rt as yggdrasil_rt;
use yggdrasil_rt::time::{self, ClockType};
use yggdrasil_rt::time::{self, ClockType, SystemTime as RawSystemTime};
use crate::time::{SystemClock, SystemTime};
pub fn now(clock: SystemClock) -> SystemTime {
let clock = match clock {
SystemClock::Monotonic => ClockType::Monotonic,
SystemClock::RealTime => ClockType::RealTime,
};
let raw = time::get_clock(clock).expect("Could not get clock");
SystemTime {
seconds: raw.seconds(),
nanoseconds: raw.subsec_nanos() as u32,
}
pub fn set_real_time(seconds: u64, nanoseconds: u32) -> io::Result<()> {
let raw = RawSystemTime::new(seconds, nanoseconds as u64);
time::set_clock(ClockType::RealTime, raw)?;
Ok(())
}

View File

@ -1,19 +0,0 @@
use crate::sys;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SystemTime {
pub seconds: u64,
pub nanoseconds: u32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SystemClock {
Monotonic,
RealTime,
}
impl SystemTime {
pub fn now(clock: SystemClock) -> Self {
sys::time::now(clock)
}
}

View File

@ -27,6 +27,11 @@ fn include_dir(d: &DirEntry) -> bool {
.is_some_and(|c| c.to_str().is_some_and(|x| !x.starts_with("_")))
}
fn content_matches(path: impl AsRef<Path>, data: &[u8]) -> bool {
let content = fs::read(path).unwrap();
content == data
}
fn generate_header(config_path: impl AsRef<Path>, header_output: impl AsRef<Path>) {
let config_path = config_path.as_ref();
let header_output = header_output.as_ref();
@ -56,12 +61,21 @@ fn generate_header(config_path: impl AsRef<Path>, header_output: impl AsRef<Path
config.cpp_compat = true;
config.function.no_return = Some("__attribute__((noreturn))".into());
let mut output = vec![];
cbindgen::Builder::new()
.with_config(config)
.with_src(mod_path)
.generate()
.unwrap()
.write_to_file(header_path);
.write(&mut output);
if !header_path.exists() || !content_matches(&header_path, &output) {
if let Some(parent) = header_path.parent() {
fs::create_dir_all(&parent).expect("Could not create header directory");
}
fs::write(&header_path, &output[..]).expect("Could not write header");
}
}
fn compile_crt0(arch: &str, output_dir: impl AsRef<Path>) {
@ -96,7 +110,6 @@ fn compile_crt0(arch: &str, output_dir: impl AsRef<Path>) {
_ => (),
}
command
.arg("-o")
.arg(output_dir.join("crt0.o"))

View File

@ -1,4 +1,4 @@
#include <openlibm_math.h>
#include <openlibm/openlibm_math.h>
typedef float float_t;
typedef double double_t;

View File

@ -8,7 +8,7 @@ use std::{
};
use bytemuck::{Pod, Zeroable};
use chrono::{DateTime, Utc};
use chrono::{DateTime, Timelike, Utc};
use clap::Parser;
use cross::io::{Poll, TimerFd};
@ -183,12 +183,10 @@ struct Args {
server: String,
}
fn handle_time(args: &Args, time: DateTime<Utc>) -> Result<(), Error> {
if args.interval.is_none() {
println!("{time}");
} else {
log::info!("{time}");
}
fn handle_time(time: DateTime<Utc>) -> Result<(), Error> {
let seconds = time.timestamp() as u64;
let nanoseconds = time.nanosecond();
cross::time::set_real_time(seconds, nanoseconds)?;
Ok(())
}
@ -205,11 +203,14 @@ fn run_loop(args: &Args, interval: Duration) -> Result<(), Error> {
let response = do_request(server);
match response {
Ok(time) => {
if let Err(error) = handle_time(args, time) {
Ok(time) if !args.dry_run => {
if let Err(error) = handle_time(time) {
log::error!("handle_time(): {error}");
}
}
Ok(time) => {
log::info!("Current time: {time}");
}
Err(error) => {
log::error!("{}: {error}", args.server);
}
@ -222,7 +223,9 @@ fn run_loop(args: &Args, interval: Duration) -> Result<(), Error> {
fn run_once(args: &Args) -> Result<(), Error> {
let server = resolve_server(args)?;
let response = do_request(server)?;
handle_time(args, response)?;
if !args.dry_run {
handle_time(response)?;
}
Ok(())
}

View File

@ -1,249 +1,206 @@
use std::{
fs,
path::{Path, PathBuf},
process::Command,
};
use crate::{
env::BuildEnv,
error::Error,
util::{self, git_clone},
};
use super::{
cargo::CargoBuilder,
toolchain_c::{self, Llvm},
};
pub const OPENLIBM_URL: &str = "https://git.alnyan.me/yggdrasil/openlibm.git";
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,
}
fn build_test_cpp_program(
env: &BuildEnv,
llvm: &Llvm,
install: &mut Vec<(PathBuf, PathBuf)>,
) -> Result<(), Error> {
log::info!("Building a test C++ program [PIE]");
let target_dir = &env.userspace_output_dir;
let mut command = llvm.c_clangpp(env);
command
.args([
"-fpie",
"-Bdynamic",
"-O0",
"-ggdb",
"-fstack-protector-strong",
])
.arg("-o")
.arg(target_dir.join("cpp-test"))
.arg(env.workspace_root.join("test.cpp"));
if !command.status()?.success() {
return Err(Error::ExternalCommandFailed);
}
install.push((target_dir.join("cpp-test"), "cpp-test".into()));
log::info!("Building a test C++ program [static]");
let target_dir = &env.userspace_output_dir;
let mut command = llvm.c_clangpp(env);
command
.args(["-static", "-O0", "-ggdb", "-fstack-protector-strong"])
.arg("-o")
.arg(target_dir.join("cpp-test-static"))
.arg(env.workspace_root.join("test.cpp"));
if !command.status()?.success() {
return Err(Error::ExternalCommandFailed);
}
install.push((target_dir.join("cpp-test-static"), "cpp-test-static".into()));
Ok(())
}
fn build_test_c_program(
env: &BuildEnv,
llvm: &Llvm,
install: &mut Vec<(PathBuf, PathBuf)>,
) -> Result<(), Error> {
log::info!("Building a test C program [PIE]");
let target_dir = &env.userspace_output_dir;
let mut command = llvm.c_clang(env);
command
.args([
"-fpie",
"-Bdynamic",
"-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);
}
install.push((target_dir.join("c-test"), "c-test".into()));
// if env.arch == Arch::x86_64 {
log::info!("Building a test C program [static]");
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-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],
})
}
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("OS", "yggdrasil");
command.env("TRIPLE", format!("{}-unknown-yggdrasil", env.arch.name()));
command.env("USEGCC", "0");
command.env("USECLANG", "1");
command.env("CC", llvm.clang());
command.env(
"CFLAGS",
format!(
"-isystem {}",
env.llvm_sysroot.join("usr/include").display()
),
);
command.current_dir(&libm_path);
command
}
let libm_path = env
.workspace_root
.join(format!("toolchain-c/libs/openlibm-{}", env.arch.name()));
git_clone(&libm_path, OPENLIBM_URL, "alnyan/yggdrasil", false)?;
log::info!("Building openlibm");
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(())
}
pub fn build_c(env: &BuildEnv, install: &mut Vec<(PathBuf, PathBuf)>) -> Result<(), Error> {
let llvm = toolchain_c::install_llvm_compiler(env)?;
let ygglibc = build_ygglibc(env)?;
install_ygglibc(env, &ygglibc)?;
toolchain_c::install_compiler_rt(env, &llvm)?;
let libm = build_openlibm(env, &llvm)?;
install_openlibm(env, &libm)?;
if env.config.components(env).libcxx {
toolchain_c::install_llvm_cxx_runtime(env, &llvm)?;
}
build_test_c_program(env, &llvm, install)?;
if env.config.components(env).libcxx {
build_test_cpp_program(env, &llvm, install)?;
install.push((
env.llvm_sysroot.join("lib/libc++.so"),
"lib/libc++.so".into(),
));
}
install.push((ygglibc.crt0_file, "lib/crt0.o".into()));
install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));
Ok(())
}
// use std::{
// fs,
// path::{Path, PathBuf},
// process::Command,
// };
//
// use crate::{
// env::BuildEnv,
// error::Error,
// util::{self, git_clone},
// };
//
// use super::{
// cargo::CargoBuilder,
// toolchain_c::{self, Llvm},
// };
//
// pub const OPENLIBM_URL: &str = "https://git.alnyan.me/yggdrasil/openlibm.git";
//
// 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,
// }
//
// fn build_test_cpp_program(
// env: &BuildEnv,
// llvm: &Llvm,
// install: &mut Vec<(PathBuf, PathBuf)>,
// ) -> Result<(), Error> {
// log::info!("Building a test C++ program [PIE]");
// let target_dir = &env.userspace_output_dir;
//
// let mut command = llvm.c_clangpp(env);
// command
// .args([
// "-fpie",
// "-Bdynamic",
// "-O0",
// "-ggdb",
// "-fstack-protector-strong",
// ])
// .arg("-o")
// .arg(target_dir.join("cpp-test"))
// .arg(env.workspace_root.join("test.cpp"));
//
// if !command.status()?.success() {
// return Err(Error::ExternalCommandFailed);
// }
//
// install.push((target_dir.join("cpp-test"), "cpp-test".into()));
//
// log::info!("Building a test C++ program [static]");
// let target_dir = &env.userspace_output_dir;
//
// let mut command = llvm.c_clangpp(env);
// command
// .args(["-static", "-O0", "-ggdb", "-fstack-protector-strong"])
// .arg("-o")
// .arg(target_dir.join("cpp-test-static"))
// .arg(env.workspace_root.join("test.cpp"));
//
// if !command.status()?.success() {
// return Err(Error::ExternalCommandFailed);
// }
//
// install.push((target_dir.join("cpp-test-static"), "cpp-test-static".into()));
//
// Ok(())
// }
//
// fn build_test_c_program(
// env: &BuildEnv,
// llvm: &Llvm,
// install: &mut Vec<(PathBuf, PathBuf)>,
// ) -> Result<(), Error> {
// log::info!("Building a test C program [PIE]");
// let target_dir = &env.userspace_output_dir;
//
// let mut command = llvm.c_clang(env);
// command
// .args([
// "-fpie",
// "-Bdynamic",
// "-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);
// }
//
// install.push((target_dir.join("c-test"), "c-test".into()));
//
// // if env.arch == Arch::x86_64 {
// log::info!("Building a test C program [static]");
// 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-static"), "c-test-static".into()));
// // }
//
// Ok(())
// }
//
// 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("OS", "yggdrasil");
// command.env("TRIPLE", format!("{}-unknown-yggdrasil", env.arch.name()));
// command.env("USEGCC", "0");
// command.env("USECLANG", "1");
// command.env("CC", llvm.clang());
// command.env(
// "CFLAGS",
// format!(
// "-isystem {}",
// env.llvm_sysroot.join("usr/include").display()
// ),
// );
// command.current_dir(&libm_path);
// command
// }
//
// let libm_path = env
// .workspace_root
// .join(format!("toolchain-c/libs/openlibm-{}", env.arch.name()));
//
// git_clone(&libm_path, OPENLIBM_URL, "alnyan/yggdrasil", false)?;
//
// log::info!("Building openlibm");
//
// 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(())
// }
//
// pub fn build_c(env: &BuildEnv, install: &mut Vec<(PathBuf, PathBuf)>) -> Result<(), Error> {
// let llvm = toolchain_c::install_llvm_compiler(env)?;
// let ygglibc = build_ygglibc(env)?;
// install_ygglibc(env, &ygglibc)?;
//
// toolchain_c::install_compiler_rt(env, &llvm)?;
//
// let libm = build_openlibm(env, &llvm)?;
// install_openlibm(env, &libm)?;
//
// if env.config.components(env).libcxx {
// toolchain_c::install_llvm_cxx_runtime(env, &llvm)?;
// }
//
// build_test_c_program(env, &llvm, install)?;
//
// if env.config.components(env).libcxx {
// build_test_cpp_program(env, &llvm, install)?;
//
// install.push((
// env.llvm_sysroot.join("lib/libc++.so"),
// "lib/libc++.so".into(),
// ));
// }
// install.push((ygglibc.crt0_file, "lib/crt0.o".into()));
// install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
// install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));
//
// Ok(())
// }

View File

@ -16,6 +16,8 @@ pub mod x86_64;
pub mod c;
mod cargo;
pub mod ports;
pub mod ygglibc;
// mod module;
pub mod toolchain;
pub mod toolchain_c;
@ -144,11 +146,7 @@ pub fn check_all(env: BuildEnv, action: CheckAction) -> Result<(), Error> {
}
CargoBuilder::Userspace(&env).run(env.workspace_root.join("userspace"), action)?;
if env.config.components(&env).libc || env.config.components(&env).libcxx {
CargoBuilder::Ygglibc(&env)
.run(env.workspace_root.join("userspace/lib/ygglibc"), action)?;
}
CargoBuilder::Ygglibc(&env).run(env.workspace_root.join("userspace/lib/ygglibc"), action)?;
CargoBuilder::Kernel(&env).run(env.workspace_root.join("kernel"), action)?;

299
xtask/src/build/ports.rs Normal file
View File

@ -0,0 +1,299 @@
use std::{
env, fs,
path::{Path, PathBuf},
process::Command,
};
use dependency_graph::{DependencyGraph, Node, Step};
use serde::Deserialize;
use crate::{
env::BuildEnv,
error::{Error, PortError},
};
use super::ygglibc;
#[derive(Debug, Clone, Copy)]
pub enum BuildStep {
Fetch,
Compile,
Install,
}
#[derive(Debug, Deserialize)]
pub struct PortBuildScripts {
pub fetch: Option<PathBuf>,
pub compile: Option<PathBuf>,
pub install: Option<PathBuf>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "kebab-case")]
pub struct PortDependencies {
pub build: Option<Vec<String>>,
pub runtime: Option<Vec<String>>,
pub c_compiler: Option<bool>,
}
#[derive(Debug, Deserialize)]
pub struct PortManifest {
pub description: String,
pub version: String,
pub dependencies: Option<PortDependencies>,
pub scripts: Option<PortBuildScripts>,
}
#[derive(Debug)]
pub struct NormalPort {
pub package_name: String,
pub manifest: PortManifest,
pub manifest_dir: PathBuf,
pub source_dir: PathBuf,
pub build_dir: PathBuf,
pub all_dependencies: Vec<String>,
}
#[derive(Debug)]
pub enum Port {
Meta(MetaPort),
Normal(NormalPort),
}
#[derive(Debug)]
pub enum MetaPort {
Libc,
}
impl Node for Port {
type DependencyType = String;
fn matches(&self, dependency: &Self::DependencyType) -> bool {
match self {
Self::Meta(MetaPort::Libc) => dependency == "meta-libc",
Self::Normal(port) => port.package_name == *dependency,
}
}
fn dependencies(&self) -> &[Self::DependencyType] {
// build + runtime dependencies
match self {
Self::Meta(MetaPort::Libc) => &[],
Self::Normal(port) => &port.all_dependencies,
}
}
}
impl NormalPort {
pub fn load(env: &BuildEnv, name: &str) -> Result<Self, PortError> {
let manifest_dir = env.workspace_root.join("ports").join(name);
let source_dir = env
.workspace_root
.join("userspace/target/ports")
.join(name)
.join("source");
let build_dir = env
.workspace_root
.join("userspace/target")
.join(env.arch.user_triple())
.join("ports")
.join(name)
.join("build");
let manifest_path = manifest_dir.join("port.toml");
let manifest_text =
fs::read_to_string(&manifest_path).map_err(|e| PortError::ManifestLoadError(e))?;
let manifest: PortManifest =
toml::from_str(&manifest_text).map_err(PortError::ManifestParseError)?;
let all_dependencies = match manifest.dependencies.as_ref() {
Some(deps) => {
let mut d = vec![];
if deps.c_compiler.unwrap_or(true) {
d.push("meta-llvm".into());
}
if let Some(build) = deps.build.as_ref() {
d.extend(build.iter().cloned());
}
if let Some(runtime) = deps.runtime.as_ref() {
d.extend(runtime.iter().cloned());
}
d
}
None => vec!["meta-llvm".into()],
};
Ok(Self {
package_name: name.into(),
manifest_dir,
source_dir,
build_dir,
manifest,
all_dependencies,
})
}
fn run_script<P: AsRef<Path>>(
&self,
env: &BuildEnv,
script: P,
step: BuildStep,
) -> Result<(), PortError> {
// Script arguments:
// * manifest-dir
// * source-dir
// * build-dir
// Script env:
// * Y_WORKSPACE_ROOT=...
// * Y_HOST_PREFIX=...
// * Y_SYSROOT=...
// * Y_PORT_VERSION=...
// * Y_ARCH=...
// * Y_TRIPLE=...
let mut command = Command::new(script.as_ref());
let ports_prefix = env.workspace_root.join("userspace/target/ports-prefix");
command.arg(&self.manifest_dir);
command.arg(&self.source_dir);
command.arg(&self.build_dir);
command.env("Y_WORKSPACE_ROOT", &env.workspace_root);
command.env("Y_SYSROOT", &env.ports_sysroot);
command.env("Y_HOST_PREFIX", &ports_prefix);
command.env("Y_PORT_VERSION", &self.manifest.version);
command.env(
"Y_PORT_UTILS",
&env.workspace_root.join("ports/meta-port-scripts"),
);
command.env("Y_ARCH", env.arch.name());
command.env("Y_TRIPLE", env.arch.user_triple());
if self.package_name != "meta-llvm" && self.package_name != "llvm" {
let path_var = env::var("PATH").unwrap();
let prefix_path = ports_prefix.join("bin");
command.env("PATH", format!("{}:{path_var}", prefix_path.display()));
}
let status = command
.status()
.map_err(|e| PortError::ScriptExecuteError(step, e))?;
if status.success() {
Ok(())
} else {
Err(PortError::ScriptFailed(step, status))
}
}
fn lookup_script<F: Fn(&PortBuildScripts) -> Option<PathBuf>>(
&self,
mapper: F,
fallback: &str,
required: bool,
) -> Result<PathBuf, PortError> {
let script = if let Some(script) = self.manifest.scripts.as_ref().and_then(mapper) {
// Explicit fetch script
if !script.exists() {
return Err(PortError::ScriptNotFound(script));
}
script
} else {
let default = self.manifest_dir.join(fallback);
if required && !default.exists() {
return Err(PortError::ScriptNotFound(fallback.into()));
}
default
};
Ok(script)
}
pub fn run_step(&self, env: &BuildEnv, step: BuildStep) -> Result<(), PortError> {
match step {
BuildStep::Fetch => {
let script =
self.lookup_script(|scripts| scripts.fetch.clone(), "fetch.sh", false)?;
if !script.exists() {
return Ok(());
}
self.run_script(env, script, step)
}
BuildStep::Compile => {
let script =
self.lookup_script(|scripts| scripts.compile.clone(), "compile.sh", true)?;
self.run_script(env, script, step)
}
BuildStep::Install => {
let script =
self.lookup_script(|scripts| scripts.install.clone(), "install.sh", true)?;
self.run_script(env, script, step)
}
}
}
}
impl Port {
pub fn load(env: &BuildEnv, name: &str) -> Result<Self, PortError> {
match name {
"meta-libc" => Ok(Self::Meta(MetaPort::Libc)),
_ => NormalPort::load(env, name).map(Self::Normal),
}
}
pub fn name(&self) -> &str {
match self {
Self::Meta(MetaPort::Libc) => "meta-libc",
Self::Normal(port) => &port.package_name,
}
}
pub fn run_step(&self, env: &BuildEnv, step: BuildStep) -> Result<(), PortError> {
log::info!("{:?}: {step:?}", self.name());
match (self, step) {
(Self::Meta(MetaPort::Libc), BuildStep::Fetch) => Ok(()),
(Self::Meta(MetaPort::Libc), BuildStep::Compile) => {
ygglibc::build_ygglibc(env).map_err(|e| PortError::LibcBuildError(step, e.into()))
}
(Self::Meta(MetaPort::Libc), BuildStep::Install) => {
ygglibc::install_ygglibc(env).map_err(|e| PortError::LibcBuildError(step, e.into()))
}
(Self::Normal(port), step) => port.run_step(env, step),
}
}
}
fn run_step(env: &BuildEnv, ports: &[&Port], step: BuildStep) -> Result<(), Error> {
for port in ports.iter().copied() {
port.run_step(env, step)
.map_err(|e| Error::PortError(port.name().into(), e))?;
}
Ok(())
}
pub fn build_and_install(env: &BuildEnv, ports: Vec<Port>) -> Result<(), Error> {
let graph = DependencyGraph::from(&ports[..]);
let mut to_build = vec![];
let mut unresolved = false;
for entry in graph {
match entry {
Step::Resolved(port) => to_build.push(port),
Step::Unresolved(name) => {
log::error!("Unresolved port: {name:?}");
unresolved = true;
}
}
}
if unresolved {
return Err(Error::PortUnresolvedDependencies);
}
run_step(env, &to_build, BuildStep::Fetch)?;
for port in to_build {
port.run_step(env, BuildStep::Compile)
.map_err(|e| Error::PortError(port.name().into(), e))?;
port.run_step(env, BuildStep::Install)
.map_err(|e| Error::PortError(port.name().into(), e))?;
}
Ok(())
}

View File

@ -1,242 +1,104 @@
use std::{
fs,
path::PathBuf,
process::{Command, Stdio},
};
// use std::{
// fs,
// path::PathBuf,
// process::{Command, Stdio},
// };
//
// use crate::{
// env::BuildEnv,
// error::{CommandExt, Error},
// util,
// };
use crate::{
env::BuildEnv,
error::{CommandExt, Error},
util,
};
pub const LLVM_URL: &str = "https://git.alnyan.me/yggdrasil/llvm-project.git";
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 c_clangpp(&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()));
// TODO: Not yet implemented features:
command.arg("-fno-exceptions");
command.arg("-fno-rtti");
command
}
pub fn clang(&self) -> PathBuf {
self.root.join("bin/clang")
}
}
pub fn install_compiler_rt(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
let build_dir = env.workspace_root.join(format!(
"toolchain-c/llvm-project/build-{}/compiler-rt",
env.arch.name()
));
let makefile = build_dir.join("build.ninja");
let toolchain_cmake = env.workspace_root.join(format!(
"toolchain-c/cmake/toolchain-{}.cmake",
env.arch.name()
));
fs::create_dir_all(&build_dir)?;
if !makefile.exists() {
log::info!("Configure compiler-rt for {}", env.arch.name());
let mut command = Command::new("cmake");
command.current_dir(&build_dir);
command.env("CROSS_TOOLCHAIN_PREFIX", &llvm.root);
command
.arg(format!("--toolchain={}", toolchain_cmake.display()))
.arg("-DCOMPILER_RT_BUILD_BUILTINS=ON")
.arg("-DCOMPILER_RT_BUILD_LIBFUZZER=OFF")
.arg("-DCOMPILER_RT_BUILD_MEMPROF=OFF")
.arg("-DCOMPILER_RT_BUILD_PROFILE=OFF")
.arg("-DCOMPILER_RT_BUILD_CTX_PROFILE=OFF")
.arg("-DCOMPILER_RT_BUILD_SANITIZERS=OFF")
.arg("-DCOMPILER_RT_BUILD_XRAY=OFF")
.arg("-DCOMPILER_RT_BUILD_STANDALONE_LIBATOMIC=ON")
.arg("-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON")
.arg("-DCOMPILER_RT_BAREMETAL_BUILD=ON")
.arg("-DCOMPILER_RT_BUILTINS_ENABLE_PIC=ON")
.arg("-DCOMPILER_RT_BUILTINS_HIDE_SYMBOLS=OFF")
.arg("-DDEFAULT_COMPILER_RT_USE_BUILTINS_LIBRARY=ON")
.arg("-DCMAKE_EXE_LINKER_FLAGS=-nostdlib")
.arg(format!(
"-DLLVM_CMAKE_DIR={}/lib/cmake/llvm",
llvm.root.display()
))
.arg(format!("-DCMAKE_SYSROOT={}", env.llvm_sysroot.display()))
.arg(format!(
"-DCMAKE_INSTALL_PREFIX={}",
env.llvm_sysroot.display()
))
.arg("-GNinja")
.arg("../../compiler-rt");
command.success().map_err(Error::CompilerRtConfigFailed)?;
}
// Build and install compiler-rt
log::info!("Build compiler-rt for {}", env.arch.name());
let mut command = Command::new("cmake");
if !env.verbose {
command.stdout(Stdio::null());
}
command.env("CROSS_TOOLCHAIN_PREFIX", &llvm.root);
command.current_dir(&build_dir);
command
.args(["--build", "."])
.args(["-t install"])
.arg("-j");
command.success().map_err(Error::CompilerRtBuildFailed)?;
Ok(())
}
pub fn install_llvm_cxx_runtime(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
let build_dir = env.workspace_root.join(format!(
"toolchain-c/llvm-project/build-{}/runtimes",
env.arch.name()
));
let makefile = build_dir.join("build.ninja");
let toolchain_cmake = env.workspace_root.join(format!(
"toolchain-c/cmake/toolchain-{}.cmake",
env.arch.name()
));
fs::create_dir_all(&build_dir)?;
if !makefile.exists() {
log::info!("Configure libc++/libc++abi for {}", env.arch.name());
let mut command = Command::new("cmake");
command.current_dir(&build_dir);
command.env("CROSS_TOOLCHAIN_PREFIX", &llvm.root);
command
.arg(format!("--toolchain={}", toolchain_cmake.display()))
.arg("-GNinja")
.arg("-DCMAKE_BUILD_TYPE=Debug")
.arg("-DLLVM_ENABLE_RUNTIMES=libcxxabi;libcxx")
.arg("-DLIBCXXABI_ENABLE_STATIC=ON")
.arg("-DLIBCXXABI_ENABLE_SHARED=OFF")
.arg("-DLIBCXXABI_USE_COMPILER_RT=ON")
.arg("-DLIBCXXABI_ENABLE_THREADS=ON")
.arg("-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF")
.arg("-DLIBCXXABI_USE_LLVM_UNWINDER=OFF")
.arg("-DLIBCXX_CXX_ABI=libcxxabi")
.arg("-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON")
.arg("-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=ON")
.arg("-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON")
.arg("-DLIBCXX_ENABLE_FILESYSTEM=ON")
.arg("-DLIBCXX_ENABLE_THREADS=ON")
.arg("-DLIBCXX_ENABLE_EXCEPTIONS=OFF")
.arg("-DLIBCXX_ENABLE_SHARED=ON")
.arg("-DLIBCXX_ENABLE_STATIC=ON")
.arg("-DLIBCXX_INCLUDE_BENCHMARKS=OFF")
.arg("-DCMAKE_EXE_LINKER_FLAGS=-nostdlib")
.arg(format!(
"-DLLVM_DEFAULT_TARGET_TRIPLE={}-unknown-yggdrasil",
env.arch.name()
))
.arg(format!("-DCMAKE_SYSROOT={}", env.llvm_sysroot.display()))
.arg(format!(
"-DCMAKE_INSTALL_PREFIX={}",
env.llvm_sysroot.display()
))
.arg("../../runtimes");
command.success().map_err(Error::CRuntimeConfigFailed)?;
}
// Build and install libc++/abi
// TODO each rebuild of ygglibc reinstalls headers which triggers libc++ rebuild,
// only copy those if the mtime on ygglibc's headers is newer than whatever's
// present in the sysroot
log::info!("Build libc++/libc++abi for {}", env.arch.name());
let mut command = Command::new("cmake");
if !env.verbose {
command.stdout(Stdio::null());
}
command.env("CROSS_TOOLCHAIN_PREFIX", &llvm.root);
command.current_dir(&build_dir);
command
.args(["--build", "."])
.args(["-t install"])
.arg("-j");
command.success().map_err(Error::CRuntimeBuildFailed)?;
Ok(())
}
pub fn install_llvm_compiler(env: &BuildEnv) -> Result<Llvm, Error> {
let root = env.workspace_root.join("toolchain-c/prefix/host");
let src_dir = env.workspace_root.join("toolchain-c/llvm-project");
let build_dir = src_dir.join("build");
let makefile = build_dir.join("build.ninja");
util::git_clone(&src_dir, LLVM_URL, "alnyan/yggdrasil", true)?;
fs::create_dir_all(&build_dir)?;
// Configure LLVM
// TODO option to force reconfig
if !makefile.exists() {
log::info!("Configure LLVM");
let have_host_ccache = which::which("ccache").is_ok();
let mut command = Command::new("cmake");
command.current_dir(&build_dir);
command
.arg("-DCMAKE_BUILD_TYPE=Release")
.arg("-DCMAKE_C_COMPILER=/usr/bin/clang")
.arg("-DCMAKE_CXX_COMPILER=/usr/bin/clang++")
.arg("-DBUILD_SHARED_LIBS=false")
.arg("-DLLVM_ENABLE_PROJECTS=clang;lld;compiler-rt")
.arg("-DLLVM_USE_LINKER=lld")
.arg("-DLLVM_BUILD_TOOLS=false");
if have_host_ccache {
command.arg("-DLLVM_CCACHE_BUILD=true");
}
command
.arg("-DLLVM_TARGETS_TO_BUILD=X86;AArch64;RISCV")
.arg(&format!("-DCMAKE_INSTALL_PREFIX={}", root.display()))
.arg("-GNinja")
.arg("../llvm");
command.success().map_err(Error::LlvmConfigFailed)?;
}
// Build and install LLVM
log::info!("Build LLVM");
let mut command = Command::new("cmake");
if !env.verbose {
command.stdout(Stdio::null());
}
command.current_dir(&build_dir);
command
.args(["--build", "."])
.args(["-t install"])
.arg("-j");
command.success().map_err(Error::LlvmBuildFailed)?;
Ok(Llvm { root })
}
// pub const LLVM_URL: &str = "https://git.alnyan.me/yggdrasil/llvm-project.git";
//
// 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 c_clangpp(&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()));
// // TODO: Not yet implemented features:
// command.arg("-fno-exceptions");
// command.arg("-fno-rtti");
// command
// }
//
// pub fn clang(&self) -> PathBuf {
// self.root.join("bin/clang")
// }
// }
//
// pub fn install_compiler_rt(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
// }
//
// pub fn install_llvm_cxx_runtime(env: &BuildEnv, llvm: &Llvm) -> Result<(), Error> {
// }
//
// pub fn install_llvm_compiler(env: &BuildEnv) -> Result<Llvm, Error> {
// let root = env.workspace_root.join("toolchain-c/prefix/host");
// let src_dir = env.workspace_root.join("toolchain-c/llvm-project");
// let build_dir = src_dir.join("build");
// let makefile = build_dir.join("build.ninja");
//
// util::git_clone(&src_dir, LLVM_URL, "alnyan/yggdrasil", true)?;
//
// fs::create_dir_all(&build_dir)?;
//
// // Configure LLVM
// // TODO option to force reconfig
// if !makefile.exists() {
// log::info!("Configure LLVM");
//
// let have_host_ccache = which::which("ccache").is_ok();
//
// let mut command = Command::new("cmake");
// command.current_dir(&build_dir);
// command
// .arg("-DCMAKE_BUILD_TYPE=Release")
// .arg("-DCMAKE_C_COMPILER=/usr/bin/clang")
// .arg("-DCMAKE_CXX_COMPILER=/usr/bin/clang++")
// .arg("-DBUILD_SHARED_LIBS=false")
// .arg("-DLLVM_ENABLE_PROJECTS=clang;lld;compiler-rt")
// .arg("-DLLVM_USE_LINKER=lld")
// .arg("-DLLVM_BUILD_TOOLS=false");
//
// if have_host_ccache {
// command.arg("-DLLVM_CCACHE_BUILD=true");
// }
//
// command
// .arg("-DLLVM_TARGETS_TO_BUILD=X86;AArch64;RISCV")
// .arg(&format!("-DCMAKE_INSTALL_PREFIX={}", root.display()))
// .arg("-GNinja")
// .arg("../llvm");
//
// command.success().map_err(Error::LlvmConfigFailed)?;
// }
//
// // Build and install LLVM
// log::info!("Build LLVM");
// let mut command = Command::new("cmake");
// if !env.verbose {
// command.stdout(Stdio::null());
// }
// command.current_dir(&build_dir);
// command
// .args(["--build", "."])
// .args(["-t install"])
// .arg("-j");
//
// command.success().map_err(Error::LlvmBuildFailed)?;
//
// Ok(Llvm { root })
// }

View File

@ -7,7 +7,10 @@ use std::{
use walkdir::WalkDir;
use crate::{
build::{c, cargo::CargoBuilder},
build::{
cargo::CargoBuilder,
ports::{self, Port},
},
check::AllOk,
env::BuildEnv,
error::Error,
@ -78,19 +81,23 @@ const PROGRAMS: &[(&str, &str)] = &[
// TODO: proper process for C program builds
];
fn build_userspace(
env: &BuildEnv,
extra: &mut Vec<(PathBuf, PathBuf)>,
_: AllOk,
) -> Result<(), Error> {
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"))?;
if env.config.components(env).libc || env.config.components(env).libcxx {
c::build_c(env, extra)?;
}
Ok(())
}
fn build_ports(env: &BuildEnv) -> Result<(), Error> {
let ports = env
.config
.components(env)
.ports
.iter()
.map(|port| Port::load(env, port).map_err(|e| Error::PortError(port.clone(), e)))
.collect::<Result<Vec<_>, Error>>()?;
ports::build_and_install(env, ports)?;
Ok(())
}
@ -226,12 +233,13 @@ fn pack_initrd<P: AsRef<Path>>(env: &BuildEnv, rootfs_dir: P) -> Result<InitrdGe
pub fn build_initrd(
env: &BuildEnv,
mut install_extra: Vec<(PathBuf, PathBuf)>,
install_extra: Vec<(PathBuf, PathBuf)>,
check: AllOk,
) -> Result<InitrdGenerated, Error> {
let rootfs_dir = env.userspace_output_dir.join("rootfs");
build_userspace(env, &mut install_extra, check)?;
build_userspace(env, check)?;
build_ports(env)?;
build_rootfs(
env,

View File

@ -0,0 +1,52 @@
use std::fs;
use crate::{env::BuildEnv, error::Error, util};
use super::cargo::CargoBuilder;
pub fn install_ygglibc(env: &BuildEnv) -> Result<(), Error> {
log::info!("Installing ygglibc into ports sysroot");
let dst_lib_dir = env.ports_sysroot.join("lib");
let dst_include_dir = env.ports_sysroot.join("usr/include");
let ygglibc_dir = env.workspace_root.join("userspace/lib/ygglibc");
let ygglibc_output_dir = ygglibc_dir
.join("target")
.join(format!("{}-unknown-none", env.arch.name()))
.join(env.profile.name());
let include_paths = [
ygglibc_output_dir.join("include"),
ygglibc_dir.join("include"),
];
fs::create_dir_all(&dst_lib_dir)?;
fs::create_dir_all(&dst_include_dir)?;
util::copy_file_if(
ygglibc_output_dir.join("libygglibc.a"),
dst_lib_dir.join("libygglibc.a"),
util::is_newer,
)?;
util::copy_file_if(
ygglibc_output_dir.join("libygglibc.so"),
dst_lib_dir.join("libygglibc.so"),
util::is_newer,
)?;
util::copy_file_if(
ygglibc_output_dir.join("crt0.o"),
dst_lib_dir.join("crt0.o"),
util::is_newer,
)?;
for path in include_paths.iter() {
util::copy_dir_recursive_if(path, &dst_include_dir, util::is_newer)?;
}
Ok(())
}
pub fn build_ygglibc(env: &BuildEnv) -> Result<(), Error> {
let ygglibc_dir = env.workspace_root.join("userspace/lib/ygglibc");
CargoBuilder::Ygglibc(env).build(&ygglibc_dir)?;
Ok(())
}

View File

@ -2,6 +2,8 @@ use std::{io, path::PathBuf};
use clap::ValueEnum;
const DEFAULT_PORTS: &[&str] = &["meta-llvm", "meta-libc", "openlibm", "compiler-rt"];
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct ToolchainConfig {
@ -11,9 +13,7 @@ pub struct ToolchainConfig {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[serde(default)]
pub struct BuildComponents {
pub libc: bool,
// Depends on .libc
pub libcxx: bool,
pub ports: Vec<String>,
}
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
@ -109,7 +109,7 @@ pub struct BuildEnv {
pub userspace_output_dir: PathBuf,
pub kernel_symbol_file: PathBuf,
pub llvm_sysroot: PathBuf,
pub ports_sysroot: PathBuf,
}
impl Default for ToolchainConfig {
@ -123,8 +123,7 @@ impl Default for ToolchainConfig {
impl Default for BuildComponents {
fn default() -> Self {
Self {
libc: true,
libcxx: true,
ports: DEFAULT_PORTS.iter().copied().map(String::from).collect(),
}
}
}
@ -165,10 +164,12 @@ 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()
));
let ports_sysroot = workspace_root.join(
workspace_root
.join("userspace/target")
.join(arch.user_triple())
.join("ports-sysroot"),
);
Self {
config,
@ -187,7 +188,7 @@ impl BuildEnv {
kernel_output_dir,
userspace_output_dir,
llvm_sysroot,
ports_sysroot,
}
}

View File

@ -1,10 +1,10 @@
use std::{
io,
path::PathBuf,
process::{Command, ExitStatusError},
process::{Command, ExitStatus, ExitStatusError},
};
use crate::env::Board;
use crate::{build::ports::BuildStep, env::Board};
#[derive(Debug, thiserror::Error)]
pub enum Error {
@ -52,6 +52,27 @@ pub enum Error {
#[error("No qemu support for board {0:?}")]
UnsupportedEmulation(Board),
#[error("Unresolved ports/dependencies")]
PortUnresolvedDependencies,
#[error("Port {0:?} build error: {1}")]
PortError(String, PortError),
}
#[derive(Debug, thiserror::Error)]
pub enum PortError {
#[error("Could not load port manifest: {0}")]
ManifestLoadError(io::Error),
#[error("Invalid port manifest: {0}")]
ManifestParseError(toml::de::Error),
#[error("Step script {0:?} not found")]
ScriptNotFound(PathBuf),
#[error("Step {0:?} script execute error: {1}")]
ScriptExecuteError(BuildStep, io::Error),
#[error("Step {0:?} failed: {1:?}")]
ScriptFailed(BuildStep, ExitStatus),
#[error("ygglibc step {0:?} failed: {1}")]
LibcBuildError(BuildStep, Box<Error>),
}
#[derive(Debug, thiserror::Error)]

View File

@ -30,6 +30,17 @@ pub fn run_external_command<S0: AsRef<OsStr>, S1: AsRef<OsStr>, I: IntoIterator<
}
}
pub fn is_newer(src: &Path, dst: &Path) -> bool {
let (Ok(src), Ok(dst)) = (
src.metadata().and_then(|m| m.modified()),
dst.metadata().and_then(|m| m.modified()),
) else {
return true;
};
src > dst
}
pub fn copy_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<(), Error> {
let src = src.as_ref();
let dst = dst.as_ref();
@ -38,7 +49,25 @@ pub fn copy_file(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> Result<(), Err
.map(|_| ())
}
pub fn copy_dir_recursive<S: AsRef<Path>, D: AsRef<Path>>(src: S, dst: D) -> Result<(), Error> {
pub fn copy_file_if<S: AsRef<Path>, D: AsRef<Path>, P: Fn(&Path, &Path) -> bool>(
src: S,
dst: D,
predicate: P,
) -> Result<(), Error> {
let src = src.as_ref();
let dst = dst.as_ref();
if !dst.exists() || predicate(src, dst) {
log::debug!("Copy {} -> {}", src.display(), dst.display());
copy_file(src, dst)?;
}
Ok(())
}
pub fn copy_dir_recursive_if<S: AsRef<Path>, D: AsRef<Path>, P: Fn(&Path, &Path) -> bool>(
src: S,
dst: D,
predicate: P,
) -> Result<(), Error> {
let src = src.as_ref();
let dst = dst.as_ref();
@ -53,14 +82,17 @@ pub fn copy_dir_recursive<S: AsRef<Path>, D: AsRef<Path>>(src: S, dst: D) -> Res
if entry.file_type().is_dir() {
fs::create_dir_all(dst_path)?;
} else {
log::trace!("Copy {} -> {}", src_path.display(), dst_path.display());
copy_file(src_path, dst_path)?;
copy_file_if(src_path, dst_path, &predicate)?;
}
}
Ok(())
}
pub fn copy_dir_recursive<S: AsRef<Path>, D: AsRef<Path>>(src: S, dst: D) -> Result<(), Error> {
copy_dir_recursive_if(src, dst, |_, _| true)
}
pub fn git_clone(
dst: impl AsRef<Path>,
url: &str,