181 lines
7.1 KiB
Bash
Executable file
181 lines
7.1 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License.
|
|
# See LICENSE.md for license information.
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# gcc2.sh - Haiku's gcc 2.95 cross compiler (component haikuGcc2, the
|
|
# x86_gcc2 primary compiler, kept for BeOS binary compatibility) behind the
|
|
# command line the shared build rules give a modern gcc, so make/hosted.mk
|
|
# drives it unchanged.
|
|
#
|
|
# gcc2.sh ROOT gcc|g++|ar ARGS...
|
|
#
|
|
# ROOT is the component: cross/ holds the compiler, sysroot/ R1/beta6's
|
|
# headers and libraries. With BE_R5_SYSROOT set (make beos: component
|
|
# beosR5's sysroot) it builds for BeOS R5 instead, which the same ABI runs
|
|
# on: R5's own header tree, start files and libraries in place of Haiku's.
|
|
# Programs stay position-independent (-pie), as R5's own are (ET_DYN), but
|
|
# their relocations are not combined (-z nocombreloc): the DT_RELCOUNT tag
|
|
# that comes with combined ones is newer than R5, whose loader will not run
|
|
# a program with a tag it does not know ("cannot execute binary file"). R5's
|
|
# libroot leaves memcpy_internal and memset_internal to the loader, which
|
|
# the driver already allows (--allow-shlib-undefined). The compiler was
|
|
# built for /tools/cross-tools-x86_gcc2 and is not relocatable, so it is
|
|
# pointed at its own programs (-B), and
|
|
# gcc 2.95 has no --sysroot, so the headers it would find in
|
|
# /boot/system/develop/headers on Haiku are named one by one. Its binutils
|
|
# (ar too) find their shared libraries through LD_LIBRARY_PATH. As Haiku's
|
|
# own gcc 2.95 does, the Be API's four-character constants ('BAPP') are not
|
|
# warned about; strict aliasing stays off, and gcc2Attributes.h, beside this
|
|
# script, is included first: the GCC attributes gcc 2.95 does not know. The
|
|
# modern options are translated:
|
|
# -Wextra is gcc 2.95's -W in C; in C++ it is left out, as -W warns
|
|
# about the Be API's own headers
|
|
# -MMD -MP gcc 2.95 has neither: the dependency file is made after a
|
|
# successful compile by a second, -M, pass -- named and
|
|
# targeted as a modern gcc would (X.d for -o X.o, NAME.d for a
|
|
# program linked as -o NAME), every header also a target of
|
|
# its own (-MP), so a deleted header does not stop make. The
|
|
# toolchain's own headers are left out, as -MMD leaves out
|
|
# system headers (gcc 2.95's -MM would leave out every
|
|
# <header>, JoeyLib's own among them).
|
|
set -euo pipefail
|
|
|
|
root="$1"
|
|
driver="$2"
|
|
shift 2
|
|
|
|
machine="i586-pc-haiku"
|
|
version="2.95.3-haiku-2017_07_20"
|
|
cross="$root/cross"
|
|
r5="${BE_R5_SYSROOT:-}"
|
|
if [ -n "$r5" ]; then
|
|
headerRoot="$r5/headers"
|
|
# R5's gcc's include directories, under develop/headers.
|
|
headerDirs="be be/app be/device be/drivers be/game be/interface be/kernel be/mail be/media be/midi be/midi2 be/net be/opengl be/storage be/support be/translation be/add-ons/graphics be/add-ons/input_server be/add-ons/screen_saver be/add-ons/tracker cpp gnu posix"
|
|
libSetup=(-B"$r5/develop-lib/x86/" -L"$r5/develop-lib/x86" -L"$r5/system-lib")
|
|
# What R5 lacks of C99's headers (stdint.h), beside this script, and
|
|
# R5's gcc's system macro in place of Haiku's: the compiler says
|
|
# __HAIKU__, as Haiku's own, where R5's said __BEOS__.
|
|
compatSetup=(-isystem "$(dirname "$0")/r5" -U__HAIKU__ -D__BEOS__)
|
|
# Where R5's libraries find each other's, when linking, and no combined
|
|
# relocations (above).
|
|
linkFlags=(-Wl,-rpath-link,"$r5/system-lib" -Wl,-z,nocombreloc)
|
|
else
|
|
develop="$root/sysroot/boot/system/develop"
|
|
headerRoot="$develop/headers"
|
|
# The include directories of Haiku's own gcc 2.95, in its order
|
|
# (buildtools' legacy/gcc/gcc/config/i386/haiku.h), under develop/headers.
|
|
headerDirs="os os/app os/device os/drivers os/game os/interface os/kernel os/locale os/mail os/media os/midi os/midi2 os/net os/opengl os/storage os/support os/translation os/add-ons/graphics os/add-ons/input_server os/add-ons/screen_saver os/add-ons/tracker os/be_apps/Deskbar os/be_apps/NetPositive os/be_apps/Tracker 3rdparty bsd glibc gnu posix"
|
|
libSetup=(-B"$develop/lib/" -L"$develop/lib")
|
|
compatSetup=()
|
|
linkFlags=()
|
|
fi
|
|
|
|
export LD_LIBRARY_PATH="$cross/x86_64-unknown-linux-gnu/$machine/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
|
|
|
if [ "$driver" = ar ]; then
|
|
exec "$cross/bin/$machine-ar" "$@"
|
|
fi
|
|
|
|
setup=(-B"$cross/lib/gcc-lib/$machine/$version/" -B"$cross/$machine/bin/" "${compatSetup[@]}")
|
|
for dir in $headerDirs; do
|
|
setup+=(-isystem "$headerRoot/$dir")
|
|
done
|
|
setup+=(-isystem "$headerRoot" -isystem "$headerRoot/c++" -include "$(dirname "$0")/gcc2Attributes.h")
|
|
|
|
args=() # the compile, translated
|
|
cppArgs=() # what the dependency pass needs: the preprocessor's options and the sources
|
|
sources=()
|
|
output=""
|
|
compileOnly=0
|
|
depFile=0
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-Wextra)
|
|
if [ "$driver" = gcc ]; then
|
|
args+=(-W)
|
|
fi
|
|
;;
|
|
-MMD)
|
|
depFile=1
|
|
;;
|
|
-MP)
|
|
;;
|
|
-lm)
|
|
# R5 keeps the maths in libroot and has no libm.
|
|
if [ -z "$r5" ]; then
|
|
args+=(-lm)
|
|
fi
|
|
;;
|
|
-o)
|
|
output="$2"
|
|
args+=(-o "$2")
|
|
shift
|
|
;;
|
|
-c)
|
|
compileOnly=1
|
|
args+=(-c)
|
|
;;
|
|
-D*|-U*|-I*)
|
|
args+=("$1")
|
|
cppArgs+=("$1")
|
|
;;
|
|
-isystem|-include|-imacros)
|
|
args+=("$1" "$2")
|
|
cppArgs+=("$1" "$2")
|
|
shift
|
|
;;
|
|
*.c|*.cc|*.cpp)
|
|
args+=("$1")
|
|
sources+=("$1")
|
|
;;
|
|
*)
|
|
args+=("$1")
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# After the caller's options: -Wall would turn the multi-character warning
|
|
# back on.
|
|
if [ "$compileOnly" = 1 ]; then
|
|
linkFlags=()
|
|
fi
|
|
"$cross/bin/$machine-$driver" "${setup[@]}" "${libSetup[@]}" "${args[@]}" "${linkFlags[@]}" -Wno-multichar -fno-strict-aliasing
|
|
|
|
if [ "$depFile" = 0 ] || [ ${#sources[@]} -eq 0 ] || [ -z "$output" ]; then
|
|
exit 0
|
|
fi
|
|
if [ "$compileOnly" = 1 ]; then
|
|
dep="${output%.*}.d"
|
|
else
|
|
dep="$output.d"
|
|
fi
|
|
# One rule for the output from every source's rule, then each header as a
|
|
# target of its own; nothing from the toolchain (or R5's sysroot).
|
|
"$cross/bin/$machine-$driver" "${setup[@]}" -M "${cppArgs[@]}" "${sources[@]}" | awk -v target="$output" -v toolchain="$root/" -v sysroot="${r5:+$r5/}" '
|
|
{
|
|
line = $0
|
|
sub(/\\$/, "", line)
|
|
sub(/^[^:]*:/, "", line)
|
|
count = split(line, words, " ")
|
|
for (i = 1; i <= count; i++) {
|
|
if (index(words[i], toolchain) != 1 && (sysroot == "" || index(words[i], sysroot) != 1) && !(words[i] in seen)) {
|
|
seen[words[i]] = 1
|
|
order[++total] = words[i]
|
|
}
|
|
}
|
|
}
|
|
END {
|
|
printf "%s:", target
|
|
for (i = 1; i <= total; i++) {
|
|
printf " %s", order[i]
|
|
}
|
|
printf "\n"
|
|
for (i = 1; i <= total; i++) {
|
|
if (order[i] !~ /\.(c|cc|cpp)$/) {
|
|
printf "\n%s:\n", order[i]
|
|
}
|
|
}
|
|
}' > "$dep"
|