From 9f2ad4f2c9c7ed5925cc5e50956662db8854ca4b Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Thu, 6 Mar 2025 20:41:16 +0200 Subject: [PATCH] ports: nicer build system for C/C++ ports --- kernel/src/syscall/imp/mod.rs | 21 +- lib/abi/def/yggdrasil.abi | 1 + lib/runtime/src/time.rs | 6 + ports/c-tests/port.toml | 5 + ports/compiler-rt/compile.sh | 35 + ports/compiler-rt/install.sh | 6 + ports/compiler-rt/port.toml | 5 + ports/libc++/compile.sh | 41 + ports/libc++/install.sh | 8 + ports/libc++/port.toml | 5 + ports/llvm/compile.sh | 55 ++ ports/llvm/install.sh | 7 + ports/llvm/port.toml | 5 + ports/meta-llvm/compile.sh | 36 + ports/meta-llvm/fetch.sh | 31 + ports/meta-llvm/install.sh | 10 + ...n-yggdrasil-Yggdrasil-target-support.patch | 622 +++++++++++++++ ...yan-yggdrasil-Yggdrasil-host-support.patch | 739 ++++++++++++++++++ ports/meta-llvm/port.toml | 11 + ports/meta-port-scripts/sig.sh | 11 + .../toolchain-aarch64.cmake | 8 +- .../toolchain-riscv64.cmake | 6 +- .../meta-port-scripts}/toolchain-x86_64.cmake | 6 +- ports/openlibm/compile.sh | 14 + ports/openlibm/fetch.sh | 31 + ports/openlibm/install.sh | 16 + ...il-force-cross-compilation-for-clang.patch | 44 ++ ...nyan-yggdrasil-fix-build-for-aarch64.patch | 34 + ...3-alnyan-yggdrasil-fix-riscv64-build.patch | 38 + .../0004-alnyan-yggdrasil-fix-includes.patch | 91 +++ ports/openlibm/port.toml | 5 + toolchain-c/cmake/toolchain-i686.cmake | 22 - userspace/lib/cross/src/lib.rs | 5 +- userspace/lib/cross/src/sys/yggdrasil/time.rs | 20 +- userspace/lib/cross/src/time.rs | 19 - userspace/lib/ygglibc/build.rs | 17 +- userspace/lib/ygglibc/include/math.h | 2 +- userspace/tools/ntpc/src/main.rs | 23 +- xtask/src/build/c.rs | 455 +++++------ xtask/src/build/mod.rs | 8 +- xtask/src/build/ports.rs | 299 +++++++ xtask/src/build/toolchain_c.rs | 344 +++----- xtask/src/build/userspace.rs | 30 +- xtask/src/build/ygglibc.rs | 52 ++ xtask/src/env.rs | 23 +- xtask/src/error.rs | 25 +- xtask/src/util.rs | 38 +- 47 files changed, 2734 insertions(+), 601 deletions(-) create mode 100644 ports/c-tests/port.toml create mode 100755 ports/compiler-rt/compile.sh create mode 100755 ports/compiler-rt/install.sh create mode 100644 ports/compiler-rt/port.toml create mode 100755 ports/libc++/compile.sh create mode 100755 ports/libc++/install.sh create mode 100644 ports/libc++/port.toml create mode 100755 ports/llvm/compile.sh create mode 100755 ports/llvm/install.sh create mode 100644 ports/llvm/port.toml create mode 100755 ports/meta-llvm/compile.sh create mode 100755 ports/meta-llvm/fetch.sh create mode 100755 ports/meta-llvm/install.sh create mode 100644 ports/meta-llvm/patches/0001-alnyan-yggdrasil-Yggdrasil-target-support.patch create mode 100644 ports/meta-llvm/patches/0002-alnyan-yggdrasil-Yggdrasil-host-support.patch create mode 100644 ports/meta-llvm/port.toml create mode 100644 ports/meta-port-scripts/sig.sh rename {toolchain-c/cmake => ports/meta-port-scripts}/toolchain-aarch64.cmake (67%) rename {toolchain-c/cmake => ports/meta-port-scripts}/toolchain-riscv64.cmake (79%) rename {toolchain-c/cmake => ports/meta-port-scripts}/toolchain-x86_64.cmake (77%) create mode 100755 ports/openlibm/compile.sh create mode 100755 ports/openlibm/fetch.sh create mode 100755 ports/openlibm/install.sh create mode 100644 ports/openlibm/patches/0001-alnyan-yggdrasil-force-cross-compilation-for-clang.patch create mode 100644 ports/openlibm/patches/0002-alnyan-yggdrasil-fix-build-for-aarch64.patch create mode 100644 ports/openlibm/patches/0003-alnyan-yggdrasil-fix-riscv64-build.patch create mode 100644 ports/openlibm/patches/0004-alnyan-yggdrasil-fix-includes.patch create mode 100644 ports/openlibm/port.toml delete mode 100644 toolchain-c/cmake/toolchain-i686.cmake delete mode 100644 userspace/lib/cross/src/time.rs create mode 100644 xtask/src/build/ports.rs create mode 100644 xtask/src/build/ygglibc.rs diff --git a/kernel/src/syscall/imp/mod.rs b/kernel/src/syscall/imp/mod.rs index ce6985cb..1c50431e 100644 --- a/kernel/src/syscall/imp/mod.rs +++ b/kernel/src/syscall/imp/mod.rs @@ -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) -> R Ok(()) } +pub(crate) fn set_clock(ty: ClockType, value: &SystemTime) -> Result<(), Error> { + match ty { + ClockType::RealTime => { + let time = chrono::DateTime::::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 { let option = SystemInfoVariant::try_from(option)?; match option { diff --git a/lib/abi/def/yggdrasil.abi b/lib/abi/def/yggdrasil.abi index 1a33d707..d7c20754 100644 --- a/lib/abi/def/yggdrasil.abi +++ b/lib/abi/def/yggdrasil.abi @@ -74,6 +74,7 @@ enum TraceLevel(u32) { syscall get_random(buffer: &mut [u8]); syscall get_clock(clock: ClockType, out: &mut MaybeUninit) -> 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<()>; diff --git a/lib/runtime/src/time.rs b/lib/runtime/src/time.rs index 7a8c2eea..f2340c39 100644 --- a/lib/runtime/src/time.rs +++ b/lib/runtime/src/time.rs @@ -13,6 +13,12 @@ pub fn get_clock(clock_type: ClockType) -> Result { 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 { diff --git a/ports/c-tests/port.toml b/ports/c-tests/port.toml new file mode 100644 index 00000000..3a645baa --- /dev/null +++ b/ports/c-tests/port.toml @@ -0,0 +1,5 @@ +description = "Test C/C++ programs" +version = "0.0.1" + +[dependencies] +runtime = ["meta-libc", "libc++"] diff --git a/ports/compiler-rt/compile.sh b/ports/compiler-rt/compile.sh new file mode 100755 index 00000000..75cb5a44 --- /dev/null +++ b/ports/compiler-rt/compile.sh @@ -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 diff --git a/ports/compiler-rt/install.sh b/ports/compiler-rt/install.sh new file mode 100755 index 00000000..8bbab6c7 --- /dev/null +++ b/ports/compiler-rt/install.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +build_dir=$3 + +cd $build_dir +cmake --build . -t install -j >/dev/null diff --git a/ports/compiler-rt/port.toml b/ports/compiler-rt/port.toml new file mode 100644 index 00000000..b1bf2722 --- /dev/null +++ b/ports/compiler-rt/port.toml @@ -0,0 +1,5 @@ +description = "LLVM's compiler-rt" +version = "19.1.3" + +[dependencies] +runtime = ["meta-libc"] diff --git a/ports/libc++/compile.sh b/ports/libc++/compile.sh new file mode 100755 index 00000000..e21f7bfe --- /dev/null +++ b/ports/libc++/compile.sh @@ -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 diff --git a/ports/libc++/install.sh b/ports/libc++/install.sh new file mode 100755 index 00000000..5af7aaa4 --- /dev/null +++ b/ports/libc++/install.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +set -e + +build_dir=$3 + +cd $build_dir +cmake --build . -t install -j >/dev/null diff --git a/ports/libc++/port.toml b/ports/libc++/port.toml new file mode 100644 index 00000000..a9f3b7a0 --- /dev/null +++ b/ports/libc++/port.toml @@ -0,0 +1,5 @@ +description = "LLVM's libc++/libc++abi" +version = "19.1.3" + +[dependencies] +runtime = ["meta-llvm", "compiler-rt", "meta-libc", "openlibm"] diff --git a/ports/llvm/compile.sh b/ports/llvm/compile.sh new file mode 100755 index 00000000..3c4d89ff --- /dev/null +++ b/ports/llvm/compile.sh @@ -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 diff --git a/ports/llvm/install.sh b/ports/llvm/install.sh new file mode 100755 index 00000000..85383255 --- /dev/null +++ b/ports/llvm/install.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -e + +build_dir=$3 +cd $build_dir +cmake --build . -t install -j >/dev/null diff --git a/ports/llvm/port.toml b/ports/llvm/port.toml new file mode 100644 index 00000000..14a7b7fe --- /dev/null +++ b/ports/llvm/port.toml @@ -0,0 +1,5 @@ +description = "clang + LLVM tools" +version = "19.1.3" + +[dependencies] +runtime = ["meta-llvm", "compiler-rt", "meta-libc", "openlibm", "libc++"] diff --git a/ports/meta-llvm/compile.sh b/ports/meta-llvm/compile.sh new file mode 100755 index 00000000..84915023 --- /dev/null +++ b/ports/meta-llvm/compile.sh @@ -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 diff --git a/ports/meta-llvm/fetch.sh b/ports/meta-llvm/fetch.sh new file mode 100755 index 00000000..b69309a3 --- /dev/null +++ b/ports/meta-llvm/fetch.sh @@ -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 diff --git a/ports/meta-llvm/install.sh b/ports/meta-llvm/install.sh new file mode 100755 index 00000000..bd3a3dec --- /dev/null +++ b/ports/meta-llvm/install.sh @@ -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 diff --git a/ports/meta-llvm/patches/0001-alnyan-yggdrasil-Yggdrasil-target-support.patch b/ports/meta-llvm/patches/0001-alnyan-yggdrasil-Yggdrasil-target-support.patch new file mode 100644 index 00000000..cf3b4fd6 --- /dev/null +++ b/ports/meta-llvm/patches/0001-alnyan-yggdrasil-Yggdrasil-target-support.patch @@ -0,0 +1,622 @@ +From 0b21467e6102cbad5b7652c06abac42be4cf0a04 Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 AllocateTarget(const llvm::Triple &Triple, + return std::make_unique(Triple, Opts); + + switch (os) { ++ case llvm::Triple::Yggdrasil: ++ return std::make_unique>(Triple, Opts); + case llvm::Triple::FreeBSD: + return std::make_unique>(Triple, + Opts); +@@ -578,6 +580,8 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, + } + case llvm::Triple::Haiku: + return std::make_unique(Triple, Opts); ++ case llvm::Triple::Yggdrasil: ++ return std::make_unique>(Triple, Opts); + case llvm::Triple::RTEMS: + return std::make_unique(Triple, Opts); + case llvm::Triple::NaCl: +@@ -638,6 +642,8 @@ std::unique_ptr AllocateTarget(const llvm::Triple &Triple, + } + case llvm::Triple::Haiku: + return std::make_unique>(Triple, Opts); ++ case llvm::Triple::Yggdrasil: ++ return std::make_unique>(Triple, Opts); + case llvm::Triple::NaCl: + return std::make_unique>(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 ++class LLVM_LIBRARY_VISIBILITY YggdrasilTargetInfo : public OSTargetInfo { ++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(Triple, Opts) { ++ this->WIntType = TargetInfo::UnsignedInt; ++ this->MCountName = "__mcount"; ++ this->HasFloat128 = true; ++ } ++}; ++ + // WebAssembly target + template + 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(*this, Target, Args); + break; ++ case llvm::Triple::Yggdrasil: ++ TC = std::make_unique(*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 ++ ++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(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(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(_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::mask* ctype::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 + diff --git a/ports/meta-llvm/patches/0002-alnyan-yggdrasil-Yggdrasil-host-support.patch b/ports/meta-llvm/patches/0002-alnyan-yggdrasil-Yggdrasil-host-support.patch new file mode 100644 index 00000000..7e1f3152 --- /dev/null +++ b/ports/meta-llvm/patches/0002-alnyan-yggdrasil-Yggdrasil-host-support.patch @@ -0,0 +1,739 @@ +From 05e94c67399dfb7924aa42f1f3f9a820ac1b16e9 Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 AllocateTarget(const llvm::Triple &Triple, + + case llvm::Triple::riscv64: + switch (os) { ++ case llvm::Triple::Yggdrasil: ++ return std::make_unique>(Triple, ++ Opts); + case llvm::Triple::FreeBSD: + return std::make_unique>(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 + #endif + #include +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::compute(FunctionT &F) { + << "\n"); + Compute.run(&F.front()); + ++#if !defined(NDEBUG) + assert(validateTree()); ++#endif + } + + template +@@ -406,7 +408,9 @@ void GenericCycleInfo::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(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(C->getType()); + bool toVec = isa(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 &Cache, ConstantExpr *Expr, + Constant *C) { + if (!Cache.insert(Expr).second) +@@ -498,7 +498,7 @@ static bool contains(Value *Expr, Value *V) { + SmallPtrSet Cache; + return contains(Cache, CE, C); + } +-#endif // NDEBUG ++// #endif // NDEBUG + + void Value::doRAUW(Value *New, ReplaceMetadataUses ReplaceMetaUses) { + assert(New && "Value::replaceAllUsesWith() 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(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 + +-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(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 &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 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 &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®_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 + + // Include the platform-specific parts of this class. +-#ifdef LLVM_ON_UNIX ++#if defined(LLVM_ON_UNIX) || defined(__yggdrasil__) + #include "Unix/Host.inc" + #include + #endif +-- +2.48.1 + diff --git a/ports/meta-llvm/port.toml b/ports/meta-llvm/port.toml new file mode 100644 index 00000000..aacc842f --- /dev/null +++ b/ports/meta-llvm/port.toml @@ -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 diff --git a/ports/meta-port-scripts/sig.sh b/ports/meta-port-scripts/sig.sh new file mode 100644 index 00000000..bc487216 --- /dev/null +++ b/ports/meta-port-scripts/sig.sh @@ -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 +} diff --git a/toolchain-c/cmake/toolchain-aarch64.cmake b/ports/meta-port-scripts/toolchain-aarch64.cmake similarity index 67% rename from toolchain-c/cmake/toolchain-aarch64.cmake rename to ports/meta-port-scripts/toolchain-aarch64.cmake index 79592d4e..5a9fd805 100644 --- a/toolchain-c/cmake/toolchain-aarch64.cmake +++ b/ports/meta-port-scripts/toolchain-aarch64.cmake @@ -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 diff --git a/toolchain-c/cmake/toolchain-riscv64.cmake b/ports/meta-port-scripts/toolchain-riscv64.cmake similarity index 79% rename from toolchain-c/cmake/toolchain-riscv64.cmake rename to ports/meta-port-scripts/toolchain-riscv64.cmake index 6d6a0025..44a8d88d 100644 --- a/toolchain-c/cmake/toolchain-riscv64.cmake +++ b/ports/meta-port-scripts/toolchain-riscv64.cmake @@ -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") diff --git a/toolchain-c/cmake/toolchain-x86_64.cmake b/ports/meta-port-scripts/toolchain-x86_64.cmake similarity index 77% rename from toolchain-c/cmake/toolchain-x86_64.cmake rename to ports/meta-port-scripts/toolchain-x86_64.cmake index 67a25a13..6551db3a 100644 --- a/toolchain-c/cmake/toolchain-x86_64.cmake +++ b/ports/meta-port-scripts/toolchain-x86_64.cmake @@ -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") diff --git a/ports/openlibm/compile.sh b/ports/openlibm/compile.sh new file mode 100755 index 00000000..000243e4 --- /dev/null +++ b/ports/openlibm/compile.sh @@ -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 diff --git a/ports/openlibm/fetch.sh b/ports/openlibm/fetch.sh new file mode 100755 index 00000000..2a0914d5 --- /dev/null +++ b/ports/openlibm/fetch.sh @@ -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 diff --git a/ports/openlibm/install.sh b/ports/openlibm/install.sh new file mode 100755 index 00000000..aefed09b --- /dev/null +++ b/ports/openlibm/install.sh @@ -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 diff --git a/ports/openlibm/patches/0001-alnyan-yggdrasil-force-cross-compilation-for-clang.patch b/ports/openlibm/patches/0001-alnyan-yggdrasil-force-cross-compilation-for-clang.patch new file mode 100644 index 00000000..a1870045 --- /dev/null +++ b/ports/openlibm/patches/0001-alnyan-yggdrasil-force-cross-compilation-for-clang.patch @@ -0,0 +1,44 @@ +From 8840f9fe4825e5ad30e54477bfffc1c6750e3d61 Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 + diff --git a/ports/openlibm/patches/0002-alnyan-yggdrasil-fix-build-for-aarch64.patch b/ports/openlibm/patches/0002-alnyan-yggdrasil-fix-build-for-aarch64.patch new file mode 100644 index 00000000..0fc708ee --- /dev/null +++ b/ports/openlibm/patches/0002-alnyan-yggdrasil-fix-build-for-aarch64.patch @@ -0,0 +1,34 @@ +From 42f9cd9675361c51b8d32eef6cbc59ac6fd55755 Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 + diff --git a/ports/openlibm/patches/0003-alnyan-yggdrasil-fix-riscv64-build.patch b/ports/openlibm/patches/0003-alnyan-yggdrasil-fix-riscv64-build.patch new file mode 100644 index 00000000..48e79ef4 --- /dev/null +++ b/ports/openlibm/patches/0003-alnyan-yggdrasil-fix-riscv64-build.patch @@ -0,0 +1,38 @@ +From 4413af583b2bff5e9da46ef7cbf168bfa1c9947e Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 + diff --git a/ports/openlibm/patches/0004-alnyan-yggdrasil-fix-includes.patch b/ports/openlibm/patches/0004-alnyan-yggdrasil-fix-includes.patch new file mode 100644 index 00000000..f7b07e60 --- /dev/null +++ b/ports/openlibm/patches/0004-alnyan-yggdrasil-fix-includes.patch @@ -0,0 +1,91 @@ +From 2d97808b68f81bc35ea4688e625222d5215305ae Mon Sep 17 00:00:00 2001 +From: Mark Poliakov +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 +-#include +-#include ++#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 ++#include "openlibm_fenv_arm.h" + #elif defined(__x86_64__) +-#include ++#include "openlibm_fenv_amd64.h" + #elif defined(__i386__) +-#include ++#include "openlibm_fenv_i387.h" + #elif defined(__powerpc__) || defined(__POWERPC__) +-#include ++#include "openlibm_fenv_powerpc.h" + #elif defined(__mips__) +-#include ++#include "openlibm_fenv_mips.h" + #elif defined(__s390__) +-#include ++#include "openlibm_fenv_s390.h" + #elif defined(__riscv) +-#include ++#include "openlibm_fenv_riscv.h" + #elif defined(__loongarch64) +-#include ++#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 ++#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 + #else /* !OPENLIBM_USE_HOST_MATH_H */ + +-#include ++#include "openlibm_defs.h" + + #ifndef OPENLIBM_MATH_H + #define OPENLIBM_MATH_H +-- +2.48.1 + diff --git a/ports/openlibm/port.toml b/ports/openlibm/port.toml new file mode 100644 index 00000000..578bb634 --- /dev/null +++ b/ports/openlibm/port.toml @@ -0,0 +1,5 @@ +description = "" +version = "0.8.4" + +[dependencies] +runtime = ["meta-libc", "compiler-rt"] diff --git a/toolchain-c/cmake/toolchain-i686.cmake b/toolchain-c/cmake/toolchain-i686.cmake deleted file mode 100644 index 9b435ad7..00000000 --- a/toolchain-c/cmake/toolchain-i686.cmake +++ /dev/null @@ -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 diff --git a/userspace/lib/cross/src/lib.rs b/userspace/lib/cross/src/lib.rs index 142cab29..cb7aa6a7 100644 --- a/userspace/lib/cross/src/lib.rs +++ b/userspace/lib/cross/src/lib.rs @@ -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; +} diff --git a/userspace/lib/cross/src/sys/yggdrasil/time.rs b/userspace/lib/cross/src/sys/yggdrasil/time.rs index b5ae496e..02048c83 100644 --- a/userspace/lib/cross/src/sys/yggdrasil/time.rs +++ b/userspace/lib/cross/src/sys/yggdrasil/time.rs @@ -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(()) } diff --git a/userspace/lib/cross/src/time.rs b/userspace/lib/cross/src/time.rs deleted file mode 100644 index 3f8b5151..00000000 --- a/userspace/lib/cross/src/time.rs +++ /dev/null @@ -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) - } -} diff --git a/userspace/lib/ygglibc/build.rs b/userspace/lib/ygglibc/build.rs index 069ac9cb..4b695ba3 100644 --- a/userspace/lib/ygglibc/build.rs +++ b/userspace/lib/ygglibc/build.rs @@ -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, data: &[u8]) -> bool { + let content = fs::read(path).unwrap(); + content == data +} + fn generate_header(config_path: impl AsRef, header_output: impl AsRef) { 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, header_output: impl AsRef) { @@ -96,7 +110,6 @@ fn compile_crt0(arch: &str, output_dir: impl AsRef) { _ => (), } - command .arg("-o") .arg(output_dir.join("crt0.o")) diff --git a/userspace/lib/ygglibc/include/math.h b/userspace/lib/ygglibc/include/math.h index af1fd9c8..fc8f6b48 100644 --- a/userspace/lib/ygglibc/include/math.h +++ b/userspace/lib/ygglibc/include/math.h @@ -1,4 +1,4 @@ -#include +#include typedef float float_t; typedef double double_t; diff --git a/userspace/tools/ntpc/src/main.rs b/userspace/tools/ntpc/src/main.rs index a7a00dfd..14266a17 100644 --- a/userspace/tools/ntpc/src/main.rs +++ b/userspace/tools/ntpc/src/main.rs @@ -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) -> Result<(), Error> { - if args.interval.is_none() { - println!("{time}"); - } else { - log::info!("{time}"); - } +fn handle_time(time: DateTime) -> 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(()) } diff --git a/xtask/src/build/c.rs b/xtask/src/build/c.rs index 7348c883..ee6b379d 100644 --- a/xtask/src/build/c.rs +++ b/xtask/src/build/c.rs @@ -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, -} - -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 { - 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 { - 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, +// } +// +// 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 { +// 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(()) +// } diff --git a/xtask/src/build/mod.rs b/xtask/src/build/mod.rs index f65131b1..00d4d18f 100644 --- a/xtask/src/build/mod.rs +++ b/xtask/src/build/mod.rs @@ -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)?; diff --git a/xtask/src/build/ports.rs b/xtask/src/build/ports.rs new file mode 100644 index 00000000..ac7503bb --- /dev/null +++ b/xtask/src/build/ports.rs @@ -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, + pub compile: Option, + pub install: Option, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "kebab-case")] +pub struct PortDependencies { + pub build: Option>, + pub runtime: Option>, + pub c_compiler: Option, +} + +#[derive(Debug, Deserialize)] +pub struct PortManifest { + pub description: String, + pub version: String, + pub dependencies: Option, + pub scripts: Option, +} + +#[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, +} + +#[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 { + 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>( + &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 Option>( + &self, + mapper: F, + fallback: &str, + required: bool, + ) -> Result { + 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 { + 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) -> 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(()) +} diff --git a/xtask/src/build/toolchain_c.rs b/xtask/src/build/toolchain_c.rs index 8ea3f55a..ecbf5877 100644 --- a/xtask/src/build/toolchain_c.rs +++ b/xtask/src/build/toolchain_c.rs @@ -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 { - 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 { +// 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 }) +// } diff --git a/xtask/src/build/userspace.rs b/xtask/src/build/userspace.rs index 81f8a76d..00d648e5 100644 --- a/xtask/src/build/userspace.rs +++ b/xtask/src/build/userspace.rs @@ -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::, Error>>()?; + ports::build_and_install(env, ports)?; Ok(()) } @@ -226,12 +233,13 @@ fn pack_initrd>(env: &BuildEnv, rootfs_dir: P) -> Result, + install_extra: Vec<(PathBuf, PathBuf)>, check: AllOk, ) -> Result { 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, diff --git a/xtask/src/build/ygglibc.rs b/xtask/src/build/ygglibc.rs new file mode 100644 index 00000000..9b2e7fe7 --- /dev/null +++ b/xtask/src/build/ygglibc.rs @@ -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(()) +} diff --git a/xtask/src/env.rs b/xtask/src/env.rs index 74b7e510..64341449 100644 --- a/xtask/src/env.rs +++ b/xtask/src/env.rs @@ -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, } #[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, } } diff --git a/xtask/src/error.rs b/xtask/src/error.rs index 307847a6..7b0c40b8 100644 --- a/xtask/src/error.rs +++ b/xtask/src/error.rs @@ -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), } #[derive(Debug, thiserror::Error)] diff --git a/xtask/src/util.rs b/xtask/src/util.rs index 4fa699de..4a708a4e 100644 --- a/xtask/src/util.rs +++ b/xtask/src/util.rs @@ -30,6 +30,17 @@ pub fn run_external_command, S1: AsRef, 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, dst: impl AsRef) -> Result<(), Error> { let src = src.as_ref(); let dst = dst.as_ref(); @@ -38,7 +49,25 @@ pub fn copy_file(src: impl AsRef, dst: impl AsRef) -> Result<(), Err .map(|_| ()) } -pub fn copy_dir_recursive, D: AsRef>(src: S, dst: D) -> Result<(), Error> { +pub fn copy_file_if, D: AsRef, 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, D: AsRef, 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, D: AsRef>(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, D: AsRef>(src: S, dst: D) -> Result<(), Error> { + copy_dir_recursive_if(src, dst, |_, _| true) +} + pub fn git_clone( dst: impl AsRef, url: &str,