449 lines
20 KiB
Bash
449 lines
20 KiB
Bash
#!/bin/bash
|
|
|
|
install_libc() {
|
|
local sharedstorage="$1"
|
|
local host_triplet="$2"
|
|
local TRIPLET="$3"
|
|
local currentpathlibc="$4"
|
|
local tripletpath="$5"
|
|
local sysrootpathusr="$6"
|
|
local usellvm="$7"
|
|
local buildheadersonly="$8"
|
|
local multilibs="${9:-no}"
|
|
local isgcccrossing="${10:-no}"
|
|
local install_full_libc="${11:-no}"
|
|
local CPU
|
|
local VENDOR
|
|
local OS
|
|
local ABI
|
|
parse_triplet $TRIPLET CPU VENDOR OS ABI
|
|
if [[ "$OS" == mingw* ]]; then
|
|
VENDOR=""
|
|
OS="windows"
|
|
ABI="gnu"
|
|
fi
|
|
|
|
local ANDROIDAPIVERSION
|
|
if [[ "$OS" == "linux" && "$ABI" == android* ]]; then
|
|
ANDROIDAPIVERSION=${ABI#android}
|
|
if [ -z "$ANDROIDAPIVERSION" ]; then
|
|
echo "Error: ANDROIDAPIVERSION is not set."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
local phase_file
|
|
if [ "$buildheadersonly" == "yes" ]; then
|
|
phase_file=".libc_headers_phase_done"
|
|
else
|
|
phase_file=".libc_phase_done"
|
|
fi
|
|
local installdirpath="${sysrootpathusr}"
|
|
mkdir -p "${currentpathlibc}"
|
|
mkdir -p "${tripletpath}"
|
|
if [ ! -f "${currentpathlibc}/${phase_file}" ]; then
|
|
if [[ "$OS" == "darwin"* ]]; then
|
|
cd "${currentpathlibc}"
|
|
local repo_url
|
|
local base_url
|
|
|
|
if [ "$CLONE_IN_CHINA" = "yes" ]; then
|
|
repo_url="https://gitee.com/qabeowjbtkwb/apple-darwin-sysroot.git"
|
|
base_url="https://gitee.com/qabeowjbtkwb/apple-darwin-sysroot/releases/download"
|
|
else
|
|
repo_url="https://github.com/trcrsired/apple-darwin-sysroot.git"
|
|
base_url="https://github.com/trcrsired/apple-darwin-sysroot/releases/download"
|
|
fi
|
|
local darwinversiondate
|
|
if [ -z ${DARWINVERSIONDATE+x} ]; then
|
|
darwinversiondate=$(git ls-remote --tags $repo_url | tail -n 1 | sed 's/.*\///')
|
|
else
|
|
darwinversiondate=${DARWINVERSIONDATE}
|
|
fi
|
|
local triplet_variant=${TRIPLET}
|
|
[[ $triplet_variant == arm64e-* ]] && triplet_variant="aarch64-${triplet_variant#arm64e-}"
|
|
wget --no-verbose ${base_url}/${darwinversiondate}/${triplet_variant}.tar.xz
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to download the Darwin sysroot"
|
|
exit 1
|
|
fi
|
|
chmod 755 ${triplet_variant}.tar.xz
|
|
tar -xf "${triplet_variant}.tar.xz" -C "${tripletpath}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Failed to extract the Darwin sysroot"
|
|
exit 1
|
|
fi
|
|
if [[ $TRIPLET != "$triplet_variant" ]]; then
|
|
mv "${tripletpath}/$triplet_variant" "${tripletpath}/$TRIPLET"
|
|
fi
|
|
elif [[ "$OS" == "freebsd"* ]]; then
|
|
cd "${currentpathlibc}"
|
|
|
|
local base_url
|
|
if [ "$CLONE_IN_CHINA" = "yes" ]; then
|
|
base_url="https://github.com/trcrsired/x86_64-freebsd-libc-bin/releases/download"
|
|
else
|
|
base_url="https://gitee.com/qabeowjbtkwb/x86_64-freebsd-libc-bin/releases/download"
|
|
fi
|
|
|
|
local version_tag="1"
|
|
local archive_name="${CPU}-freebsd-libc.tar.xz"
|
|
local remote_url="${base_url}/${version_tag}/${archive_name}"
|
|
local local_archive="${currentpathlibc}/downloads/${archive_name}"
|
|
local shared_archive="${sharedstorage}/freebsd-libc/${archive_name}"
|
|
local decompress_dir="${currentpathlibc}/sysroot_decompress"
|
|
|
|
mkdir -p "$(dirname "$local_archive")"
|
|
mkdir -p "$(dirname "$shared_archive")"
|
|
mkdir -p "$decompress_dir"
|
|
|
|
# Step 1: Try to reuse shared archive if available
|
|
if [ -f "$shared_archive" ]; then
|
|
echo "Using cached libc archive from sharedstorage"
|
|
cp "$shared_archive" "$local_archive"
|
|
else
|
|
echo "Downloading libc archive from $remote_url"
|
|
wget --no-verbose -O "$local_archive" "$remote_url"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to download $archive_name for $TRIPLET"
|
|
exit 1
|
|
fi
|
|
cp "$local_archive" "$shared_archive"
|
|
fi
|
|
|
|
# Step 2: Extract
|
|
tar -xf "$local_archive" -C "$decompress_dir"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to extract $archive_name"
|
|
exit 1
|
|
fi
|
|
|
|
# Step 3: Add write permission for owner
|
|
chmod -R u+w "$decompress_dir/${CPU}-freebsd-libc"
|
|
|
|
# Step 4: Install
|
|
mkdir -p "$installdirpath"
|
|
cp -a "$decompress_dir/${CPU}-freebsd-libc/"* "$installdirpath/"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Copy to installdir for freebsd"
|
|
exit 1
|
|
fi
|
|
elif [[ "$OS" == "windows" ]]; then
|
|
if [[ "$ABI" == "msvc" ]]; then
|
|
clone_or_update_dependency windows-msvc-sysroot
|
|
elif [[ "$ABI" == "gnu" ]]; then
|
|
clone_or_update_dependency mingw-w64
|
|
local MINGWTRIPLET="${CPU}-w64-mingw32"
|
|
local MINGWW64COMMON
|
|
if [[ ${CPU} == "x86_64" ]]; then
|
|
if [[ "$multilibs" == "yes" ]]; then
|
|
MINGWW64COMMON="--enable-lib32 --enable-lib64"
|
|
else
|
|
MINGWW64COMMON="--disable-lib32 --enable-lib64"
|
|
fi
|
|
elif [[ ${CPU} == "aarch64" ]]; then
|
|
MINGWW64COMMON="--disable-lib32 --disable-lib64 --disable-libarm32 --enable-libarm64"
|
|
elif [[ ${CPU} == "arm" ]]; then
|
|
MINGWW64COMMON="--disable-lib32 --disable-lib64 --enable-libarm32 --disable-libarm64"
|
|
elif [[ ${CPU} =~ i[3-6]86 ]]; then
|
|
MINGWW64COMMON="--enable-lib32 --disable-lib64 --with-default-msvcrt=msvcrt"
|
|
else
|
|
MINGWW64COMMON="--disable-lib32 --disable-lib64 --disable-libarm32 --disable-libarm64 --enable-lib$CPU"
|
|
fi
|
|
MINGWW64COMMON="$MINGWW64COMMON --host=${MINGWTRIPLET} --disable-nls --disable-werror --prefix=${sysrootpathusr}"
|
|
local MINGWW64COMMONENV="
|
|
CC=\"clang --target=${TRIPLET} -fuse-ld=lld \"--sysroot=${sysrootpathusr}\"\"
|
|
CXX=\"clang++ --target=${TRIPLET} -fuse-ld=lld \"--sysroot=${sysrootpathusr}\"\"
|
|
LD=lld
|
|
NM=llvm-nm
|
|
RANLIB=llvm-ranlib
|
|
AR=llvm-ar
|
|
DLLTOOL=llvm-dlltool
|
|
AS=llvm-as
|
|
STRIP=llvm-strip
|
|
OBJDUMP=llvm-objdump
|
|
WINDRES=llvm-windres
|
|
"
|
|
|
|
# Resolve absolute paths to ensure accurate comparison
|
|
local tripletpath_real="$(realpath "${tripletpath}")"
|
|
local installdirpath_real="$(realpath "${installdirpath}")"
|
|
|
|
if [ ! -f "${currentpathlibc}/.libc_phase_header" ]; then
|
|
mkdir -p "${currentpathlibc}/mingw-w64-headers"
|
|
cd "${currentpathlibc}/mingw-w64-headers"
|
|
|
|
if [ ! -f Makefile ]; then
|
|
if [[ "$usellvm" == "yes" ]]; then
|
|
eval ${MINGWW64COMMONENV} $TOOLCHAINS_BUILD/mingw-w64/mingw-w64-headers/configure ${MINGWW64COMMON}
|
|
else
|
|
$TOOLCHAINS_BUILD/mingw-w64/mingw-w64-headers/configure ${MINGWW64COMMON}
|
|
fi
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: mingw-w64-headers($TRIPLET) configure failed"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
make -j$(nproc) 2>err.txt
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: make mingw-w64-headers($TRIPLET) install-strip failed"
|
|
exit 1
|
|
fi
|
|
|
|
make install-strip -j$(nproc) 2>>err.txt
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: make mingw-w64-headers($TRIPLET) install-strip failed"
|
|
exit 1
|
|
fi
|
|
# Skip copy if source and destination are the same directory
|
|
# if [ "$tripletpath_real" = "$installdirpath_real" ]; then
|
|
# echo "Skip copy: source and destination are the same ($tripletpath_real)"
|
|
# else
|
|
# Copy all files from source to destination, preserving symbolic links
|
|
# cp -r --preserve=links "${tripletpath}"/* "${installdirpath}"/
|
|
|
|
# Check if the copy command failed
|
|
# if [ $? -ne 0 ]; then
|
|
# echo "Error: copy mingw-w64-headers($TRIPLET) failed"
|
|
# exit 1
|
|
# fi
|
|
# fi
|
|
echo "$(date +%s)" > "${currentpathlibc}/.libc_phase_header"
|
|
fi
|
|
|
|
mkdir -p "${currentpathlibc}/mingw-w64-crt"
|
|
cd "${currentpathlibc}/mingw-w64-crt"
|
|
|
|
if [ ! -f Makefile ]; then
|
|
if [[ "$usellvm" == "yes" ]]; then
|
|
eval ${MINGWW64COMMONENV} $TOOLCHAINS_BUILD/mingw-w64/mingw-w64-crt/configure ${MINGWW64COMMON}
|
|
else
|
|
$TOOLCHAINS_BUILD/mingw-w64/mingw-w64-crt/configure ${MINGWW64COMMON}
|
|
fi
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: configure mingw-w64-crt($TRIPLET) failed"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
make -j$(nproc) 2>err.txt
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: make mingw-w64-crt($TRIPLET) failed"
|
|
exit 1
|
|
fi
|
|
|
|
make install-strip -j$(nproc) 2>>err.txt
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: make install-strip mingw-w64-crt($TRIPLET) failed"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$isgcccrossing" == "yes" ]]; then
|
|
# Create lib/32 symlink if lib32 exists and multilibs is enabled for x86_64
|
|
if [[ "$CPU" == "x86_64" && "$multilibs" == "yes" ]]; then
|
|
if [ -d "${installdirpath}/lib32" ]; then
|
|
mkdir -p "${installdirpath}/lib"
|
|
if [ ! -e "${installdirpath}/lib/32" ]; then
|
|
ln -sfn ../lib32 "${installdirpath}/lib/32"
|
|
echo "Created symlink: ${installdirpath}/lib/32 → ../lib32"
|
|
else
|
|
echo "Symlink already exists: ${installdirpath}/lib/32"
|
|
fi
|
|
else
|
|
echo "lib32 directory not found under ${installdirpath}, skipping symlink"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Skip copy if source and destination are the same directory
|
|
# if [ "$tripletpath_real" = "$installdirpath_real" ]; then
|
|
# echo "Skip copy: source and destination are the same ($tripletpath_real)"
|
|
# else
|
|
# Copy all files from source to destination, preserving symbolic links
|
|
# cp -r --preserve=links "${tripletpath}"/* "${installdirpath}"/
|
|
|
|
# Check if the copy command failed
|
|
# if [ $? -ne 0 ]; then
|
|
# echo "Error: copy mingw-w64-crt($TRIPLET) failed"
|
|
# exit 1
|
|
# fi
|
|
# fi
|
|
else
|
|
echo "Unknown Windows ABI: $ABI"
|
|
exit 1
|
|
fi
|
|
elif [[ "$OS" == "linux" ]]; then
|
|
if [[ "$ABI" == "android"* ]]; then
|
|
if [ -z "${ANDROIDNDKVERSION}" ]; then
|
|
ANDROIDNDKVERSION=$(git ls-remote --tags https://github.com/android/ndk.git 2>/dev/null \
|
|
| grep -v '\^{}' \
|
|
| awk -F'/' '{print $3}' \
|
|
| grep -E '^r[0-9]+$' \
|
|
| sort -V \
|
|
| tail -n1)
|
|
echo "Detected ANDROIDNDKVERSION: ${ANDROIDNDKVERSION}"
|
|
if [ -z "${ANDROIDNDKVERSION}" ]; then
|
|
ANDROIDNDKVERSION="r29"
|
|
fi
|
|
fi
|
|
|
|
local ANDROIDNDKVERSIONSHORTNAME="android-ndk-${ANDROIDNDKVERSION}"
|
|
local ANDROIDNDKVERSIONFULLNAME="${ANDROIDNDKVERSIONSHORTNAME}-linux"
|
|
# China Mirror no longer works
|
|
# if [ "$CLONE_IN_CHINA" = "yes" ]; then
|
|
# base_url="https://googledownloads.cn/android/repository"
|
|
# else
|
|
local base_url="https://dl.google.com/android/repository"
|
|
# fi
|
|
|
|
local NDKURL="${base_url}/${ANDROIDNDKVERSIONFULLNAME}.zip"
|
|
|
|
# Define filenames and paths
|
|
local NDK_ZIP="${ANDROIDNDKVERSIONFULLNAME}.zip"
|
|
local NDK_DONE_FILE=".ndk_downloaded_at"
|
|
local NDK_SHARED_ZIP="${sharedstorage}/${NDK_ZIP}"
|
|
local NDK_SHARED_DONE="${sharedstorage}/${NDK_DONE_FILE}"
|
|
|
|
# Ensure sharedstorage exists
|
|
mkdir -p "${sharedstorage}"
|
|
|
|
# Download to sharedstorage if not already completed
|
|
if [ -f "${NDK_SHARED_DONE}" ] && [ -f "${NDK_SHARED_ZIP}" ]; then
|
|
echo "NDK zip already downloaded in shared storage."
|
|
else
|
|
echo "Downloading NDK zip to shared storage..."
|
|
cd "${sharedstorage}"
|
|
wget --tries=2 --show-progress "${NDKURL}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "wget ${NDKURL} failure"
|
|
exit 1
|
|
fi
|
|
echo "$(date +%s)" > "${NDK_DONE_FILE}"
|
|
fi
|
|
|
|
# Prepare target extraction directory
|
|
mkdir -p "${currentpathlibc}"
|
|
cd "${currentpathlibc}"
|
|
|
|
# Unzip directly from sharedstorage into currentpathlibc
|
|
unzip -q "${NDK_SHARED_ZIP}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "unzip ${NDK_SHARED_ZIP} failure"
|
|
exit 1
|
|
fi
|
|
|
|
# Record download completion timestamp
|
|
echo "$(date +%s)" > "${NDK_DONE_FILE}"
|
|
mkdir -p "${installdirpath}"
|
|
cp -r --preserve=links ${currentpathlibc}/${ANDROIDNDKVERSIONSHORTNAME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/${CPU}-linux-android/${ANDROIDAPIVERSION} ${installdirpath}/lib
|
|
cp -r --preserve=links ${currentpathlibc}/${ANDROIDNDKVERSIONSHORTNAME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include ${installdirpath}/
|
|
cp -r --preserve=links ${installdirpath}/include/${CPU}-linux-android/asm ${installdirpath}/include/
|
|
else
|
|
clone_or_update_dependency linux
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to clone or update linux"
|
|
exit 1
|
|
fi
|
|
install_linux_kernel_headers $CPU "${currentpathlibc}" "${installdirpath}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to install Linux kernel headers"
|
|
exit 1
|
|
fi
|
|
|
|
if [[ "$ABI" == "gnu" ]]; then
|
|
clone_or_update_dependency glibc
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to clone or update glibc"
|
|
exit 1
|
|
fi
|
|
build_glibc $CPU "${currentpathlibc}" "${installdirpath}" "${usellvm}" "${buildheadersonly}" "no" "" "${install_full_libc}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to build glibc"
|
|
exit 1
|
|
fi
|
|
elif [[ "$ABI" == "musl" ]]; then
|
|
clone_or_update_dependency musl
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to clone or update musl"
|
|
exit 1
|
|
fi
|
|
build_musl $TRIPLET "${currentpathlibc}" "${installdirpath}" "${usellvm}" "${buildheadersonly}" "no" "" "${install_full_libc}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to build musl"
|
|
exit 1
|
|
fi
|
|
fi
|
|
fi
|
|
elif [[ "$OS" == "msdosdjgpp" ]]; then
|
|
local DJCRX="${DJCRX:-djcrx205}"
|
|
local shared_djgpp_zip="${sharedstorage}/djgpp/${DJCRX}.zip"
|
|
local local_djgpp_zip="${currentpathlibc}/downloads/${DJCRX}.zip"
|
|
local local_djgpp_root="${currentpathlibc}/${DJCRX}"
|
|
|
|
mkdir -p "${currentpathlibc}/downloads"
|
|
mkdir -p "${local_djgpp_root}"
|
|
mkdir -p "${sysrootpathusr}"
|
|
mkdir -p "$(dirname "$shared_djgpp_zip")"
|
|
|
|
# Step 1: Try to copy from sharedstorage if available
|
|
if [ -f "$shared_djgpp_zip" ]; then
|
|
echo "Using cached ${DJCRX}.zip from sharedstorage"
|
|
cp "$shared_djgpp_zip" "$local_djgpp_zip"
|
|
else
|
|
echo "Downloading ${DJCRX}.zip from Delorie"
|
|
#Use my fix up of djcrx since it has no struct timespec which breaks libstdc++ build
|
|
# wget -O "$local_djgpp_zip" "http://www.delorie.com/pub/djgpp/current/v2/${DJCRX}.zip"
|
|
wget -O "$local_djgpp_zip" "https://github.com/trcrsired/djcrx/releases/download/20251102/${DJCRX}.zip"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to download ${DJCRX}.zip"
|
|
exit 1
|
|
fi
|
|
cp "$local_djgpp_zip" "$shared_djgpp_zip"
|
|
fi
|
|
|
|
chmod 755 "$local_djgpp_zip" || true
|
|
|
|
unzip "$local_djgpp_zip" -d "${local_djgpp_root}"
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to unzip ${DJCRX}.zip"
|
|
exit 1
|
|
fi
|
|
|
|
mkdir -p "${sysrootpathusr}/bin"
|
|
|
|
# Determine compiler for stubify/stubedit
|
|
local stub_compiler=""
|
|
if [ -z "$host_triplet" ]; then
|
|
if [[ "$usellvm" == "yes" ]]; then
|
|
stub_compiler="clang -fuse-ld=lld"
|
|
else
|
|
stub_compiler="gcc"
|
|
fi
|
|
else
|
|
if [[ "$usellvm" == "yes" ]]; then
|
|
stub_compiler="clang --target=${host_triplet} -fuse-ld=lld"
|
|
else
|
|
stub_compiler="${host_triplet}-gcc"
|
|
fi
|
|
fi
|
|
|
|
$stub_compiler -o "${sysrootpathusr}/bin/stubify" "${local_djgpp_root}/src/stub/stubify.c" -s -O3 -flto
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to compile stubify"
|
|
exit 1
|
|
fi
|
|
|
|
$stub_compiler -o "${sysrootpathusr}/bin/stubedit" "${local_djgpp_root}/src/stub/stubedit.c" -s -O3 -flto
|
|
if [ $? -ne 0 ]; then
|
|
echo "Error: Failed to compile stubedit"
|
|
exit 1
|
|
fi
|
|
|
|
cp -a "${local_djgpp_root}"/include "${sysrootpathusr}/"
|
|
cp -a "${local_djgpp_root}"/lib "${sysrootpathusr}/"
|
|
fi
|
|
echo "$(date +%s)" > "${currentpathlibc}/${phase_file}"
|
|
fi
|
|
}
|