Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash -ex
- # Fetch the old CHOST from make.conf or profile.
- OLD_CHOST=$(portageq envvar CHOST)
- # The new CHOST needs to end in hf. The vendor part doesn't really
- # matter as long as it's not softfloat or softfp but the convention is
- # to replace hardfloat with unknown.
- CHOST=${OLD_CHOST/-hardfloat-/-unknown-}hf
- if [[ ${OLD_CHOST} == *hf ]]; then
- echo "You already have the new *hf CHOST? Either you've already successful run this or you're doing something crazy."
- exit 1
- fi
- # This function is used to skip parts of this script if it is being
- # retried following a failure. It checks whether the given atom has
- # been built against the new CHOST.
- atom_new_chost() {
- local path=${VDB}/${1}/CHOST
- [[ ! -f ${path} ]] && return 1
- [[ $(cat "${path}") == ${CHOST} ]]
- }
- # This script supports prefixed systems.
- EPREFIX=$(portageq envvar EPREFIX)
- # The VDB path is needed for atom_new_chost above.
- VDB=$(portageq vdb_path)
- # Fetch the old profile and convert to the new profile. The new
- # profile may already be selected if this script is being retried so
- # convert both ways just in case. Note that some profiles like
- # hardened are not versioned so these will not change. That is okay.
- OLD_PROFILE=$(eselect --brief profile show)
- OLD_PROFILE=${OLD_PROFILE/17.0/13.0}
- NEW_PROFILE=${OLD_PROFILE/13.0/17.0}
- # What are the latest binutils and gcc versions we can install?
- BINUTILS_PF=$(portageq best_visible "${EPREFIX}"/ sys-devel/binutils)
- GCC_PF=$(portageq best_visible "${EPREFIX}"/ sys-devel/gcc)
- # We need the new binutils and gcc SLOTs for some operations below.
- BINUTILS_SLOT=$(portageq metadata "${EPREFIX}"/ ebuild "${BINUTILS_PF}" SLOT)
- GCC_SLOT=$(portageq metadata "${EPREFIX}"/ ebuild "${GCC_PF}" SLOT)
- # What libc does this profile use, what is the latest we can install?
- LIBC=$(portageq expand_virtual "${EPREFIX}"/ virtual/libc)
- LIBC_PF=$(portageq best_visible "${EPREFIX}"/ "${LIBC}")
- # What are the latest libtool and perl versions we can install?
- LIBTOOL_PF=$(portageq best_visible "${EPREFIX}"/ sys-devel/libtool)
- PERL_PF=$(portageq best_visible "${EPREFIX}"/ dev-lang/perl)
- # Ensure portage, sandbox, and portage-utils are up to date. Older
- # sandbox can block newer libtool. portage-utils is needed for qfile.
- emerge -v1u sys-apps/portage sys-apps/sandbox app-portage/portage-utils
- # Backup the old toolchain, just in case.
- atom_new_chost "${BINUTILS_PF}" ||
- quickpkg sys-devel/binutils sys-devel/gcc "${LIBC}"
- # Select the new profile.
- eselect profile set ${NEW_PROFILE}
- # If we modify make.conf with the new CHOST now then we won't be able
- # to reliably determine the old CHOST when retrying this script. Just
- # override with this variable and modify make.conf at the end.
- export CHOST
- # Build binutils with the new CHOST.
- atom_new_chost "${BINUTILS_PF}" ||
- emerge -v1 "=${BINUTILS_PF}"
- # Remove old binutils versions to avoid a mix-up.
- ! emerge -C "<${BINUTILS_PF}"
- # Explicitly select the newly built binutils.
- binutils-config "${CHOST}-${BINUTILS_SLOT}"
- # Build gcc with the new CHOST.
- atom_new_chost "${GCC_PF}" ||
- emerge -v1 "=${GCC_PF}"
- # Remove old gcc versions to avoid a mix-up.
- ! emerge -C "<${GCC_PF}"
- # Explicitly select the newly built gcc.
- gcc-config -f "${CHOST}-${GCC_SLOT}"
- # Delete old CHOST files from env.d.
- find "${EPREFIX}"/etc/env.d/ -regex ".*\\b${OLD_CHOST}\\b.*" -exec rm -v {} +
- # Delete old CHOST files from ld.so.conf.d, which may not exist.
- [[ -d "${EPREFIX}"/etc/ld.so.conf.d ]] &&
- find "${EPREFIX}"/etc/ld.so.conf.d/ -regex ".*\\b${OLD_CHOST}\\b.*" -exec rm -v {} +
- # Refresh the environment.
- env-update
- source "${EPREFIX}"/etc/profile
- ldconfig
- # Build libc with the new CHOST.
- atom_new_chost "${LIBC_PF}" ||
- emerge -v1 "=${LIBC_PF}"
- # Rebuild libtool and binutils as required for a PIE migration.
- if ! atom_new_chost "${LIBTOOL_PF}"; then
- emerge -v1 "=${BINUTILS_PF}"
- emerge -v1 "=${LIBTOOL_PF}"
- fi
- # fix_libtool_files.sh is sometimes needed after changing CHOST.
- "${EPREFIX}"/usr/share/gcc-data/"${CHOST}/${GCC_SLOT}"/fix_libtool_files.sh "${GCC_SLOT}" --oldarch "${OLD_CHOST}"
- # Delete any orphaned files under /usr/bin that are prefixed with the
- # old CHOST. This is mainly to clean up files created by gcc-config.
- qfile -o "${EPREFIX}"/usr/bin/"${OLD_CHOST}"-* | xargs rm -vf
- # Rename any remaining files under /usr/bin that are prefixed with the
- # old CHOST so that they now have the new CHOST instead.
- find "${EPREFIX}"/usr/bin -name "${OLD_CHOST}-*" -execdir sh -c "X='{}'; mv -v \"\${X}\" \"\${X/${OLD_CHOST}/${CHOST}}\"" \;
- # The previous operation will have broken symlinks such as xml2-config
- # so replace the old CHOST with the new CHOST in such symlinks.
- find "${EPREFIX}"/usr/bin -lname "${OLD_CHOST}-*" -execdir sh -c "X='{}'; ln -snfv \"${CHOST}-\${X##*/}\" \"\${X}\"" \;
- # Safely delete broken symlinks and empty directories from the old
- # toolchain including the main top-level directory, if possible.
- ! find "${EPREFIX}/usr/${OLD_CHOST}"/ -xtype l -delete
- ! find "${EPREFIX}/usr/${OLD_CHOST}"/ -type d -empty -delete
- # Update make.conf with the new CHOST. We do this before rebuilding
- # Perl below because Perl is a prime candidate for package blockers,
- # which you are free to resolve manually at this point.
- sed -i "/CHOST=/s/${OLD_CHOST}/${CHOST}/" "${EPREFIX}"/etc/portage/make.conf
- # Perl is sensitive to a CHOST change so rebuild.
- if portageq has_version "${EPREFIX}"/ dev-lang/perl && ! atom_new_chost "${PERL_PF}"; then
- emerge -v1 "=${PERL_PF}"
- fi
- echo "All done! :)"
- [[ -d "${EPREFIX}/usr/${OLD_CHOST}" ]] &&
- echo "Tried to delete ${EPREFIX}/usr/${OLD_CHOST} but it wasn't empty. Please check and delete it manually."
Add Comment
Please, Sign In to add comment