| git.druid.rocks | index | druid520 | ports | ports/ | compilers/ | gcc/ | pkg.conf |
ports/compilers/gcc/pkg.conf
pkg_name="gcc"
pkg_license="gpl-3.0+"
pkg_ver="git"
pkg_tags="cc"
pkg_pref="60"
# gawk, hard (not %awk): gcc's own generated config.status hardcodes a
# LITERAL call to "gawk" specifically in several places (stage3-target-
# libgcc's own configure among them) -- confirmed directly, a real
# build failure ("./config.status: line 1030: gawk: not found") on a
# system whose own %awk default is build-tools/onetrueawk instead.
# gawk's own install (see its own pkg.conf) skips creating a
# $MP_PREFIX/bin/awk symlink by default specifically so it can coexist
# as exactly this kind of specific, named dependency without
# disturbing whatever this system's own chosen %awk provider is.
pkg_deps="gawk"
# c is always built (gcc needs a c compiler to build itself) and isn't
# a flag. cxx defaults on since most of this tree's own c++ software
# (needing libstdc++) assumes it; fortran/objc/ada/d/go are real
# optional gcc frontends this tree has no other dependencies for, off
# by default to keep the (already long) bootstrap from growing further
# for languages nothing here actually uses yet.
#
# pie: OFF by default -- opt-in for whoever wants libcc1 (gdb's own
# "compile" command) and libsanitizer (-fsanitize=address/undefined/...)
# working, at the cost of a real, different, more opinionated recipe
# (--enable-default-pie --enable-shared, matching Alpine's own gcc
# APKBUILD, plus the two patches/ this flag pulls in via patches.conf's
# own IF_USE="pie !static" -- see build:'s own comment on the configure
# line for the full why). the DEFAULT recipe keeps --disable-libcc1
# --disable-libsanitizer instead (see the same comment) -- a
# conservative, upstream-shaped build nothing here strictly needs
# beyond a working c/c++ compiler, left plain on purpose rather than
# opinionated by default.
#
# static: OFF by default -- opt-in for --disable-shared, skipping gcc's
# own shared runtime libs (libstdc++.so, libgcc_s.so, the sanitizer
# .so's) entirely, keeping only static .a archives. independent of
# pie: "static" alone is a plain static build (no PIE code-gen change),
# "pie static" together produces static-PIE output (PIE code
# generation, with everything else linked static) -- matching this
# port's own build system's static-pie convention where one is in use.
# libcc1 (gdb's own "compile" JIT bridge) still needs pie specifically
# to build under EITHER static setting: checked directly in gcc's own
# Makefile.def rather than assumed, libcc1's own sub-configure always
# gets "--enable-shared" force-appended regardless of this port's own
# top-level shared/static choice, so libcc1.so is still attempted even
# under "static" -- it only actually needs the PIC-compatible static
# libstdc++.a objects pie itself provides (build:'s own comment has
# the full story), so "pie static" builds a real, working libcc1.so
# same as plain pie does; static WITHOUT pie still can't build it, and
# disables it. libsanitizer has no such override in Makefile.def --
# it genuinely follows this port's own shared/static choice, so under
# static (with or without pie) it only ever builds static .a archives
# (usable via -static-libasan/-static-libubsan/...) with no .so
# attempted at all, meaning it needs disabling only in the plain
# default case (neither pie nor static).
#
# bootstrap: ON by default -- gcc's own upstream-recommended 3-stage
# bootstrap-and-compare (see build:'s own comment on the configure
# line for the full reasoning). turning it off adds --disable-bootstrap
# for a single, faster build with the host compiler instead, at the
# cost of gcc's own reproducibility self-check.
pkg_use="+cxx fortran objc ada d go pie static +bootstrap"
# "mp reinstall --inplace" builds into a throwaway, ephemeral prefix and
# merges the result onto the live root afterward -- mpx's own merge
# command only rewrites symlink targets rooted at the source prefix,
# never arbitrary text/data embedded inside a file, so it can't fix up
# gcc's own compiled-in internal search paths (its own --prefix and
# --with-native-system-header-dir, baked into its "specs" file and its
# libexec/gcc/<target>/<ver>/ layout) -- under --inplace those would
# bake in the ephemeral scratch path instead of the live root, leaving
# gcc unable to find its own cc1/libgcc/crtbegin.o the moment that
# scratch dir is cleaned up post-merge. same class of incident as
# languages/perl5, build-tools/gnu-{autoconf,automake,libtool,gettext},
# ssl/libressl, networking/curl, and vcs/git's own identical
# pkg_no_inplace -- gcc is simply the largest, and the single most
# consequential to get wrong (see remove:'s own comment for why).
pkg_no_inplace="yes"
# mplib::resolve::clean_manifest_files runs independently of remove: --
# it deletes every file in a package's OWN tracked manifest as part of
# "reinstall", regardless of what remove: itself does or doesn't do.
# remove:'s own comment explains why gcc's live files must never be
# removed before a fresh build finishes; this is the OTHER, separate
# mechanism that removal has to be disabled for too -- missed the first
# time around and hit for real: manifest cleanup alone removed 1847
# files (the entire live gcc-git tree) the moment the network hiccuped
# mid-rebuild (a transient "connection reset by peer" downloading a
# prerequisite), leaving the system with no compiler at all until a
# container rescue restored it. same pkg_manifest_cleanup="no" as
# libcs/musl and build-tools/busybox, for the identical reason.
pkg_manifest_cleanup="no"
# rewritten as real fetch:/build:/install:/remove: phases (not a legacy
# add.sh/del.sh) so patches/*.patch + patches/patches.conf's own
# IF_USE="pie !static" gating actually works -- legacy ports can't get
# that synthesis at all (mplib::resolve's own apply_patch_manifest
# bails out immediately for a legacy port, "return if $pc->{_legacy};").
fetch:
git clone --depth 1 https://github.com/gcc-mirror/gcc.git
cd gcc
# busybox's own wget applet resets the TLS connection to
# gcc.gnu.org every time ("Connection reset by peer" -- a real,
# reproduced interop gap, not transient flakiness: curl fetches the
# identical URL fine), and contrib/download_prerequisites always
# prefers wget over curl whenever wget is on PATH at all, with no
# override switch of its own. shadowing "wget" with a tiny
# curl-based shim for just this one call, rather than pre-fetching
# this script's own prerequisite files by name here, keeps this
# working even after upstream bumps one of those pinned versions --
# this shim only has to handle the ONE way this particular script
# invokes it ("wget --no-verbose URL", the last arg always being
# the url, everything before it a flag to ignore).
mkdir -p /tmp/gcc-fetch-shim
cat > /tmp/gcc-fetch-shim/wget <<'SHIM'
#!/bin/sh
eval url=\$$#
exec curl -sSL -O "$url"
SHIM
chmod +x /tmp/gcc-fetch-shim/wget
PATH="/tmp/gcc-fetch-shim:$PATH" ./contrib/download_prerequisites
rm -rf /tmp/gcc-fetch-shim
build:
# unset entirely, not just left at CFLAGS_FOR_BUILD/STAGE1_CFLAGS/
# LDFLAGS_FOR_BUILD-scoped overrides (tried first, and each one
# really was needed -- see below): an ambient CFLAGS/CXXFLAGS/
# LDFLAGS/CPPFLAGS (e.g. a system-wide static-pie policy some
# mp-based systems set in /etc/mpx.env) still leaks into gcc's own
# bootstrap through paths those per-variable overrides don't cover
# -- gcc's own top-level Makefile concatenates STAGE1_LDFLAGS
# (hardcoded "-static-libstdc++ -static-libgcc", never inheriting
# ambient LDFLAGS on its own) alongside the PLAIN, unset $(LDFLAGS)
# variable for stage1's own ./configure sanity checks, so an
# ambient LDFLAGS containing -static-pie still reaches them
# regardless. unsetting the ambient flags entirely up front matches
# the already-established exemption directly: gcc's own internal
# tools were never meant to inherit a host system's own general
# build policy in the first place (same as mp's own mk.conf gives
# itself), so its build has no business seeing it at all. CPATH (a
# separate, independent env var, still set) and the include-symlink
# trick further below still cover "find this sysroot's real libc
# headers" without needing CFLAGS to carry "-I$MP_PREFIX/include"
# itself.
unset CFLAGS CXXFLAGS LDFLAGS CPPFLAGS
# TMPDIR -> this port's own stage dir (always writable under
# SANDBOX="yes", unlike /tmp -- see the dependency-tracking comment
# on the configure line below for why this matters, not just for
# gettext's own nested configure but for every make invocation in
# this build, "make clean" at the end of install: included).
export TMPDIR="$PWD"
# populate the CURRENTLY installed gcc's own last-resort include
# fallback (bin/../lib/gcc/../../include -- confirmed via
# "g++ -v -E", it's the final entry in gcc's own compiled-in search
# list) with symlinks to this sysroot's real libc headers, same as
# the post-install step below does for the gcc THIS build produces.
# needed here too: several of gcc's own bundled subprojects
# (libcody, and the downloaded gettext prerequisite among them) get
# compiled as part of ITS OWN bootstrap using whatever compiler is
# currently installed, and neither respects an injected -idirafter/
# CFLAGS/CXXFLAGS the way a normal port's build would (tried first,
# didn't reach either one -- libcody hardcodes its own g++
# invocation with no $(CXXFLAGS) substitution at all, and the
# nested gettext prerequisite's own autoconf ./configure runs
# independently of gcc's top-level Makefile's "_FOR_BUILD"-suffixed
# variables). symlinks into the fallback directory itself sidestep
# needing every such nested build to cooperate at all.
#
# "the currently installed gcc" is NOT necessarily "$MP_PREFIX/
# gcc-git" -- true whenever a rebuild happens at the SAME prefix
# gcc was last built at (the common case), but NOT when $MP_PREFIX
# itself has changed since (e.g. an OpenBSD/usrmerge-style prefix
# migration): the compiler actually on PATH right now may still
# live at its own OLD, unrelated absolute prefix. resolved via the
# resident compiler's own real location instead of assumed, so this
# keeps working either way. "|| true" on the mkdir/loop: this step
# is a best-effort optimization (the currently-installed compiler
# may already have a perfectly good fallback dir populated from ITS
# OWN prior build, in which case there's nothing to add here at
# all) never a hard requirement, and writing outside $MP_PREFIX
# entirely (exactly the OLD-prefix case above) is exactly what
# SANDBOX="yes" (the default) restricts -- a failure here should
# never abort a build this expensive over a step this optional.
old_gcc_root="$(dirname "$(dirname "$(readlink -f "$(command -v gcc)")")")"
mkdir -p "$old_gcc_root/include" || true
# skipped entirely when old_gcc_root/include IS MP_PREFIX/include
# (the common case: a rebuild at the SAME prefix gcc was last
# built at) -- "populate this directory with symlinks to
# itself" is never useful, and ln -sf's own directory-target
# behavior (source is a directory, destination already exists
# as one too -> installs INSIDE it under its own basename, not
# a replace) means every entry silently produces a real,
# confirmed-on-disk self-referential symlink instead of erroring
# where it'd be noticed: $MP_PREFIX/include/foo/foo ->
# $MP_PREFIX/include/foo, for every directory entry under
# include/, recreated on every single gcc rebuild forever.
if [ "$(readlink -f "$old_gcc_root/include")" != "$(readlink -f "$MP_PREFIX/include")" ]; then
for f in $MP_PREFIX/include/*; do
ln -sf "$f" "$old_gcc_root/include/$(basename "$f")" || true
done
fi
# no "cd gcc" here: mp's own write_phase_scripts already auto-
# prepends "cd gcc 2>/dev/null || true" to every phase but fetch:
# (matching pkg_name -- see remove:'s own comment on this same
# mechanism), so CWD already starts inside the checkout.
mkdir build
cd build
# c is always built; the rest are USE flags (see pkg_use above).
LANGUAGES=c
[ -n "$USE_cxx" ] && LANGUAGES="$LANGUAGES,c++"
[ -n "$USE_fortran" ] && LANGUAGES="$LANGUAGES,fortran"
[ -n "$USE_objc" ] && LANGUAGES="$LANGUAGES,objc"
[ -n "$USE_ada" ] && LANGUAGES="$LANGUAGES,ada"
[ -n "$USE_d" ] && LANGUAGES="$LANGUAGES,d"
[ -n "$USE_go" ] && LANGUAGES="$LANGUAGES,go"
# --disable-werror wasn't actually the fix: libiberty/getopt1.c's
# missing _getopt_internal declaration (a genuine musl-vs-glibc
# gap, upstream never tested this against musl) fails as a hard
# *error* regardless of --Werror, because gcc 14+ defaults
# -Wimplicit-function-declaration to an error for c99-and-later,
# unconditionally - a real behavior change in modern gcc, not
# something --disable-werror ever controlled. the actual failure is
# in "all-build-libiberty" specifically, gcc's separate
# build-machine-tools copy of libiberty (genattrtab and friends,
# not the target compiler itself), which reads CFLAGS_FOR_BUILD
# rather than the normal bootstrap CFLAGS. kept --disable-werror
# too since it doesn't hurt and matches upstream's own
# recommendation for git checkouts.
#
# also exported as plain CFLAGS (appended, not replaced -- mpx's
# own runsh.c already injected its own baseline
# "-I$MP_PREFIX/include" in there, which this must keep): stage1's
# OWN copy of libiberty (as opposed to the build-machine-tools copy
# CFLAGS_FOR_BUILD already covers) builds via ITS OWN separately-
# generated, ordinary autoconf Makefile several levels down, which
# captures plain inherited CFLAGS as its own cached default rather
# than reading BOOT_CFLAGS/CFLAGS_FOR_BUILD -- same shape of gap as
# the bundled gettext prerequisite's own nested ./configure
# elsewhere in this bootstrap.
export CFLAGS="$CFLAGS -Wno-implicit-function-declaration"
# --build/--host/--target explicit, all three the same triplet:
# this is a native, non-cross build, but gcc's own bundled
# config.guess has no way to tell musl apart from glibc (it isn't
# looking for musl at all) and defaults to guessing
# "x86_64-pc-linux-gnu" -- which then propagates into every nested
# sub-configure (stage1-target-libatomic among them), picking
# GLIBC-conventional defaults (its dynamic linker path in
# particular) that don't exist anywhere on a musl-only system. hit
# for real: "cannot run C compiled programs" configuring
# libatomic, root-caused via its own config.log to "./conftest: not
# found" -- not a missing/malformed binary, but one whose baked
# PT_INTERP pointed at a real glibc loader path this system has
# never had.
gcc_triplet="$(gcc -dumpmachine)"
# LDFLAGS_FOR_BUILD="" alongside CFLAGS_FOR_BUILD, not left to
# gcc's own default: its own top-level Makefile sets
# "LDFLAGS_FOR_BUILD = $(LDFLAGS)" (falls through to whatever this
# whole build session's own ambient LDFLAGS happens to be) -- but
# CFLAGS_FOR_BUILD is explicitly kept free of -fPIC/-static-pie
# (these build-machine tools were never meant to be static-pie
# themselves), so an ambient LDFLAGS containing -static-pie
# mismatches against objects that were never compiled -fPIC in the
# first place. hit for real: "relocation R_X86_64_32 ... can not be
# used when making a PIE object; recompile with -fPIE" building
# build-x86_64-pc-linux-musl/fixincludes' own conftest, on a system
# whose ambient LDFLAGS carried -static-pie. (STAGE1_LDFLAGS,
# stage1's own equivalent to STAGE1_CFLAGS, doesn't have this
# problem -- gcc's own Makefile hardcodes it to "-static-libstdc++
# -static-libgcc" unconditionally, never falling back to ambient
# LDFLAGS at all.)
#
# pie USE flag: --enable-default-pie (Alpine's own gcc APKBUILD
# recipe on musl x86_64, confirmed working the same way here),
# combined with --enable-shared (see the static USE flag just
# below for when that isn't the case), is what actually lets
# libcc1.so (gdb's own "compile" JIT bridge) and libsanitizer's own
# libubsan.so/libtsan.so link successfully -- root cause: each
# pulls in the STATIC libstdc++.a (the shared libstdc++.so isn't
# finished yet at this point in bootstrap ordering), whose objects
# were built non-PIC -- "recompile with -fPIC" the moment ld folds
# them into a shared object. --with-pic (meant to make libtool
# build every intermediate static archive PIC-only, sidestepping
# exactly this) was tried and empirically DIDN'T fix either
# failure, confirmed via a real GCC/libstdc++ maintainer's own
# mailing list advice (Jonathan Wakely) too -- --with-pic does NOT
# fix this on gcc trunk. --enable-default-pie instead makes PIE
# (hence PIC-compatible) the default code-generation mode for
# everything gcc's own build produces, including the plain
# (non-multilib) static archive variant, so libstdc++.a's objects
# are already position-independent from the start regardless of
# build order.
#
# static USE flag: --disable-shared, independent of pie -- gcc's
# own shared runtime libs (libstdc++.so, libgcc_s.so, the
# sanitizer .so's) simply don't get built at all, only static .a
# archives. "pie static" together produces static-PIE output: PIE
# code generation, with everything else linked static.
#
# libcc1 and libsanitizer do NOT need the same condition, checked
# directly in gcc's own Makefile.def rather than assumed:
#
# - libcc1 (Makefile.def's own host_modules entry) carries
# "extra_configure_flags=--enable-shared" UNCONDITIONALLY --
# gcc's own build system always forces libcc1's OWN sub-configure
# to --enable-shared, regardless of the top-level shared/static
# setting. so libcc1.so still gets attempted even under a
# top-level --disable-shared build, and only actually needs pie
# (for PIC-compatible static libstdc++.a objects, this port's own
# top comment has the full story) -- disable it whenever pie is
# off, regardless of static.
# - libsanitizer (Makefile.def's own target_modules entry) has NO
# such override -- its own sub-configure just inherits whatever
# the top-level shared/static setting is. under --disable-shared
# it only ever builds static .a archives (usable via
# -static-libasan/-static-libubsan/...), no .so is attempted at
# all, so the PIC-mismatch failure below never arises in the
# first place -- it only needs disabling in the plain default
# case (neither pie nor static: shared stays gcc's own implicit
# default, so a .so IS attempted, and without pie its objects
# aren't PIC-compatible).
pie_flags=""
[ -n "$USE_pie" ] && pie_flags="--enable-default-pie"
if [ -n "$USE_static" ]; then
pie_flags="$pie_flags --disable-shared"
else
pie_flags="$pie_flags --enable-shared"
fi
[ -z "$USE_pie" ] && pie_flags="$pie_flags --disable-libcc1"
[ -z "$USE_pie" ] && [ -z "$USE_static" ] && pie_flags="$pie_flags --disable-libsanitizer"
# bootstrap USE flag: ON by default (see pkg_use's own comment) --
# --disable-bootstrap only gets added when it's turned off.
bootstrap_flags=""
[ -z "$USE_bootstrap" ] && bootstrap_flags="--disable-bootstrap"
CFLAGS_FOR_BUILD="-O2 -Wno-implicit-function-declaration" \
LDFLAGS_FOR_BUILD="" \
../configure --prefix=$MP_PREFIX/gcc-git --disable-multilib --disable-werror --enable-languages=$LANGUAGES $pie_flags $bootstrap_flags \
--build=$gcc_triplet --host=$gcc_triplet --target=$gcc_triplet \
--with-native-system-header-dir=$MP_PREFIX/include $CONFIGURE_FLAGS
# root cause of "config.status: error: Something went wrong
# bootstrapping makefile fragments for automatic dependency
# tracking" (hit repeatedly configuring the bundled gettext
# prerequisite, deterministically -- survived a fully serial
# JOBS=1 retry too, ruling out a parallel-build race): NOT a gmake
# regression, NOT anything wrong with dependency tracking itself.
# config.status's own "executing depfiles commands" step runs
# `sed ... | $MAKE -f - am--depfiles` -- a make invocation
# INHERITED MAKEFLAGS reaches (mpx's own runsh.c always exports
# MAKEFLAGS with -jMP_JOBS, even for commands that never asked for
# -j themselves), so it always tries to participate in a
# jobserver. modern GNU Make (4.4+) defaults to a FIFO-style
# jobserver, which needs mkfifo(1) under $TMPDIR (unset -> /tmp) --
# and /tmp is NOT one of the directories SANDBOX="yes" leaves
# writable (confirmed directly: `mkfifo /tmp/x` inside a real `mpx
# runsh` sandbox fails with "Read-only file system", the exact same
# error class visible on install:'s own trailing "make clean" line
# in a real build log -- "jobserver mkfifo: /tmp/GmFIFO...:
# Read-only file system"). the TMPDIR export above (pointing at
# this port's own stage dir, always writable) fixes the actual
# cause instead of disabling dependency tracking: every make
# invocation, nested or not, can now create its jobserver FIFO
# successfully. an isolated plain-shell reproduction (clone+
# configure+build gcc entirely outside mpx, /tmp genuinely
# writable) did NOT reproduce this bug at all, confirming it's
# specific to the sandbox's read-only /tmp, not gettext/gmake/gcc
# themselves.
# --with-native-system-header-dir above: without it, gcc's own
# default header search only ever finds ITS OWN bundled private
# headers (limits.h, stddef.h, ...), never this sysroot's real libc
# headers (musl's own limits.h etc, at $MP_PREFIX/include) - every
# mp-driven build still works regardless, since mpx's own runsh.c
# always injects "-I$MP_PREFIX/include" into CFLAGS itself, but
# anything that invokes gcc/cpp directly with no -I flags at all
# (autoconf's own AC_PROG_CPP sanity check in particular, which
# deliberately tests with CPPFLAGS, not CFLAGS) fails outright:
# "#include <limits.h>" recurses via gcc's own "#include_next
# <limits.h>" straight off the end of the search path. invisible
# on a normal native build, where autoconf's own fallback probe
# (literal "/lib/cpp") happens to find the HOST's real system cpp
# and silently substitutes it instead - only surfaced once building
# moved into a real chroot, where no such host fallback exists. on
# its own this option's baked value hasn't actually been resolving
# correctly for #include_next's own purposes (hit for real: a full
# libstdc++ header chain still landed on an empty fallback
# directory despite this flag) -- the symlink step above and below
# is what actually makes the fallback directory usable either way,
# so this stays for whatever partial effect it has without being
# load-bearing.
#
# STAGE1_CFLAGS below (NOT BOOT_CFLAGS, tried first and didn't
# reach it): the SAME libiberty/getopt1.c _getopt_internal gap
# CFLAGS_FOR_BUILD already works around for gcc's own
# build-machine tools copy of libiberty also hits stage1's copy
# (the real target compiler's own bootstrap,
# "all-stage1-libiberty") -- that one is configured via a hardcoded
# "STAGE1_CFLAGS = -g" in gcc's own top-level Makefile (deliberately
# minimal/fixed for the bootstrap's first stage, by design --
# neither BOOT_CFLAGS nor an exported plain CFLAGS reaches it,
# confirmed via libiberty's own generated config.log still showing
# "CFLAGS='-g'" after both). -g kept alongside so this override
# doesn't silently drop gcc's own default for the rest of stage1.
#
# bootstrap ON by default: the normal 3-stage bootstrap-and-compare
# (stage1 with the host cc, stage2 built with THAT, stage3 rebuilt
# with stage2 and diffed against it to confirm reproducibility) is
# gcc's own upstream-recommended default and what this shared port
# keeps -- slower, but the safer default for a port other systems
# build from too. turning the bootstrap USE flag off adds
# --disable-bootstrap for a single, faster build with the host
# compiler instead (see bootstrap_flags above).
make CFLAGS_FOR_BUILD="-O2 -Wno-implicit-function-declaration" LDFLAGS_FOR_BUILD="" STAGE1_CFLAGS="-g -Wno-implicit-function-declaration" -j$MP_JOBS
install:
# see build:'s own identical export -- a separate phase, a separate
# script/process, so this needs setting again here (every make
# invocation below inherits mpx's own MAKEFLAGS="-jMP_JOBS" and
# tries to create a jobserver FIFO regardless of whether IT asked
# for -j, "make clean" at the very end included).
export TMPDIR="$PWD"
# same auto-cd as build: (see its own comment) -- CWD already
# starts inside the checkout, so just "cd build" from there.
cd build
make install
mkdir -p $MP_PREFIX/bin
ln -sf $MP_PREFIX/gcc-git/bin/gcc $MP_PREFIX/bin/gcc
# cc and c99: the POSIX-conventional generic C compiler names
# (POSIX itself specifies invoking the compiler as "c99"/"cc") - a
# huge amount of handwritten configure/Makefile/bootstrap-script
# code assumes one or the other is on PATH unconditionally (CC=cc
# as a bare default, or a literal "c99 ..." invocation, never
# falling back to gcc specifically), not just gcc's own name.
ln -sf $MP_PREFIX/gcc-git/bin/gcc $MP_PREFIX/bin/cc
ln -sf $MP_PREFIX/gcc-git/bin/gcc $MP_PREFIX/bin/c99
ln -sf $MP_PREFIX/gcc-git/bin/cpp $MP_PREFIX/bin/cpp
ln -sf $MP_PREFIX/gcc-git/bin/gcov $MP_PREFIX/bin/gcov
[ -n "$USE_cxx" ] && ln -sf $MP_PREFIX/gcc-git/bin/g++ $MP_PREFIX/bin/g++
# gcc-git installs its own runtime shared libs (libstdc++, libgomp,
# libatomic, the sanitizers, ...) under its own --prefix's lib64/,
# not under $MP_PREFIX/lib. every other port's own binaries get
# -Wl,-rpath,$MP_PREFIX/lib automatically (mpx's own runsh.c always
# adds it), so once this gcc becomes the default cc/g++ on PATH,
# anything it links against libstdc++/libgomp/etc silently falls
# through the rpath to whatever OLDER version happens to already be
# on the base system's default library path instead -- compiles
# fine, then fails at runtime with missing/mismatched symbol
# versions. symlinking gcc-git's own copies into $MP_PREFIX/lib
# makes them win over that fallback for every port built after this
# one, the same way its bin/ symlinks already do for the compiler
# binaries themselves.
mkdir -p $MP_PREFIX/lib
for f in $MP_PREFIX/gcc-git/lib64/*.so*; do
ln -sf "$f" "$MP_PREFIX/lib/$(basename "$f")"
done
# see the identical step in build:, before ../configure: make
# install just recreated $MP_PREFIX/gcc-git/include from scratch
# (gcc's own bundled c++ wrapper headers only), wiping out that fix
# for THIS freshly installed copy -- redone here so every port
# built after this one (which invoke gcc/g++ directly, not through
# this recipe) get a working #include_next chain too, not just
# this bootstrap itself.
for f in $MP_PREFIX/include/*; do
ln -sf "$f" "$MP_PREFIX/gcc-git/include/$(basename "$f")"
done
cd ..
make clean || true
remove:
# unlike a typical remove phase, this deliberately does NOT remove
# the live $MP_PREFIX/gcc-git tree, its bin/ symlinks, or the lib/
# runtime symlinks up front. gcc is the compiler the WHOLE system
# (every other port's own build included) depends on, and once c++
# is enabled, its libstdc++.so/libgomp.so/... symlinked into
# $MP_PREFIX/lib are runtime dependencies of already-compiled
# binaries, not just build-time ones -- removing any of this before
# a fresh build finishes would leave the system with no working
# compiler AND broken c++ runtime linking for the entire duration
# of the next build, and if that build then fails for any reason
# there is no way to even rebuild gcc again (same shape of incident
# as libcs/musl's own remove phase, which learned this the hard way
# for libc.so specifically -- see its own comment).
#
# install:'s own fresh "configure --prefix=$MP_PREFIX/gcc-git &&
# make && make install" overwrites every one of gcc's own installed
# files (and its own "ln -sf" calls overwrite every bin/ and lib/
# symlink) in place regardless, so nothing here actually needs
# deleting first.
#
# NOT "cd .. ; rm -rf gcc" (a natural-looking mistake matching
# build:/install:'s own starting point one level deeper): mp's own
# write_phase_scripts auto-prepends "cd gcc 2>/dev/null || true" to
# every phase but fetch: (matching pkg_name, portformat.pm's own
# $srcname), which is how build:/install: end up starting inside
# the checkout with no explicit "cd gcc" of their own. remove: gets
# that SAME auto-cd -- but remove: runs BEFORE fetch: ever
# (re-)clones a checkout for a "reinstall" pass, so at the moment
# it runs there's nothing named "gcc" to cd into yet, and the auto-
# cd's own "|| true" swallows that failure silently, leaving CWD at
# the stage root instead (confirmed directly: a debug "pwd" placed
# here prints ".../gcc" -- the STAGE dir, i.e. $MP_PREFIX's sibling
# named after this package, not the checkout inside it). a leading
# "cd .." from here doesn't reach some sibling checkout dir; it
# escapes to this stage dir's own PARENT, and "rm -rf gcc" from
# there would be deleting THIS SAME stage dir's own directory
# entry while still running inside its own bind mount, a mount
# namespace's own root -- self-referential and unremovable
# ("Resource busy") regardless of the TMPDIR fix. "make clean"
# below hits an empty/no-Makefile directory here for the same
# reason (no checkout at this level yet) -- harmless, hence
# `|| true`. plain "gcc" directly below (no cd) correctly targets
# any stale checkout subdirectory a previous run's fetch: left
# behind, and is a silent no-op when there isn't one.
export TMPDIR="$PWD"
make clean || true
rm -rf gcc