首次提交

This commit is contained in:
2026-07-07 15:23:39 +08:00
commit dd8d5d2ddb
91 changed files with 15746 additions and 0 deletions
+438
View File
@@ -0,0 +1,438 @@
#!/bin/bash
# shellcheck disable=SC2155
if ! type "include" > /dev/null 2>&1; then
include() {
. "$(cd "$(dirname "$1")" && pwd)/${2}";
};
fi
include "${BASH_SOURCE[0]}" ../pragma_once.bash
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
include "${BASH_SOURCE[0]}" ../base/export.bash
false && source ../base/export.bash
include "${BASH_SOURCE[0]}" ../gcc/export.bash
false && source ../gcc/export.bash
include "${BASH_SOURCE[0]}" ../Qt/export.bash
false && source ../Qt/export.bash
# gcc_env
export gev_target_env
export gev_target_sysroot
export gev_cross_dir
export gev_canadian_dir
export gev_stage1_dir
export gev_local_dir
export gev_cur_env_name
export gev_cur_toolchain_name
# 构建sysroot所需
export gev_linux_ver # 下载linux 内核源码的 url
export gev_linux_arch # linux arch架构名称
export gev_glibc_ver gev_glibc_suffix_opts
export gev_stage1_gcc_ver gev_stage1_gcc_suffix_opts
# 自动计算
export gev_local_triplet gev_local_triplet_no_vendor
export gev_target
export gev_build
# 这个函数不能放到gcc编译的开头因为gcc编译的开头需要外部的参数 如果设置了外部参数就失效了
gev_init_params() {
gev_target_env=""
gev_target_sysroot=""
gev_cross_dir=""
gev_canadian_dir=""
gev_stage1_dir=""
gev_local_dir=""
gev_cur_env_name=""
gev_cur_toolchain_name=""
gev_linux_ver="v5.15.139"
gev_linux_arch="x86_64"
gev_glibc_ver="glibc-2.31"
gev_glibc_suffix_opts=""
gev_stage1_gcc_ver="releases/gcc-10.5.0"
gev_stage1_gcc_suffix_opts=""
}
# 初始化全局变量参数值
gev_init_params
init_by_env_name() {
detect_platform_triplet gev_local_triplet gev_local_triplet_no_vendor
gev_build=${gev_local_triplet}
gev_cur_env_name="${1}"
gev_cur_toolchain_name="${gev_cur_env_name}"
gev_target="${2}"
gev_target_env="/ae/env/${gev_cur_env_name}"
# 这个地方可以改 sysroot 叫什么名称
gev_target_sysroot="${gev_target_env}/sysroot_${gev_target}"
gev_cross_dir="${gev_target_env}"
gev_canadian_dir="${gev_target_env}"
gev_stage1_dir="${gev_target_env}/stage1"
gev_local_dir="${gev_target_env}/local"
check_and_create_dir "$gev_target_sysroot"
# 设置当前日志路径
LOG_PATH="${gev_target_env}/build.log"
log_info "init_by_env_name ok"
}
cacl_toolchain_name(){
local -n ret="$1"
local build="$2"
local host="$3"
local target="$4"
local ver="$5"
ver="${ver//\//_}"
ret="${ver}_${host}"
}
cacl_toolchain_name_cross(){
local ver="$2"
cacl_toolchain_name "${1}" "${gev_build}" "${gev_build}" "${gev_target}" "${ver}"
}
# env_name source_sysroot
init_env() {
init_by_env_name "${1}" "${3}"
local source_sysroot="${2}"
# cp -a "$source_sysroot/." "$gev_target_sysroot/"
if [[ -d "$gev_target_sysroot" ]] && [[ "$(ls -A "$gev_target_sysroot" 2>/dev/null)" ]]; then
log_info "sysroot already exists, skip copy: $gev_target_sysroot\n"
else
log_info "copy sysroot: [$source_sysroot] -> [$gev_target_sysroot]\n"
mkdir -p "$gev_target_sysroot"
check_directory_var source_sysroot
cp -a "$source_sysroot/." "$gev_target_sysroot/"
# rsync -aH --numeric-ids \
# --exclude='/dev/*' \
# --exclude='/proc/*' \
# --exclude='/sys/*' \
# --exclude='/run/*' \
# "$source_sysroot/" \
# "$gev_target_sysroot/"
# rsync -aH --numeric-ids \
# --include='/usr/' \
# --include='/usr/include/***' \
# --include='/usr/lib/***' \
# --include='/lib/***' \
# --include='/lib64/***' \
# --include='/etc/' \
# --include='/etc/ld.so.conf' \
# --include='/etc/ld.so.conf.d/***' \
# --exclude='*' \
# "$source_sysroot/" \
# "$gev_target_sysroot/"
# rsync -aH --numeric-ids \
# --include='/usr/' \
# --include='/usr/include/***' \
# --include='/usr/lib/' \
# --include="/usr/lib/${bge_target}/***" \
# --include='/usr/lib/gcc/' \
# --include="/usr/lib/gcc/${bge_target}/***" \
# --include='/lib/' \
# --include="/lib/${bge_target}/***" \
# --include='/lib64/***' \
# --include='/etc/' \
# --include='/etc/ld.so.conf' \
# --include='/etc/ld.so.conf.d/***' \
# --exclude='*' \
# "$source_sysroot/" \
# "$gev_target_sysroot/"
#copy_compile_sysroot_files "$source_sysroot" "$gev_target_sysroot" "$bge_target"
fi
log_info "env initialized: env=[${gev_target_env}] sysroot=[${gev_target_sysroot}]\n"
}
attach_env_stage1_gcc() {
log_info "attach_env_stage1_gcc start"
local target="$1"
local local_triplet local_triplet_no_vendor
detect_platform_triplet local_triplet local_triplet_no_vendor
bge_gcc_ver="${gev_stage1_gcc_ver}"
bge_stage1=1
bge_install_prefix="${gev_stage1_dir}/gcc_stage1_${target}"
bge_build="$local_triplet"
bge_host="$local_triplet"
bge_target="$target" #注意这一点 即使是cross 编译 stage1 gcc 永远是本机gcc
bge_sysroot_use_mode="link"
bge_source_sysroot="$bge_install_prefix/sysroot"
bge_toolchain_name="${gev_cur_toolchain_name}"
check_and_create_dir "${bge_source_sysroot}"
build_gcc_ex
log_info "attach_env_stage1_gcc end"
}
# env_name target 选项没配置对 目前编译到 glibc checking host system type... Invalid configuration `aarch64-linux-gnu': machine `aarch64' not recognized
init_env_build_sysroot() {
# https://stackoverflow.com/questions/28904902/how-do-i-change-gccs-default-search-directory-for-crti-o?utm_source=chatgpt.com
# https://gcc.gnu.org/onlinedocs/gcc/Spec-Files.html?utm_source=chatgpt.com
# https://gcc.gnu.org/onlinedocs/gccint/Driver.html?utm_source=chatgpt.com
# 第一处是 GCC 的 spec 机制文档。官方明确写了:
# %S:处理 startfile spec,也就是“决定哪些对象文件作为最先传给 linker 的文件”,典型就是 crt0.o、crt1.o、crti.o 这类启动文件。
# %E:处理 endfile spec,也就是“决定哪些对象文件作为最后传给 linker 的文件”,典型就是 crtn.o 这类收尾文件。
# 第二处是 GCC Internals 的 Driver 文档。里面把这些宏的职责写得更直接:
# STARTFILE_SPEC 指定标准 C startup file。
# ENDFILE_SPEC 指定标准 C end file。
# 文档还说明,如果没有定义这些宏,就会用默认值。
# 这意味着:
# crti.o、crt1.o 这类不是普通 -lxxx 库
# 它们走的是 STARTFILE_SPEC
# crtn.o 这类走的是 ENDFILE_SPEC
# 所以它们和 -lc、-lm 这类普通库的搜索规则不是一回事
# /ae/bash/0_git_cache_dir/gcc/build/gcc/specs
init_by_env_name "${1}"
local target="${2}"
local t_cpu t_vendor t_os t_abi
parse_triplet "$target" t_cpu t_vendor t_os t_abi
local linuxarch=$t_cpu
if [[ $linuxarch == "aarch64" ]]; then
linuxarch="arm64"
elif [[ $linuxarch =~ i[3-6]86 ]]; then
linuxarch="x86"
elif [[ $linuxarch != x86_64 ]]; then
linuxarch="${linuxarch%%[0-9]*}"
fi
# 参数检查:确保必要参数存在
if [[ -z "$target" ]]; then
log_error "ERROR: target is required for init_env_build_sysroot\n"
exit 1
fi
local build_triplet build_triplet_no_vendor
detect_platform_triplet build_triplet build_triplet_no_vendor
(
log_info "step 1 stage1_gcc构建失败 Starting kernel header installation...\n"
attach_env_stage1_gcc "${target}"
)
check_ret_exit "stage1_gcc构建失败!"
(
log_info "step 2 安装内核头文件 Starting kernel header installation... ${linuxarch} ${gev_linux_ver}\n"
local install_prefix="${gev_target_sysroot}/usr"
local src_dir
ensure_repo_version src_dir "linux" "${gev_linux_ver}"
cd $src_dir || exit 89
check_and_create_dir "${install_prefix}"
exec_record "make headers_install ARCH=${linuxarch} -j$(nproc) INSTALL_HDR_PATH=\"${install_prefix}\""
)
check_ret_exit "安装内核头文件失败!"
(
load_toolchains_under "$gev_stage1_dir"
local glibc_triplet
local glibc_cpu="${t_cpu}"
compose_triplet glibc_triplet "${glibc_cpu}" "" "${t_os}" "${t_abi}"
log_info "glibc_triplet ${glibc_triplet}\n"
local glibc_opts="\
--build=${build_triplet} \
--host=${target} \
--with-headers=${gev_target_sysroot}/usr/include \
--prefix=/usr \
--disable-werror \
--disable-nls \
${gev_glibc_suffix_opts}"
log_info " step 3 编译glibc Compiling glibc with options: $gev_target_sysroot\n"
log_info " glibc_opts: $glibc_opts\n"
local src_dir
ensure_repo_version src_dir "glibc" "${gev_glibc_ver}"
configure_gnu_ex "${src_dir}" "$glibc_opts"
exec_record_fast_fail "make -j $(nproc)"
exec_record_fast_fail "make -h"
exec_record_fast_fail "make install install_root=$gev_target_sysroot -j $(nproc)"
local src_dir="${gev_target_sysroot}/usr/lib64"
local dest_dir="${gev_target_sysroot}/lib"
check_directory "${src_dir}"
check_directory "${dest_dir}"
local array=(crt1.o crti.o crtn.o gcrt1.o Scrt1.o rcrt1.o)
log_info "cp [${array[*]}] ${src_dir} ==> ${dest_dir} "
for f in "${array[@]}"; do
local src_file="$src_dir/$f"
if [ -e "$src_file" ]; then
echo "copy $f"
cp -f "$src_file" "${dest_dir}"
fi
done
)
check_ret_exit "glibc 安装失败"
log_info " 自构建sysroot环境搭建完成 env initialized: env=${gev_target_env} sysroot=${gev_target_sysroot}\n"
}
cacl_toolchain_name_canadian(){
local host="$2"
local ver="$3"
cacl_toolchain_name "${1}" "${gev_build}" "${host}" "${gev_target}" "${ver}"
}
# target ver
attach_env_local_cross() {
log_info "attach_env_local_cross start"
local ver="$1"
local target="$gev_target"
[[ -z "$target" ]] && log_error "ERROR: target required\n" && exit 1
[[ -z "$ver" ]] && log_error "ERROR: ver required\n" && exit 1
(
[[ ! -d "$gev_target_sysroot" ]] && log_error "ERROR: env sysroot not found: $gev_target_sysroot\n" && exit 1
bge_build="$gev_local_triplet"
bge_host="$gev_local_triplet"
bge_target="$target"
local toolchain_name
cacl_toolchain_name_cross toolchain_name "${ver}"
bge_install_prefix="${gev_cross_dir}/${toolchain_name}"
bge_source_sysroot="$gev_target_sysroot"
bge_sysroot_use_mode="link"
bge_gcc_ver="${ver}"
bge_toolchain_name="${gev_cur_toolchain_name}"
build_gcc_ex
)
log_info "attach_env_local_cross end"
}
load_toolchains_under() {
local base="$1"
[[ -d "$base" ]] || return 0
local prefix trip
# base 下每个子目录当作一个工具链 prefix(例如 cross/gcc_xxx 或 canadian/gcc_xxx
for prefix in "$base"/*; do
[[ -d "$prefix" ]] || continue
[[ -d "$prefix/bin" ]] || continue
# prefix 下可能有 triplet 目录(aarch64-xxx-gnu 这类)
for trip in "$prefix"/*; do
[[ -d "$trip" ]] || continue
local n
n="$(basename "$trip")"
# 跳过常见非 triplet 目录
case "$n" in
bin | lib | lib64 | include | share | etc | var | tmp | sysroot | cross | canadian | libexec) continue ;;
esac
load_toolchain "$prefix" "$n"
log_info "loaded toolchain: prefix=$prefix triplet=$n\n"
# 满足目录形态才加载
if [[ -d "$prefix/$n/usr" || -d "$prefix/$n/sysroot/usr" || -d "$prefix/$n/sysroot/lib" ]]; then
load_toolchain "$prefix" "$n"
log_info "loaded toolchain: prefix=$prefix triplet=$n\n"
fi
done
done
}
# sudo apt install -y mingw-w64 gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64
# 注意这个函数调用前需要加载 前两个交叉编译环境 默认的windows "x86_64-w64-mingw32"
# host target ver
# TODO: host是windows时 要编译mingw运行时库 和 移动 gmp mpc mpfr等库 到 ${root}/bin 里去
attach_env_canadian_stage3() {
log_info "attach_env_canadian_stage3 start"
local host="$1"
local ver="$2"
local target="$gev_target"
bge_build="$gev_local_triplet"
bge_host="$host"
bge_target="$target"
local toolchain_name
local toolchain_name
cacl_toolchain_name_canadian toolchain_name "${host}" "${ver}"
bge_install_prefix="${gev_canadian_dir}/${toolchain_name}"
(
local target_toolchain_name host_toolchain_name
cacl_toolchain_name_cross target_toolchain_name "${ver}"
cacl_toolchain_name host_toolchain_name "${bge_build}" "${bge_build}" "${bge_host}" "${ver}"
local target_tool_chain="${gev_cross_dir}/${target_toolchain_name}"
local host_tool_chain="${gev_cross_dir}/${host_toolchain_name}"
if [[ -d "$target_tool_chain" ]]; then
load_toolchain "${target_tool_chain}" "${target}"
else
log_warn "target_tool_chain not exists: $target_tool_chain"
fi
if [[ -d "$host_tool_chain" ]]; then
load_toolchain "${host_tool_chain}" "${host}"
else
log_warn "host_tool_chain not exists: $host_tool_chain"
fi
bge_source_sysroot="$gev_target_sysroot"
bge_sysroot_use_mode="link"
bge_gcc_ver="${ver}"
bge_toolchain_name="${gev_cur_toolchain_name}"
build_gcc_ex
)
log_info "attach_env_canadian_stage3 end"
}
attach_host_tool_qt(){
bq_sysroot="${gev_target_sysroot}"
bq_cross=0
bq_install_prefix="${gev_local_dir}/Qt/${bq_ver}"
build_qt
}
attach_cross_tool_qt(){
bq_sysroot="${gev_target_sysroot}"
bq_cross=1
bq_host_tool_install_prefix="${gev_local_dir}/Qt/${bq_ver}"
bq_platform="linux-g++"
bq_xplatform="linux-aarch64-gnu-g++"
bq_install_prefix="${gev_cross_dir}/Qt/${bq_xplatform}/${bq_ver}"
log_info "attach_cross_tool_qt ${bq_install_prefix}"
build_qt
}
attach_cross_win_qt(){
bq_sysroot="${gev_target_sysroot}"
bq_cross=1
bq_platform="linux-g++"
bq_xplatform="linux-aarch64-gnu-g++"
bq_host_platform="win32-g++"
bq_install_prefix="${gev_target_env}/Qt/${bq_host_platform}_${bq_xplatform}/${bq_ver}"
bq_host_triplet="x86_64-w64-mingw32"
bq_target_triplet="aarch64-linux-gnu"
local h_cpu h_vendor h_os h_abi
local t_cpu t_vendor t_os t_abi
parse_triplet "${bq_host_triplet}" h_cpu h_vendor h_os h_abi
parse_triplet "${bq_target_triplet}" t_cpu t_vendor t_os t_abi
log_info "host cpu[${h_cpu}] vendor[${h_vendor}] os[${h_os}] abi[${h_abi}] \n"
log_info "target cpu[${t_cpu}] vendor[${t_vendor}] os[${t_os}] abi[${t_abi}] \n"
log_info "attach_cross_tool_qt ${bq_install_prefix}"
build_qt
}
attach_win_2_arm_qt(){
bq_sysroot="${gev_target_sysroot}"
bq_cross=1
bq_host_tool_install_prefix="${gev_local_dir}/Qt/${bq_ver}"
bq_platform="linux-g++"
bq_xplatform="linux-aarch64-gnu-g++"
bq_install_prefix="${gev_cross_dir}/Qt/${bq_xplatform}/${bq_ver}"
log_info "attach_cross_tool_qt ${bq_install_prefix}"
build_qt
}
@@ -0,0 +1,16 @@
if ! type "include" > /dev/null 2>&1; then
include() {
. "$(cd "$(dirname "$1")" && pwd)/${2}";
};
fi
include "${BASH_SOURCE[0]}" ../pragma_once.bash
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
include "${BASH_SOURCE[0]}" ./core.bash
# shellcheck source=./core.bash
return 0