diff options
| author | bjorn3 <bjorn3@users.noreply.github.com> | 2018-12-14 13:58:33 +0100 |
|---|---|---|
| committer | bjorn3 <bjorn3@users.noreply.github.com> | 2018-12-15 16:18:03 +0100 |
| commit | 1e5c6bc5b86c4ff61ef3de63a9748789d5b369b0 (patch) | |
| tree | 3b534c853745f053ca9557e3da48922b91466c20 /build_sysroot | |
| parent | 9351f1d0c7763ee8564e096eaa3ed607f089e5db (diff) | |
| download | rust-1e5c6bc5b86c4ff61ef3de63a9748789d5b369b0.tar.gz rust-1e5c6bc5b86c4ff61ef3de63a9748789d5b369b0.zip | |
Stop using xargo for building the sysroot
It is currently broken. (see https://github.com/japaric/xargo/issues/227) This makes it easier to for example patch whole crates away.
Diffstat (limited to 'build_sysroot')
| -rw-r--r-- | build_sysroot/Cargo.toml | 15 | ||||
| -rw-r--r-- | build_sysroot/alloc_system/Cargo.toml | 13 | ||||
| -rw-r--r-- | build_sysroot/alloc_system/lib.rs | 365 | ||||
| -rwxr-xr-x | build_sysroot/build_sysroot.sh | 33 | ||||
| -rw-r--r-- | build_sysroot/compiler_builtins/Cargo.toml | 20 | ||||
| -rw-r--r-- | build_sysroot/compiler_builtins/lib.rs | 3 | ||||
| -rwxr-xr-x | build_sysroot/prepare_sysroot_src.sh | 31 | ||||
| -rw-r--r-- | build_sysroot/src/lib.rs | 1 |
8 files changed, 481 insertions, 0 deletions
diff --git a/build_sysroot/Cargo.toml b/build_sysroot/Cargo.toml new file mode 100644 index 00000000000..d4873602d4d --- /dev/null +++ b/build_sysroot/Cargo.toml @@ -0,0 +1,15 @@ +[package] +authors = ["bjorn3 <bjorn3@users.noreply.github.com>"] +name = "sysroot" +version = "0.0.0" + +[dependencies] +core = { path = "./sysroot_src/src/libcore" } +compiler_builtins = "0.1" +alloc = { path = "./sysroot_src/src/liballoc" } + +alloc_system = { path = "./alloc_system" } + +[patch.crates-io] +rustc-std-workspace-core = { path = "./sysroot_src/src/tools/rustc-std-workspace-core" } +compiler_builtins = { path = "./compiler_builtins" } diff --git a/build_sysroot/alloc_system/Cargo.toml b/build_sysroot/alloc_system/Cargo.toml new file mode 100644 index 00000000000..221faab32bd --- /dev/null +++ b/build_sysroot/alloc_system/Cargo.toml @@ -0,0 +1,13 @@ +[package] +authors = ["The Rust Project Developers", "bjorn3 (edited to be usable outside the rust source)"] +name = "alloc_system" +version = "0.0.0" +[lib] +name = "alloc_system" +path = "lib.rs" +test = false +doc = false +[dependencies] +core = { path = "../sysroot_src/src/libcore" } +libc = { version = "0.2.43", features = ['rustc-dep-of-std'], default-features = false } +compiler_builtins = "0.1" diff --git a/build_sysroot/alloc_system/lib.rs b/build_sysroot/alloc_system/lib.rs new file mode 100644 index 00000000000..74b52a6497e --- /dev/null +++ b/build_sysroot/alloc_system/lib.rs @@ -0,0 +1,365 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +#![no_std] +#![allow(unused_attributes)] +#![unstable(feature = "alloc_system", + reason = "this library is unlikely to be stabilized in its current \ + form or name", + issue = "32838")] +#![feature(allocator_api)] +#![feature(core_intrinsics)] +#![feature(nll)] +#![feature(staged_api)] +#![feature(rustc_attrs)] +#![cfg_attr( + all(target_arch = "wasm32", not(target_os = "emscripten")), + feature(integer_atomics, stdsimd) +)] +#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))] +#![rustc_alloc_kind = "lib"] +// The minimum alignment guaranteed by the architecture. This value is used to +// add fast paths for low alignment values. +#[cfg(all(any(target_arch = "x86", + target_arch = "arm", + target_arch = "mips", + target_arch = "powerpc", + target_arch = "powerpc64", + target_arch = "asmjs", + target_arch = "wasm32")))] +#[allow(dead_code)] +const MIN_ALIGN: usize = 8; +#[cfg(all(any(target_arch = "x86_64", + target_arch = "aarch64", + target_arch = "mips64", + target_arch = "s390x", + target_arch = "sparc64")))] +#[allow(dead_code)] +const MIN_ALIGN: usize = 16; +use core::alloc::{Alloc, GlobalAlloc, AllocErr, Layout}; +use core::ptr::NonNull; +/// The default memory allocator provided by the operating system. +/// +/// This is based on `malloc` on Unix platforms and `HeapAlloc` on Windows, +/// plus related functions. +/// +/// This type can be used in a `static` item +/// with the `#[global_allocator]` attribute +/// to force the global allocator to be the system’s one. +/// (The default is jemalloc for executables, on some platforms.) +/// +/// ```rust +/// use std::alloc::System; +/// +/// #[global_allocator] +/// static A: System = System; +/// +/// fn main() { +/// let a = Box::new(4); // Allocates from the system allocator. +/// println!("{}", a); +/// } +/// ``` +/// +/// It can also be used directly to allocate memory +/// independently of the standard library’s global allocator. +#[stable(feature = "alloc_system_type", since = "1.28.0")] +pub struct System; +#[unstable(feature = "allocator_api", issue = "32838")] +unsafe impl Alloc for System { + #[inline] + unsafe fn alloc(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { + NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) + } + #[inline] + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<NonNull<u8>, AllocErr> { + NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) + } + #[inline] + unsafe fn dealloc(&mut self, ptr: NonNull<u8>, layout: Layout) { + GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + } + #[inline] + unsafe fn realloc(&mut self, + ptr: NonNull<u8>, + layout: Layout, + new_size: usize) -> Result<NonNull<u8>, AllocErr> { + NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + } +} +#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))] +mod realloc_fallback { + use core::alloc::{GlobalAlloc, Layout}; + use core::cmp; + use core::ptr; + impl super::System { + pub(crate) unsafe fn realloc_fallback(&self, ptr: *mut u8, old_layout: Layout, + new_size: usize) -> *mut u8 { + // Docs for GlobalAlloc::realloc require this to be valid: + let new_layout = Layout::from_size_align_unchecked(new_size, old_layout.align()); + let new_ptr = GlobalAlloc::alloc(self, new_layout); + if !new_ptr.is_null() { + let size = cmp::min(old_layout.size(), new_size); + ptr::copy_nonoverlapping(ptr, new_ptr, size); + GlobalAlloc::dealloc(self, ptr, old_layout); + } + new_ptr + } + } +} +#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))] +mod platform { + extern crate libc; + use core::ptr; + use MIN_ALIGN; + use System; + use core::alloc::{GlobalAlloc, Layout}; + #[stable(feature = "alloc_system_type", since = "1.28.0")] + unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::malloc(layout.size()) as *mut u8 + } else { + #[cfg(target_os = "macos")] + { + if layout.align() > (1 << 31) { + return ptr::null_mut() + } + } + aligned_malloc(&layout) + } + } + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { + libc::calloc(layout.size(), 1) as *mut u8 + } else { + let ptr = self.alloc(layout.clone()); + if !ptr.is_null() { + ptr::write_bytes(ptr, 0, layout.size()); + } + ptr + } + } + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + libc::free(ptr as *mut libc::c_void) + } + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN && layout.align() <= new_size { + libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 + } else { + self.realloc_fallback(ptr, layout, new_size) + } + } + } + #[cfg(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris"))] + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(layout.align(), layout.size()) as *mut u8 + } + #[cfg(not(any(target_os = "android", + target_os = "hermit", + target_os = "redox", + target_os = "solaris")))] + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + let mut out = ptr::null_mut(); + let ret = libc::posix_memalign(&mut out, layout.align(), layout.size()); + if ret != 0 { + ptr::null_mut() + } else { + out as *mut u8 + } + } +} +#[cfg(windows)] +#[allow(nonstandard_style)] +mod platform { + use MIN_ALIGN; + use System; + use core::alloc::{GlobalAlloc, Layout}; + type LPVOID = *mut u8; + type HANDLE = LPVOID; + type SIZE_T = usize; + type DWORD = u32; + type BOOL = i32; + extern "system" { + fn GetProcessHeap() -> HANDLE; + fn HeapAlloc(hHeap: HANDLE, dwFlags: DWORD, dwBytes: SIZE_T) -> LPVOID; + fn HeapReAlloc(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID, dwBytes: SIZE_T) -> LPVOID; + fn HeapFree(hHeap: HANDLE, dwFlags: DWORD, lpMem: LPVOID) -> BOOL; + fn GetLastError() -> DWORD; + } + #[repr(C)] + struct Header(*mut u8); + const HEAP_ZERO_MEMORY: DWORD = 0x00000008; + unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header { + &mut *(ptr as *mut Header).offset(-1) + } + unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 { + let aligned = ptr.add(align - (ptr as usize & (align - 1))); + *get_header(aligned) = Header(ptr); + aligned + } + #[inline] + unsafe fn allocate_with_flags(layout: Layout, flags: DWORD) -> *mut u8 { + let ptr = if layout.align() <= MIN_ALIGN { + HeapAlloc(GetProcessHeap(), flags, layout.size()) + } else { + let size = layout.size() + layout.align(); + let ptr = HeapAlloc(GetProcessHeap(), flags, size); + if ptr.is_null() { + ptr + } else { + align_ptr(ptr, layout.align()) + } + }; + ptr as *mut u8 + } + #[stable(feature = "alloc_system_type", since = "1.28.0")] + unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, 0) + } + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + allocate_with_flags(layout, HEAP_ZERO_MEMORY) + } + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + if layout.align() <= MIN_ALIGN { + let err = HeapFree(GetProcessHeap(), 0, ptr as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } else { + let header = get_header(ptr); + let err = HeapFree(GetProcessHeap(), 0, header.0 as LPVOID); + debug_assert!(err != 0, "Failed to free heap memory: {}", + GetLastError()); + } + } + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + if layout.align() <= MIN_ALIGN { + HeapReAlloc(GetProcessHeap(), 0, ptr as LPVOID, new_size) as *mut u8 + } else { + self.realloc_fallback(ptr, layout, new_size) + } + } + } +} +// This is an implementation of a global allocator on the wasm32 platform when +// emscripten is not in use. In that situation there's no actual runtime for us +// to lean on for allocation, so instead we provide our own! +// +// The wasm32 instruction set has two instructions for getting the current +// amount of memory and growing the amount of memory. These instructions are the +// foundation on which we're able to build an allocator, so we do so! Note that +// the instructions are also pretty "global" and this is the "global" allocator +// after all! +// +// The current allocator here is the `dlmalloc` crate which we've got included +// in the rust-lang/rust repository as a submodule. The crate is a port of +// dlmalloc.c from C to Rust and is basically just so we can have "pure Rust" +// for now which is currently technically required (can't link with C yet). +// +// The crate itself provides a global allocator which on wasm has no +// synchronization as there are no threads! +#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))] +mod platform { + extern crate dlmalloc; + use core::alloc::{GlobalAlloc, Layout}; + use System; + static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::DLMALLOC_INIT; + #[stable(feature = "alloc_system_type", since = "1.28.0")] + unsafe impl GlobalAlloc for System { + #[inline] + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.malloc(layout.size(), layout.align()) + } + #[inline] + unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.calloc(layout.size(), layout.align()) + } + #[inline] + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + let _lock = lock::lock(); + DLMALLOC.free(ptr, layout.size(), layout.align()) + } + #[inline] + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let _lock = lock::lock(); + DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) + } + } + #[cfg(target_feature = "atomics")] + mod lock { + use core::arch::wasm32; + use core::sync::atomic::{AtomicI32, Ordering::SeqCst}; + static LOCKED: AtomicI32 = AtomicI32::new(0); + pub struct DropLock; + pub fn lock() -> DropLock { + loop { + if LOCKED.swap(1, SeqCst) == 0 { + return DropLock + } + unsafe { + let r = wasm32::atomic::wait_i32( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // expected value + -1, // timeout + ); + debug_assert!(r == 0 || r == 1); + } + } + } + impl Drop for DropLock { + fn drop(&mut self) { + let r = LOCKED.swap(0, SeqCst); + debug_assert_eq!(r, 1); + unsafe { + wasm32::atomic::wake( + &LOCKED as *const AtomicI32 as *mut i32, + 1, // only one thread + ); + } + } + } + } + #[cfg(not(target_feature = "atomics"))] + mod lock { + #[inline] + pub fn lock() {} // no atomics, no threads, that's easy! + } +} diff --git a/build_sysroot/build_sysroot.sh b/build_sysroot/build_sysroot.sh new file mode 100755 index 00000000000..38608e02163 --- /dev/null +++ b/build_sysroot/build_sysroot.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e +cd $(dirname "$0") + +# Cleanup for previous run +cargo clean +rm Cargo.lock 2>/dev/null || true +rm -r sysroot 2>/dev/null || true + +# FIXME find a better way to get the target triple +unamestr=`uname` +if [[ "$unamestr" == 'Linux' ]]; then + TARGET_TRIPLE='x86_64-unknown-linux-gnu' +elif [[ "$unamestr" == 'Darwin' ]]; then + TARGET_TRIPLE='x86_64-apple-darwin' +else + echo "Unsupported os" + exit 1 +fi + +# Build libs +export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked --sysroot ../" +if [[ "$1" == "--release" ]]; then + channel='release' + RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release +else + channel='debug' + cargo build --target $TARGET_TRIPLE +fi + +# Copy files to sysroot +mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ +cp target/$TARGET_TRIPLE/$channel/deps/*.rlib sysroot/lib/rustlib/$TARGET_TRIPLE/lib/ diff --git a/build_sysroot/compiler_builtins/Cargo.toml b/build_sysroot/compiler_builtins/Cargo.toml new file mode 100644 index 00000000000..724a637a201 --- /dev/null +++ b/build_sysroot/compiler_builtins/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "compiler_builtins" +# Make sure the `compiler_builtins` from crates.io doesn't take precedence over this +# replacement by specifying a higher version than the one on crates.io. +version = "0.1.100" +authors = ["bjorn3 <bjorn3@users.noreply.github.com>"] +edition = "2018" + +[lib] +name = "compiler_builtins" +path = "lib.rs" +test = false +doc = false + +[dependencies] +core = { path = "../sysroot_src/src/libcore" } + +[features] +rustc-dep-of-std = [] +c = [] diff --git a/build_sysroot/compiler_builtins/lib.rs b/build_sysroot/compiler_builtins/lib.rs new file mode 100644 index 00000000000..90a118deeef --- /dev/null +++ b/build_sysroot/compiler_builtins/lib.rs @@ -0,0 +1,3 @@ +#![feature(compiler_builtins)] +#![compiler_builtins] +#![no_std] diff --git a/build_sysroot/prepare_sysroot_src.sh b/build_sysroot/prepare_sysroot_src.sh new file mode 100755 index 00000000000..fceccdb4dea --- /dev/null +++ b/build_sysroot/prepare_sysroot_src.sh @@ -0,0 +1,31 @@ +#!/bin/bash +set -e +cd $(dirname "$0") + +SRC_DIR=$(dirname $(rustup which rustc))"/../lib/rustlib/src/rust/" +DST_DIR="sysroot_src" + +if [ ! -e $SRC_DIR ]; then + echo "Please install rust-src component" + exit 1 +fi + +rm -rf $DST_DIR +mkdir -p $DST_DIR/src +cp -r $SRC_DIR/src $DST_DIR/ + +pushd $DST_DIR +echo "[GIT] init" +git init +echo "[GIT] add" +git add . +echo "[GIT] commit" +git commit -m "Initial commit" -q +for file in $(ls ../../patches/ | grep -v patcha); do +echo "[GIT] apply" $file +git apply ../../patches/$file +git commit -am "Patch $file" +done +popd + +echo "Successfully prepared libcore for building" diff --git a/build_sysroot/src/lib.rs b/build_sysroot/src/lib.rs new file mode 100644 index 00000000000..0c9ac1ac8e4 --- /dev/null +++ b/build_sysroot/src/lib.rs @@ -0,0 +1 @@ +#![no_std] |
