diff --git a/.github/workflows/crossdev.yml b/.github/workflows/crossdev.yml new file mode 100644 index 0000000..0ef1838 --- /dev/null +++ b/.github/workflows/crossdev.yml @@ -0,0 +1,53 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + schedule: + - cron: 00 4 * * * + +jobs: + crossdev: + strategy: + matrix: + include: + # `target` is the cross target. + # `stage3` is the host stage3. + - target: aarch64-unknown-linux-musl + stage3: musl-llvm + args: --llvm + name: crossdev target=${{ matrix.target }} stage3=${{ matrix.stage3 }} + runs-on: ubuntu-latest + container: docker.io/gentoo/stage3:${{ matrix.stage3 }} + steps: + - uses: actions/checkout@v4 + + - name: Install dependencies + run: | + # FIXME: Uncomment + # emerge --sync --quiet + emerge \ + app-eselect/eselect-repository \ + sys-apps/config-site + + # FIXME: Remove this step once necessary changes are merged. + - name: Use patched overlay + run: | + curl -L \ + https://github.com/vadorovsky/gentoo/archive/refs/heads/cross-llvm.tar.gz | \ + tar -xz + + - name: Install crossdev + run: make install + + - name: Create cross environment + run: crossdev ${{ matrix.args }} --target ${{ matrix.target }} + + # zstd and its dependencies need both C and C++ toolchain. If any of them + # is broken, the installation will fail. + - name: Sanity check + run: ${{ matrix.target }}-emerge app-arch/zstd diff --git a/crossdev b/crossdev index 176bb71..2f534e1 100755 --- a/crossdev +++ b/crossdev @@ -873,6 +873,9 @@ KCAT="sys-kernel" ; KPKG="linux-headers" ; KVER="" KUSE="" KENV="" KOVL="" KMASK LCAT="sys-libs" ; LPKG="[none]" ; LVER="" LUSE="" LENV="" LOVL="" LMASK="" LFORCE="" DCAT="dev-debug" ; DPKG="gdb" ; DVER="" DUSE="" DENV="" DOVL="" DMASK="" DFORCE="" RCAT="sys-libs" ; RPKG="compiler-rt" ; RVER="" RUSE="" RENV="" ROVL="" RMASK="" RFORCE="" +UCAT="sys-libs" ; UPKG="llvm-libunwind" ; UVER="" UUSE="" UENV="" UOVL="" UMASK="" UFORCE="" +ACAT="sys-libs" ; APKG="libcxxabi" ; AVER="" AUSE="" AENV="" AOVL="" AMASK="" AFORCE="" +CXCAT="sys-libs" ; CXPKG="libcxx" ; CXVER="" CXUSE="" CXENV="" CXOVL="" CXMASK="" CXFORCE="" CCAT="sys-devel" ; CPKG="clang-crossdev-wrappers" ; CVER="" CUSE="" CENV="" COVL="" CMASK="" CFORCE="" XPKGS=() XVERS=() XUSES=() XENVS=() XOVLS=() XMASKS=() XFORCES=() DEFAULT_VER="[latest]" @@ -915,69 +918,84 @@ LLVM="no" while [[ $# -gt 0 ]] ; do case $1 in - -V|--version) echo "crossdev-${CROSSDEV_VER}"; exit 0;; - -t|--target) shift; parse_target $1;; - --b|--binutils) shift; BVER=$1;; - --benv) shift; BENV=$1;; - -ob|--ov-binutils) shift; BOVL=$1;; - --bcat) shift; BCAT=$1;; - --bpkg) shift; BPKG=$1;; - --d|--gdb) shift; DVER=$1;; - --denv) shift; DENV=$1;; - -od|--ov-gdb) shift; DOVL=$1;; - --dcat) shift; DCAT=$1;; - --dpkg) shift; DPKG=$1;; - --g|--gcc) shift; GVER=$1;; - --genv) shift; GENV=$1;; - -og|--ov-gcc) shift; GOVL=$1;; - --gcat) shift; GCAT=$1;; - --gpkg) shift; GPKG=$1;; - --k|--kernel) shift; KVER=$1;; - --kenv) shift; KENV=$1;; - -ok|--ov-kernel) shift; KOVL=$1;; - --kcat) shift; KCAT=$1;; - --kpkg) shift; KPKG=$1;; - --l|--libc) shift; LVER=$1;; - --lenv) shift; LENV=$1;; - -ol|--ov-libc) shift; LOVL=$1;; - --lcat) shift; LCAT=$1;; - --lpkg) shift; LPKG=$1;; - --r|--crt) shift; RVER=$1;; - --renv) shift; RENV=$1;; - -or|--ov-crt) shift; ROVL=$1;; - --rcat) shift; RCAT=$1;; - --rpkg) shift; RPKG=$1;; - --c|--ccw) shift; CVER=$1;; - --cenv) shift; CENV=$1;; - -oc|--ov-ccw) shift; COVL=$1;; - --ccat) shift; CCAT=$1;; - --cpkg) shift; CPKG=$1;; - -ox|--ov-extra) shift; XOVLS+=( "$1" );; - --env) shift; AENV=$1;; - -L|--llvm) LLVM="yes";; - -A|--abis) shift; MULTILIB_ABIS=$1;; - --host-abi) shift; HOST_ABI=$1;; - -S|--stable) DEFAULT_VER="[stable]";; - -C|--clean) shift; parse_target $1; ACTION="uninstall";; - -s?|--stage?) STAGE=${1:0-1};; - -oS|--overlays) shift; SEARCH_OVERLAYS=$1;; - -oO|--ov-output) shift; CROSSDEV_OVERLAY=$1;; - --ex-only) EX_FAST="yes";; - --ex-gcc) EX_GCC="yes";; - --ex-gdb) EX_GDB="yes";; - --ex-pkg) shift; XPKGS+=( "$1" );; - --with-*) eval $(set_withval $1);; - --without-*) eval $(set_withval $1);; - -f|--force) FORCE="yes";; - -x) SET_X="yes";; - --show-target-cfg) SHOW_TARGET_CFG="yes";; - --init-target) INIT_TARGET_ONLY="yes";; - --show-fail-log) SHOW_FAIL_LOG="yes";; - --show-repo-cfg) show_repo_cfg "$2";; - -P|--portage) UOPTS="${UOPTS} $2"; shift;; - -h|--help) usage;; - -*) eerror "UNKNOWN OPTION: '$1'" ; usage 1;; - *) parse_target $1;; + -V|--version) echo "crossdev-${CROSSDEV_VER}"; exit 0;; + -t|--target) shift; parse_target $1;; + --b|--binutils) shift; BVER=$1;; + --benv) shift; BENV=$1;; + -ob|--ov-binutils) shift; BOVL=$1;; + --bcat) shift; BCAT=$1;; + --bpkg) shift; BPKG=$1;; + --d|--gdb) shift; DVER=$1;; + --denv) shift; DENV=$1;; + -od|--ov-gdb) shift; DOVL=$1;; + --dcat) shift; DCAT=$1;; + --dpkg) shift; DPKG=$1;; + --g|--gcc) shift; GVER=$1;; + --genv) shift; GENV=$1;; + -og|--ov-gcc) shift; GOVL=$1;; + --gcat) shift; GCAT=$1;; + --gpkg) shift; GPKG=$1;; + --k|--kernel) shift; KVER=$1;; + --kenv) shift; KENV=$1;; + -ok|--ov-kernel) shift; KOVL=$1;; + --kcat) shift; KCAT=$1;; + --kpkg) shift; KPKG=$1;; + --l|--libc) shift; LVER=$1;; + --lenv) shift; LENV=$1;; + -ol|--ov-libc) shift; LOVL=$1;; + --lcat) shift; LCAT=$1;; + --lpkg) shift; LPKG=$1;; + --r|--crt) shift; RVER=$1;; + --renv) shift; RENV=$1;; + -or|--ov-crt) shift; ROVL=$1;; + --rcat) shift; RCAT=$1;; + --rpkg) shift; RPKG=$1;; + --u|--libunwind) shift; UVER=$1;; + --uenv) shift; UENV=$1;; + -ou|--ov-libuinwind) shift; UOVL=$1;; + --ucat) shift; UCAT=$1;; + --upkg) shift; UPKG=$1;; + --a|--libcxxabi) shift; AVER=$1;; + --aenv) shift; AENV=$1;; + -oa|--ov--libcxxabi) shift; AOVL=$1;; + --acat) shift; ACAT=$1;; + --apkg) shift; APKG=$1;; + --cx|--libcxx) shift; CXVER=$1;; + --cxenv) shift; CXENV=$1;; + -ocx|--ov-libcxx) shift; CXOVL=$1;; + --cxcat) shift; CXCAT=$1;; + --cxpkg) shift; CXPKG=$1;; + --c|--ccw) shift; CVER=$1;; + --cenv) shift; CENV=$1;; + -oc|--ov-ccw) shift; COVL=$1;; + --ccat) shift; CCAT=$1;; + --cpkg) shift; CPKG=$1;; + -ox|--ov-extra) shift; XOVLS+=( "$1" );; + --env) shift; AENV=$1;; + -L|--llvm) LLVM="yes";; + -A|--abis) shift; MULTILIB_ABIS=$1;; + --host-abi) shift; HOST_ABI=$1;; + -S|--stable) DEFAULT_VER="[stable]";; + -C|--clean) shift; parse_target $1; ACTION="uninstall";; + -s?|--stage?) STAGE=${1:0-1};; + -oS|--overlays) shift; SEARCH_OVERLAYS=$1;; + -oO|--ov-output) shift; CROSSDEV_OVERLAY=$1;; + --ex-only) EX_FAST="yes";; + --ex-gcc) EX_GCC="yes";; + --ex-gdb) EX_GDB="yes";; + --ex-pkg) shift; XPKGS+=( "$1" );; + --with-*) eval $(set_withval $1);; + --without-*) eval $(set_withval $1);; + -f|--force) FORCE="yes";; + -x) SET_X="yes";; + --show-target-cfg) SHOW_TARGET_CFG="yes";; + --init-target) INIT_TARGET_ONLY="yes";; + --show-fail-log) SHOW_FAIL_LOG="yes";; + --show-repo-cfg) show_repo_cfg "$2";; + -P|--portage) UOPTS="${UOPTS} $2"; shift;; + -h|--help) usage;; + -*) eerror "UNKNOWN OPTION: '$1'" ; usage 1;; + *) parse_target $1;; esac shift done @@ -985,8 +1003,6 @@ done if [[ "${LLVM}" == "yes" ]] ; then WITH_HEADERS="yes" CROSSDEV_OVERLAY_CATEGORY_PREFIX="cross_llvm-" - # To avoid bug reports - [[ "${LPKG}" == "glibc" ]] && die "LLVM/Clang cannot currently compile glibc" fi CROSSDEV_OVERLAY_CATEGORY="${CROSSDEV_OVERLAY_CATEGORY_PREFIX}${CTARGET}" @@ -1001,6 +1017,10 @@ GVER=${GVER:-${DEFAULT_VER}} KVER=${KVER:-${DEFAULT_VER}} LVER=${LVER:-${DEFAULT_VER}} DVER=${DVER:-${DEFAULT_VER}} +RVER=${RVER:-${DEFAULT_VER}} +AVER=${AVER:-${DEFAULT_VER}} +CXVER=${CXVER:-${DEFAULT_VER}} +UVER=${UVER:-${DEFAULT_VER}} STAGE=${STAGE:-${STAGE_DEFAULT}} [[ -z ${CTARGET} ]] && usage 1 for with in HEADERS ; do @@ -1017,8 +1037,6 @@ if [[ ${LPKG} == "newlib" && ${LVER} == "[stable]" ]]; then LVER="[latest]" fi -RVER="[latest]" - show_target_cfg() { local pkgs crosspkgs=() @@ -1180,6 +1198,9 @@ fi info() { hr - [[ "${LLVM}" == "yes" ]] && einfo "Using LLVM/Clang as cross compiler, experimental!" +if [[ "${LLVM}" == "yes" && "${CTARGET}" == *-gnu* ]] ; then + einfo "Using GCC as a fallback compiler for glibc." +fi einfo "crossdev version: ${CROSSDEV_VER}" einfo "Host Portage ARCH: ${HARCH}" einfo "Host Portage System: ${HCHOST} (${HCHOSTS[*]})" @@ -1192,12 +1213,15 @@ einfo "Target ABIs: ${MULTILIB_ABIS}${def_out}" echo ex_fast || { is_s0 && { -[[ "${LLVM}" == "yes" ]] || einfo "binutils: `pretty_atom ${BPKG}- ${BVER}`" + if [[ "${LLVM}" != "yes" || "${CTARGET}" == *-gnu* ]] ; then + einfo "binutils: `pretty_atom ${BPKG}- ${BVER}`" + fi } is_s1 && { if [[ "${LLVM}" == "yes" ]] ; then einfo "compiler-rt: `pretty_atom ${RPKG}- ${RVER}`" - else + fi + if [[ "${LLVM}" != "yes" || "${CTARGET}" == *-gnu* ]] ; then einfo "gcc: `pretty_atom ${GPKG}- ${GVER}`" fi } @@ -1208,6 +1232,12 @@ einfo "headers: `pretty_atom ${KPKG}- ${KVER}`" is_s3 && { einfo "libc: `pretty_atom ${LPKG}- ${LVER}`" } +is_s4 && { +[[ "${LLVM}" == "yes" ]] && \ +einfo "llvm-libunwind: `pretty_atom ${UPKG}- ${UVER}`" +einfo "libcxxabi: `pretty_atom ${APKG}- ${AVER}`" +einfo "libcxx: `pretty_atom ${CXPKG}- ${CXVER}`" +} } ex_gcc && { einfo "Extra: gcc pass: DO IT" @@ -1397,7 +1427,12 @@ set_env() { output=$(_set_portage_file ${pkg} package.env) echo "${CROSSDEV_OVERLAY_CATEGORY}/${pkg} ${CROSSDEV_OVERLAY_CATEGORY}/${pkg}.conf" >> ${output} - [[ "${LLVM}" == "yes" ]] && echo "${CROSSDEV_OVERLAY_CATEGORY}/${pkg} ${CROSSDEV_OVERLAY_CATEGORY}/llvm.conf" >> ${output} + + # If LLVM is the main toolchain, use the generic LLVM environment for all + # packages except gcc and glibc. + if [[ "${LLVM}" == "yes" && ! "${pkg}" =~ (binutils|gcc|glibc) ]] ; then + echo "${CROSSDEV_OVERLAY_CATEGORY}/${pkg} ${CROSSDEV_OVERLAY_CATEGORY}/llvm.conf" >> ${output} + fi } set_portage() { local l=$1 @@ -1548,7 +1583,11 @@ done pkglist=( K L ) if [[ ${LLVM} == "yes" ]] ; then - pkglist+=( R C ) + pkglist+=( R C A CX U ) + # Install GCC as a fallback compiler for GNU environments. + if [[ ${CTARGET} == *-gnu* ]] ; then + pkglist+=( B G ) + fi else pkglist+=( B G D ) fi @@ -1584,9 +1623,11 @@ LLVM="${LLVM}" emerge-wrapper --target ${CTARGET} --init || exit 1 ### but gcc relies on their presence by refering to =/lib64 as ### =/usr/lib/../lib64 when builds itself (see https://bugs.gentoo.org/652724) ### -### Thus we create non-symlinked layout early. -xmkdir -p "${EPREFIX}"/usr/${CTARGET}/lib +### Thus we create the layout early. xmkdir -p "${EPREFIX}"/usr/${CTARGET}/usr/lib +pushd "${EPREFIX}"/usr/${CTARGET} >/dev/null +ln -s usr/lib lib +popd >/dev/null ### ### We need some special riscv sauce here similar as in baselayout. Ugly. ### step 1: set up all multilib libdirs @@ -1736,8 +1777,7 @@ if [[ "${LLVM}" == "yes" ]]; then --rtlib=compiler-rt --sysroot=/usr/${CTARGET} --target=${CTARGET} - --unwindlib=libunwind - --stdlib=libc++ + --unwindlib=none -fuse-ld=lld EOF # Workaround until LLVM libc supports dynamic linking and SSP @@ -1752,7 +1792,7 @@ USE="${USE} -selinux" if ! ex_fast ; then - # stage 0: binutils + # stage 0: compiler wrappers, binutils if [[ "${LLVM}" == "yes" ]] ; then if ! portageq has_version / "sys-devel/llvm" ; then eerror "LLVM is not installed" @@ -1785,13 +1825,25 @@ if ! ex_fast ; then [[ ${supported_arch} -eq 0 ]] && die "Target architecture not supported by installed LLVM toolchain" USE="${CUSE}" doemerge ${CPKG} - else + fi + if [[ "${LLVM}" != "yes" || "${CTARGET}" == *-gnu* ]]; then USE="${BUSE}" doemerge ${BPKG} fi # stage1: bare C compiler if is_s1 ; then + # Build stage1 GCC if: + # + # - It's the main compiler. + # - LLVM is the main compiler, but in GNU environment, so GCC is needed as a + # fallback compiler for glibc. + if [[ "${LLVM}" != "yes" || "${CTARGET}" == *-gnu* ]]; then + USE="${GUSE} ${USE} ${GUSE_DISABLE_STAGE_1}" \ + CROSSCOMPILE_OPTS="" \ + doemerge ${GPKG} ${GPKG}-stage1 + fi + # first install headers if requested if with_headers ; then # install kernel headers (since the C library often uses them) @@ -1811,16 +1863,11 @@ if ! ex_fast ; then fi fi - # then finally get around to the C compiler if [[ "${LLVM}" == "yes" ]]; then # Compile compiler-rt USE="${RUSE} ${USE}" \ CROSSCOMPILE_OPTS="" \ doemerge ${RPKG} - else - USE="${GUSE} ${USE} ${GUSE_DISABLE_STAGE_1}" \ - CROSSCOMPILE_OPTS="" \ - doemerge ${GPKG} ${GPKG}-stage1 fi fi @@ -1846,10 +1893,27 @@ if ! ex_fast ; then fi # stage4: full compiler (C/C++/etc...) - if is_s4 && [[ "${LLVM}" != "yes" ]] ; then - EOPTS="${EOPTS_UP} --newuse" \ - USE="${GUSE} ${USE} ${GUSE_DISABLE_STAGE_2}" \ - doemerge ${GPKG} ${GPKG}-stage2 + if is_s4 ; then + if [[ "${LLVM}" == "yes" ]]; then + USE="${UUSE} ${USE}" \ + doemerge ${UPKG} + + # Include libunwind in the cross configuration. libc++ depends on it. + sed -i "s/--unwindlib=.*$/--unwindlib=libunwind/" "${CLANG_CROSS_CFG}" + + USE="${AUSE} ${USE}" \ + doemerge ${APKG} + USE="${CXUSE} ${USE}" \ + doemerge ${CXPKG} + + # Finally, include libc++ in the cross configuration. + sed -i "/--unwindlib/ a --stdlib=libc++" "${CLANG_CROSS_CFG}" + fi + if [[ "${LLVM}" != "yes" || "${CTARGET}" == *-gnu* ]]; then + EOPTS="${EOPTS_UP} --newuse" \ + USE="${GUSE} ${USE} ${GUSE_DISABLE_STAGE_2}" \ + doemerge ${GPKG} ${GPKG}-stage2 + fi fi fi