首次提交
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user