#!/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 }