File PKGBUILD of Package gcc-git-god

# Maintainer: neycrol <330578697@qq.com>

pkgbase=gcc-git-god
pkgname=(
  gcc-git-god
  gcc-libs-git-god
  lib32-gcc-libs-git-god
  libgccjit-git-god
)
pkgver=0
pkgrel=3
pkgdesc="GCC Git toolchain and runtime libraries (God Mode, latest upstream)"
arch=('x86_64')
url="https://gcc.gnu.org/git/gcc.git"
license=('GPL3' 'LGPL' 'FDL' 'custom')
makedepends=(
  git flex bison texinfo perl autoconf automake libtool make
  gmp mpfr libmpc isl zlib zstd python
  lib32-glibc-git
)
options=('!strip' '!debug' '!lto')
source=(
  "gcc-git.tar.gz"
  "gmp.tar.gz"
  "mpfr.tar.gz"
  "mpc.tar.gz"
  "isl.tar.gz"
)
sha256sums=('SKIP' 'SKIP' 'SKIP' 'SKIP' 'SKIP')

pkgver() {
  local _date _rev _base _src
  _date=$(date -u +%Y%m%d)

  if [[ -f "${srcdir}/._servicedata" ]]; then
    _rev=$(sed -n 's:.*<revision>\(.*\)</revision>.*:\1:p' "${srcdir}/._servicedata" | head -n1)
    if [[ -z "${_rev}" ]]; then
      _rev=$(sed -n 's:.*revision="\([0-9a-f]\+\)".*:\1:p' "${srcdir}/._servicedata" | head -n1)
    fi
  fi

  _src=""
  for d in "${srcdir}"/gcc*; do
    if [[ -d "${d}" && -f "${d}/gcc/BASE-VER" ]]; then
      _src="${d}"
      break
    fi
  done

  if [[ -n "${_src}" ]]; then
    _base=$(cat "${_src}/gcc/BASE-VER")
  fi

  if [[ -n "${_rev}" ]]; then
    echo "${_base:-0}.${_date}.g${_rev:0:8}"
  else
    echo "${_base:-0}.${_date}"
  fi
}

_find_gcc_src() {
  local d
  for d in "${srcdir}"/gcc*; do
    if [[ -d "${d}" && -f "${d}/configure" ]]; then
      echo "${d}"
      return 0
    fi
  done
  return 1
}

_vendor_dep() {
  local _src="$1" _name="$2" _tar="$3"
  if [[ ! -d "${_src}/${_name}" && -f "${srcdir}/${_tar}" ]]; then
    mkdir -p "${_src}/${_name}"
    bsdtar -xf "${srcdir}/${_tar}" -C "${_src}/${_name}" --strip-components=1
  fi
}

_copy_so_family() {
  local _from="$1" _stem="$2" _to="$3"
  local _f _hit=1
  for _f in "${_from}/${_stem}.so"*; do
    [[ -e "${_f}" ]] || continue
    cp -a "${_f}" "${_to}/"
    _hit=0
  done
  return ${_hit}
}

prepare() {
  local _src
  _src=$(_find_gcc_src) || {
    echo "gcc sources not found"
    return 1
  }

  _vendor_dep "${_src}" gmp  "gmp.tar.gz"
  _vendor_dep "${_src}" mpfr "mpfr.tar.gz"
  _vendor_dep "${_src}" mpc  "mpc.tar.gz"
  _vendor_dep "${_src}" isl  "isl.tar.gz"

  # LTO can trip on a few runtime libs in trunk; keep selective fallback.
  if [[ -f "${_src}/libatomic/Makefile.in" ]] && ! grep -q "fno-lto" "${_src}/libatomic/Makefile.in"; then
    echo "LIBATOMIC_CFLAGS += -fno-lto" >> "${_src}/libatomic/Makefile.in"
  fi
  if [[ -f "${_src}/libgomp/Makefile.in" ]] && ! grep -q "fno-lto" "${_src}/libgomp/Makefile.in"; then
    echo "LIBGOMP_CFLAGS += -fno-lto" >> "${_src}/libgomp/Makefile.in"
  fi

  echo "${_src}" > "${srcdir}/.gcc_srcdir"
  rm -rf "${srcdir}/build" "${srcdir}/pkgroot"
  mkdir -p "${srcdir}/build" "${srcdir}/pkgroot"
}

build() {
  local _src
  local _bootstrap_target="profiledbootstrap"
  _src=$(cat "${srcdir}/.gcc_srcdir")

  export CC=/usr/bin/gcc
  export CXX=/usr/bin/g++

  # Host build flags: keep conservative for configure/bootstrap reliability.
  export CFLAGS="-O2 -pipe -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -fno-semantic-interposition"
  export CXXFLAGS="${CFLAGS}"
  export LDFLAGS="-Wl,-O2,--sort-common,--as-needed,-z,relro,-z,now"

  # Target runtime flags: aggressive but without data collection dependency.
  export CFLAGS_FOR_TARGET="-O3 -march=alderlake -mtune=alderlake -pipe -fno-plt -fexceptions -fstack-clash-protection -fcf-protection -fno-semantic-interposition"
  export CXXFLAGS_FOR_TARGET="${CFLAGS_FOR_TARGET}"
  export LDFLAGS_FOR_TARGET="${LDFLAGS}"

  export MAKEFLAGS="-j$(/usr/bin/getconf _NPROCESSORS_ONLN)"

  cd "${srcdir}/build"

  "${_src}/configure" \
    --prefix=/opt/gcc-git-god \
    --libdir=/opt/gcc-git-god/lib64 \
    --libexecdir=/opt/gcc-git-god/lib \
    --enable-languages=c,c++,fortran,jit,lto \
    --enable-bootstrap \
    --with-build-config=bootstrap-lto-lean \
    --enable-multilib \
    --enable-host-shared \
    --enable-shared \
    --enable-threads=posix \
    --enable-__cxa_atexit \
    --enable-libstdcxx-time \
    --enable-lto \
    --enable-plugin \
    --enable-linker-build-id \
    --enable-default-pie \
    --enable-default-ssp \
    --with-linker-hash-style=gnu \
    --with-system-zlib \
    --disable-libsanitizer \
    --disable-werror

  # Pure OBS internal data collection:
  # prefer autoprofiledbootstrap when perf+create_gcov exist, else profiledbootstrap.
  if command -v perf >/dev/null 2>&1 && command -v create_gcov >/dev/null 2>&1; then
    _bootstrap_target="autoprofiledbootstrap"
  fi
  msg2 "Bootstrap optimization mode: ${_bootstrap_target}"

  if ! make -O STAGE1_CFLAGS="-O2" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" \
      LDFLAGS_FOR_TARGET="$LDFLAGS_FOR_TARGET" "${_bootstrap_target}"; then
    if [[ "${_bootstrap_target}" == "autoprofiledbootstrap" ]]; then
      echo "autoprofiledbootstrap failed, fallback to profiledbootstrap"
      make -O STAGE1_CFLAGS="-O2" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" \
        LDFLAGS_FOR_TARGET="$LDFLAGS_FOR_TARGET" profiledbootstrap || \
      make -O STAGE1_CFLAGS="-O2" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" \
        LDFLAGS_FOR_TARGET="$LDFLAGS_FOR_TARGET" bootstrap
    else
      echo "profiledbootstrap failed, fallback to bootstrap"
      make -O STAGE1_CFLAGS="-O2" BOOT_CFLAGS="$CFLAGS" BOOT_LDFLAGS="$LDFLAGS" \
        LDFLAGS_FOR_TARGET="$LDFLAGS_FOR_TARGET" bootstrap
    fi
  fi

  make DESTDIR="${srcdir}/pkgroot" install
}

package_gcc-git-god() {
  pkgdesc="GCC Git compiler suite (installed under /opt)"
  depends=("gcc-libs-git-god=${pkgver}-${pkgrel}" binutils gmp mpfr libmpc isl zlib zstd)
  provides=('gcc' "gcc=${pkgver}-${pkgrel}")
  conflicts=('gcc')
  replaces=('gcc')

  install -dm755 "${pkgdir}/opt"
  cp -a "${srcdir}/pkgroot/opt/gcc-git-god" "${pkgdir}/opt/"

  install -dm755 "${pkgdir}/usr/bin"
  local _tool
  local _target
  local _compat_tools=(
    gcc g++ c++ cc cpp
    gcc-ar gcc-nm gcc-ranlib
    gcov gcov-dump gcov-tool
    gfortran lto-dump
  )
  for _tool in "${_compat_tools[@]}"; do
    _target="${_tool}"
    case "${_tool}" in
      cc) _target="gcc" ;;
      c++) _target="g++" ;;
    esac
    cat > "${pkgdir}/usr/bin/${_tool}" <<EOS
#!/bin/sh
exec /opt/gcc-git-god/bin/${_target} "\$@"
EOS
    chmod 755 "${pkgdir}/usr/bin/${_tool}"
  done

  # Keep explicit custom entry points for manual selection.
  ln -sf gcc "${pkgdir}/usr/bin/gcc-git-god"
  ln -sf g++ "${pkgdir}/usr/bin/g++-git-god"

  # Rust and some build systems probe target-prefixed tool names directly.
  local _triplet="x86_64-pc-linux-gnu"
  local _prefixed_tools=(
    "${_triplet}-gcc"
    "${_triplet}-g++"
    "${_triplet}-cpp"
    "${_triplet}-gcc-ar"
    "${_triplet}-gcc-nm"
    "${_triplet}-gcc-ranlib"
  )
  for _tool in "${_prefixed_tools[@]}"; do
    if [[ -x "${pkgdir}/opt/gcc-git-god/bin/${_tool}" ]]; then
      ln -sf "/opt/gcc-git-god/bin/${_tool}" "${pkgdir}/usr/bin/${_tool}"
    fi
  done

  # Keep binutils LTO integration working after replacing the gcc package.
  local _lto_plugin
  _lto_plugin=$(find "${pkgdir}/opt/gcc-git-god" -type f -name liblto_plugin.so | head -n1 || true)
  if [[ -n "${_lto_plugin}" ]]; then
    install -dm755 "${pkgdir}/usr/lib/bfd-plugins"
    ln -sf "/${_lto_plugin#${pkgdir}/}" "${pkgdir}/usr/lib/bfd-plugins/liblto_plugin.so"
  fi

  # Do not provide /usr/lib/gcc compatibility symlink here.
  # It conflicts with existing directory ownership from toolchains
  # such as mingw-w64-gcc and causes pacman file conflicts.
}

package_gcc-libs-git-god() {
  pkgdesc="Runtime libraries shipped by GCC Git (system replacement)"
  depends=('glibc>=2.27')
  provides=(
    'gcc-libs' "gcc-libs=${pkgver}-${pkgrel}"
    'libasan' 'libatomic' 'libgfortran' 'libgcc' 'libgomp' 'liblsan' 'libobjc' 'libquadmath' 'libstdc++' 'libtsan' 'libubsan'
    'libgfortran.so=5-64' 'libgcc_s.so=1-64' 'libstdc++.so=6-64'
    'libubsan.so' 'libasan.so' 'libtsan.so' 'liblsan.so'
  )
  conflicts=(
    'gcc-libs'
    'libasan' 'libatomic' 'libgfortran' 'libgcc' 'libgomp' 'liblsan' 'libobjc' 'libquadmath' 'libstdc++' 'libtsan' 'libubsan'
  )
  replaces=(
    'gcc-libs'
    'libasan' 'libatomic' 'libgfortran' 'libgcc' 'libgomp' 'liblsan' 'libobjc' 'libquadmath' 'libstdc++' 'libtsan' 'libubsan'
  )
  options=('!emptydirs' '!strip')

  local _src _lib64
  _src=$(cat "${srcdir}/.gcc_srcdir")
  _lib64="${srcdir}/pkgroot/opt/gcc-git-god/lib64"

  install -dm755 "${pkgdir}/usr/lib"

  local _libs=(
    libasan libatomic libgcc_s libgfortran libgomp
    libitm liblsan libquadmath libstdc++ libtsan libubsan
  )
  local _l
  for _l in "${_libs[@]}"; do
    _copy_so_family "${_lib64}" "${_l}" "${pkgdir}/usr/lib" || true
  done

  for _l in libstdc++ libgcc_s libgomp libatomic; do
    if ! compgen -G "${pkgdir}/usr/lib/${_l}.so*" > /dev/null; then
      echo "missing required runtime library family: ${_l}"
      return 1
    fi
  done

  # Runtime Library Exception
  install -Dm644 "${_src}/COPYING.RUNTIME" \
    "${pkgdir}/usr/share/licenses/gcc-libs-git-god/RUNTIME.LIBRARY.EXCEPTION"

  # Optional runtime info pages
  install -dm755 "${pkgdir}/usr/share/info"
  for _info in libgomp.info.gz libitm.info.gz libquadmath.info.gz; do
    if [[ -f "${srcdir}/pkgroot/opt/gcc-git-god/share/info/${_info}" ]]; then
      cp -a "${srcdir}/pkgroot/opt/gcc-git-god/share/info/${_info}" "${pkgdir}/usr/share/info/"
    fi
  done

  install -dm755 "${pkgdir}/usr/share/locale"
  if [[ -d "${srcdir}/pkgroot/opt/gcc-git-god/share/locale" ]]; then
    cp -a "${srcdir}/pkgroot/opt/gcc-git-god/share/locale/." "${pkgdir}/usr/share/locale/"
  fi
}

package_lib32-gcc-libs-git-god() {
  pkgdesc='32-bit runtime libraries shipped by GCC Git (system replacement)'
  depends=('lib32-glibc>=2.27')
  provides=('lib32-gcc-libs' "lib32-gcc-libs=${pkgver}-${pkgrel}" 'libgfortran.so' 'libubsan.so' 'libasan.so')
  conflicts=('lib32-gcc-libs')
  replaces=('lib32-gcc-libs')
  options=('!emptydirs' '!strip')

  local _src _lib32
  _src=$(cat "${srcdir}/.gcc_srcdir")
  _lib32="${srcdir}/pkgroot/opt/gcc-git-god/lib32"

  install -dm755 "${pkgdir}/usr/lib32"

  local _libs=(
    libasan libatomic libgcc_s libgfortran libgomp
    libitm libquadmath libstdc++ libubsan
  )
  local _l
  for _l in "${_libs[@]}"; do
    _copy_so_family "${_lib32}" "${_l}" "${pkgdir}/usr/lib32" || true
  done

  for _l in libstdc++ libgcc_s libgomp libatomic; do
    if ! compgen -G "${pkgdir}/usr/lib32/${_l}.so*" > /dev/null; then
      echo "missing required 32-bit runtime library family: ${_l}"
      return 1
    fi
  done

  install -Dm644 "${_src}/COPYING.RUNTIME" \
    "${pkgdir}/usr/share/licenses/lib32-gcc-libs-git-god/RUNTIME.LIBRARY.EXCEPTION"
}

package_libgccjit-git-god() {
  pkgdesc="Just-In-Time Compilation library with GCC Git backend"
  depends=("gcc-libs-git-god=${pkgver}-${pkgrel}" 'isl')
  provides=('libgccjit' "libgccjit=${pkgver}-${pkgrel}")
  conflicts=('libgccjit')
  replaces=('libgccjit')

  local _lib64
  _lib64="${srcdir}/pkgroot/opt/gcc-git-god/lib64"

  install -dm755 "${pkgdir}/usr/lib" "${pkgdir}/usr/include"
  _copy_so_family "${_lib64}" "libgccjit" "${pkgdir}/usr/lib" || {
    echo "libgccjit shared library not found"
    return 1
  }

  if [[ -f "${srcdir}/pkgroot/opt/gcc-git-god/include/libgccjit.h" ]]; then
    cp -a "${srcdir}/pkgroot/opt/gcc-git-god/include/libgccjit.h" "${pkgdir}/usr/include/"
  fi
  if [[ -f "${srcdir}/pkgroot/opt/gcc-git-god/include/libgccjit++.h" ]]; then
    cp -a "${srcdir}/pkgroot/opt/gcc-git-god/include/libgccjit++.h" "${pkgdir}/usr/include/"
  fi

  install -dm755 "${pkgdir}/usr/share/info"
  if [[ -f "${srcdir}/pkgroot/opt/gcc-git-god/share/info/libgccjit.info.gz" ]]; then
    cp -a "${srcdir}/pkgroot/opt/gcc-git-god/share/info/libgccjit.info.gz" "${pkgdir}/usr/share/info/"
  fi

  local _src
  _src=$(cat "${srcdir}/.gcc_srcdir")
  install -Dm644 "${_src}/COPYING.RUNTIME" \
    "${pkgdir}/usr/share/licenses/libgccjit-git-god/RUNTIME.LIBRARY.EXCEPTION"
}
openSUSE Build Service is sponsored by