| # Copyright 2020 The Chromium OS Authors. All rights reserved. |
| # Distributed under the terms of the GNU General Public License v2 |
| |
| # Bootstraps rustc (the official Rust compiler) using mrustc (a Rust |
| # compiler written in C++). |
| # |
| # The version of this ebuild reflects the version of rustc that will |
| # ultimately be installed. |
| # |
| # This ebuild can be used in two modes, controlled by the fullbootstrap |
| # USE flag: |
| # |
| # fullbootstrap: Build everything from source. This can take over |
| # 10 hours. |
| # |
| # -fullbootstrap: Start with a prebuilt from an earlier rust-bootstrap |
| # and build only versions after that from source. |
| # |
| # The default is -fullbootstrap, so that you only get the 10+ hour build |
| # time if you explicitly request it. |
| |
| EAPI=7 |
| |
| inherit toolchain-funcs |
| |
| DESCRIPTION="Bootstraps the rustc Rust compiler using mrustc" |
| HOMEPAGE="https://github.com/thepowersgang/mrustc" |
| MRUSTC_VERSION="0.9" |
| MRUSTC_NAME="mrustc-${MRUSTC_VERSION}" |
| |
| SLOT="0" |
| KEYWORDS="*" |
| IUSE="-fullbootstrap" |
| |
| INITIAL_RUSTC_VERSION="1.29.0" |
| # Versions of rustc to build after the initial one. |
| RUSTC_FULL_BOOTSTRAP_SEQUENCE=( |
| 1.30.0 |
| 1.31.1 |
| 1.32.0 |
| 1.33.0 |
| 1.34.2 |
| 1.35.0 |
| 1.36.0 |
| 1.37.0 |
| 1.38.0 |
| 1.39.0 |
| 1.40.0 |
| 1.41.1 |
| 1.42.0 |
| 1.43.1 |
| 1.44.1 |
| 1.45.2 |
| ) |
| # When not using fullbootstrap, use this version as a starting point. |
| PREBUILT_VERSION="${RUSTC_FULL_BOOTSTRAP_SEQUENCE[-1]}" |
| SRC_URI="gs://chromeos-localmirror/distfiles/rustc-${PV}-src.tar.gz |
| !fullbootstrap? ( gs://chromeos-localmirror/distfiles/rust-bootstrap-${PREBUILT_VERSION}.tbz2 ) |
| fullbootstrap? ( gs://chromeos-localmirror/distfiles/${MRUSTC_NAME}.tar.gz ) |
| fullbootstrap? ( gs://chromeos-localmirror/distfiles/rustc-${INITIAL_RUSTC_VERSION}-src.tar.gz )" |
| for version in "${RUSTC_FULL_BOOTSTRAP_SEQUENCE[@]}"; do |
| SRC_URI+=" fullbootstrap? ( gs://chromeos-localmirror/distfiles/rustc-${version}-src.tar.gz )" |
| done |
| |
| LICENSE="MIT Apache-2.0 BSD-1 BSD-2 BSD-4 UoI-NCSA" |
| |
| DEPEND="dev-libs/openssl |
| net-libs/libssh2" |
| RDEPEND="${DEPEND}" |
| |
| # These tasks take a long time to run for not much benefit: Most of the files |
| # they check are never installed. Those that are are only there to bootstrap |
| # the rust ebuild, which has the same RESTRICT anyway. |
| RESTRICT="binchecks strip" |
| |
| pkg_setup() { |
| if use fullbootstrap; then |
| RUSTC_VERSION_SEQUENCE=( "${RUSTC_FULL_BOOTSTRAP_SEQUENCE[@]}" ) |
| PATCHES=( |
| "${FILESDIR}/${P}-no-curl.patch" |
| "${FILESDIR}/${P}-compilation-fixes.patch" |
| "${FILESDIR}/${P}-8ddb05-invalid-output-constraint.patch" |
| "${FILESDIR}/${P}-libgit2-sys-pkg-config.patch" |
| "${FILESDIR}/${P}-cc.patch" |
| "${FILESDIR}/${P}-printf.patch" |
| "${FILESDIR}/${P}-libc++.patch" |
| ) |
| S="${WORKDIR}/${MRUSTC_NAME}" |
| else |
| RUSTC_VERSION_SEQUENCE=( ) |
| # We manually apply patches to rustcs in the version sequence, |
| # so that we can pass the necessary -p value. To prevent |
| # default from trying and failing to apply patches, we set |
| # PATCHES to empty. |
| PATCHES=( ) |
| S="${WORKDIR}/rustc-${PV}-src" |
| fi |
| RUSTC_VERSION_SEQUENCE+=( ${PV} ) |
| } |
| |
| src_unpack() { |
| default |
| if use fullbootstrap; then |
| # Move rustc sources to where mrustc expects them. |
| mv "${WORKDIR}/rustc-${INITIAL_RUSTC_VERSION}-src" "${S}" || die |
| fi |
| } |
| |
| src_prepare() { |
| # Call the default implementation. This applies PATCHES. |
| default |
| |
| if use fullbootstrap; then |
| |
| # The next few steps mirror what mrustc's Makefile does to configure the |
| # build for a specific rustc version. |
| (cd "rustc-${INITIAL_RUSTC_VERSION}-src" || die; eapply -p0 "${S}/rustc-${INITIAL_RUSTC_VERSION}-src.patch") |
| cd "${S}" || die |
| echo "${INITIAL_RUSTC_VERSION}" > "rust-version" || die |
| cp "rust-version" "rustc-${INITIAL_RUSTC_VERSION}-src/dl-version" || die |
| fi |
| |
| # There are some patches that need to be applied to the rustc versions |
| # we build with rustc. Apply them here. |
| local version |
| for version in "${RUSTC_VERSION_SEQUENCE[@]}"; do |
| einfo "Patching rustc-${version}" |
| (cd "${WORKDIR}/rustc-${version}-src" || die; eapply -p2 "${FILESDIR}/${P}-libc++.patch") |
| done |
| } |
| |
| src_configure() { |
| # Avoid the default implementation, which overwrites vendored |
| # config.guess and config.sub files, which then causes checksum |
| # errors during the build, e.g. |
| # error: the listed checksum of `/var/tmp/portage/dev-lang/rust-bootstrap-1.46.0/work/rustc-1.46.0-src/vendor/backtrace-sys/src/libbacktrace/config.guess` has changed: |
| # expected: 12e217c83267f1ff4bad5d9b2b847032d91e89ec957deb34ec8cb5cef00eba1e |
| # actual: 312ea023101dc1de54aa8c50ed0e82cb9c47276316033475ea403cb86fe88ffe |
| # (The dev-lang/rust ebuilds in Chrome OS and Gentoo also have custom |
| # src_configure implementations.) |
| true |
| } |
| |
| src_compile() { |
| # 1. Build initial rustc using mrustc |
| # ----------------------------------- |
| # |
| # All of these specify: |
| # - CC and CXX so that we build with Clang instead of a GCC version that defaults to pre-C99 C. |
| # - LLVM_TARGETS, else it will be empty and rustc will not work. |
| # - RUSTC_VERSION because the Makefiles will otherwise set it to an incorrect value. |
| # - OPENSSL_DIR so that cargo knows where to look for OpenSSL headers. |
| export CC=$(tc-getBUILD_CC) |
| export CXX=$(tc-getBUILD_CXX) |
| export PKG_CONFIG=$(tc-getBUILD_PKG_CONFIG) |
| export OPENSSL_DIR="${ESYSROOT}/usr" |
| # Only actually build mrustc when using fullbootstrap. |
| if use fullbootstrap; then |
| # Two separate commands, because invoking just the second command leads to race |
| # conditions. |
| emake LLVM_TARGETS=X86 RUSTC_VERSION=${INITIAL_RUSTC_VERSION} output/rustc output/cargo |
| emake LLVM_TARGETS=X86 RUSTC_VERSION=${INITIAL_RUSTC_VERSION} -C run_rustc |
| fi |
| |
| # 2. Build successive versions of rustc using previous rustc |
| # ---------------------------------------------------------- |
| if use fullbootstrap; then |
| local prev_version=${INITIAL_RUSTC_VERSION} |
| local prev_cargo="${S}/run_rustc/output/prefix/bin/cargo" |
| local prev_rustc="${S}/run_rustc/output/prefix/bin/rustc" |
| else |
| local prev_version=${PREBUILT_VERSION} |
| local prev_cargo="${WORKDIR}/opt/rust-bootstrap-${PREBUILT_VERSION}/bin/cargo" |
| local prev_rustc="${WORKDIR}/opt/rust-bootstrap-${PREBUILT_VERSION}/bin/rustc" |
| fi |
| local next_version rustc_dir |
| for next_version in "${RUSTC_VERSION_SEQUENCE[@]}"; do |
| einfo "Building rustc-${next_version} using rustc-${prev_version}" |
| rustc_dir="${WORKDIR}/rustc-${next_version}-src" |
| cd "${rustc_dir}" || die "Could not chdir to ${rustc_dir}" |
| cat > config.toml <<EOF |
| [build] |
| cargo = "${prev_cargo}" |
| rustc = "${prev_rustc}" |
| docs = false |
| vendor = true |
| # extended means we also build cargo and a few other commands. |
| extended = true |
| |
| [install] |
| prefix = "${ED}/opt/rust-bootstrap-${next_version}" |
| |
| [rust] |
| default-linker = "${CC}" |
| |
| [target.x86_64-unknown-linux-gnu] |
| cc = "${CC}" |
| cxx = "${CXX}" |
| linker = "${CC}" |
| EOF |
| |
| # --stage 2 causes this to use the previously-built compiler, |
| # instead of the default behavior of downloading one from |
| # upstream. |
| ./x.py --stage 2 build || die |
| # For some rustc versions (e.g. 1.31.1), the build script will exit with |
| # a nonzero exit status because miri fails to build when it is not in a git |
| # repository. This does not affect the ability to build the next rustc. |
| # So instead of looking at the exit code, we check if rustc and cargo |
| # were built. |
| prev_version=${next_version} |
| prev_cargo="${rustc_dir}/build/x86_64-unknown-linux-gnu/stage2-tools/x86_64-unknown-linux-gnu/release/cargo" |
| prev_rustc="${rustc_dir}/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" |
| [[ -x "${prev_rustc}" ]] || die "Failed to build ${prev_rustc}" |
| [[ -x "${prev_cargo}" ]] || die "Failed to build ${prev_cargo}" |
| einfo "Built rustc-${next_version}" |
| done |
| |
| # Remove the src/rust symlink which will be dangling after sources are |
| # removed, and the containing src directory. |
| rm "${WORKDIR}/rustc-${PV}-src/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/src/rust" || die |
| rmdir "${WORKDIR}/rustc-${PV}-src/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/src" || die |
| } |
| |
| src_install() { |
| local obj="${WORKDIR}/rustc-${PV}-src/build/x86_64-unknown-linux-gnu/stage2" |
| local tools="${obj}-tools/x86_64-unknown-linux-gnu/release/" |
| exeinto "/opt/${P}/bin" |
| # With rustc-1.45.2 at least, regardless of the value of install.libdir, |
| # the rpath seems to end up as $ORIGIN/../lib. So install the libraries there. |
| insinto "/opt/${P}/lib" |
| doexe "${obj}/bin/rustc" |
| doexe "${tools}/cargo" |
| doins -r "${obj}/lib/"* |
| find "${D}" -name '*.so' -exec chmod +x '{}' ';' |
| } |