2023-08-31 19:41:37 +08:00
|
|
|
#!/bin/bash
|
|
|
|
|
|
|
|
set -e
|
|
|
|
|
|
|
|
self=$0
|
|
|
|
|
|
|
|
defconfig_command="$self defconfig"
|
|
|
|
clean_command="$self clean"
|
|
|
|
|
|
|
|
cmake_build_dir="build"
|
|
|
|
cmake_cache_file="build/CMakeCache.txt"
|
|
|
|
cmake_user_build_dir="user/build"
|
|
|
|
cmake_kernel_build_dir="kernel/build"
|
|
|
|
cmake_libc_build_dirs="user/musl-1.1.24/build user/musl-1.1.24/obj"
|
|
|
|
|
|
|
|
cmake_script_dir="scripts/build/cmake"
|
|
|
|
cmake_init_cache_default="$cmake_script_dir/LoadConfigDefault.cmake"
|
|
|
|
cmake_init_cache_ask="$cmake_script_dir/LoadConfigAsk.cmake"
|
|
|
|
cmake_init_cache_abort="$cmake_script_dir/LoadConfigAbort.cmake"
|
|
|
|
cmake_init_cache_dump="$cmake_script_dir/DumpConfig.cmake"
|
|
|
|
|
|
|
|
config_file=".config"
|
|
|
|
defconfig_dir="scripts/build/defconfigs"
|
|
|
|
|
|
|
|
RED='\033[0;31m'
|
|
|
|
BLUE='\033[0;34m'
|
|
|
|
GREEN='\033[0;32m'
|
|
|
|
ORANGE='\033[0;33m'
|
|
|
|
BOLD='\033[1m'
|
|
|
|
NONE='\033[0m'
|
|
|
|
|
|
|
|
_echo_info() {
|
|
|
|
echo -e "${BOLD}$@${NONE}"
|
|
|
|
}
|
|
|
|
|
|
|
|
_echo_succ() {
|
|
|
|
echo -e "${GREEN}${BOLD}$@${NONE}"
|
|
|
|
}
|
|
|
|
|
|
|
|
_echo_warn() {
|
|
|
|
echo -e "${ORANGE}${BOLD}$@${NONE}"
|
|
|
|
}
|
|
|
|
|
|
|
|
_echo_err() {
|
|
|
|
echo -e "${RED}${BOLD}$@${NONE}"
|
|
|
|
}
|
|
|
|
|
|
|
|
defconfig() {
|
|
|
|
if [ -d $cmake_build_dir ]; then
|
|
|
|
_echo_err "There exists a build directory, please run \`$clean_command\` first"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
plat="raspi3"
|
|
|
|
else
|
|
|
|
plat="$1"
|
|
|
|
fi
|
|
|
|
|
|
|
|
_echo_info "Generating default config file for \`$plat\` platform..."
|
|
|
|
cp $defconfig_dir/${plat}.config $config_file
|
|
|
|
_config_default
|
|
|
|
_sync_config_with_cache
|
|
|
|
_echo_succ "Default config written to \`$config_file\` file."
|
|
|
|
}
|
|
|
|
|
|
|
|
_check_config_file() {
|
|
|
|
if [ ! -f $config_file ]; then
|
|
|
|
_echo_err "There is no \`.config\` file, please run \`$defconfig_command\` first"
|
|
|
|
exit 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
_config_default() {
|
|
|
|
_echo_info "Configuring CMake..."
|
|
|
|
cmake -B $cmake_build_dir -C $cmake_init_cache_default
|
|
|
|
}
|
|
|
|
|
|
|
|
_config_ask() {
|
|
|
|
_echo_info "Configuring CMake..."
|
|
|
|
cmake -B $cmake_build_dir -C $cmake_init_cache_ask
|
|
|
|
}
|
|
|
|
|
|
|
|
_sync_config_with_cache() {
|
|
|
|
cmake -N -B $cmake_build_dir -C $cmake_init_cache_dump >/dev/null
|
|
|
|
}
|
|
|
|
|
|
|
|
config() {
|
|
|
|
_check_config_file
|
|
|
|
_config_ask
|
|
|
|
_sync_config_with_cache
|
|
|
|
_echo_succ "Config syned to \`$config_file\` file."
|
|
|
|
}
|
|
|
|
|
|
|
|
menuconfig() {
|
|
|
|
_check_config_file
|
|
|
|
_config_default
|
|
|
|
|
|
|
|
echo
|
|
|
|
_echo_warn "Note: In the menu config view, press C to save, Q to quit."
|
|
|
|
read -p "Now press Enter to continue..."
|
|
|
|
|
|
|
|
ccmake -B $cmake_build_dir
|
|
|
|
_sync_config_with_cache
|
|
|
|
_echo_succ "Config saved to \`$config_file\` file."
|
|
|
|
}
|
|
|
|
|
|
|
|
build() {
|
|
|
|
_check_config_file
|
|
|
|
_config_ask
|
|
|
|
_sync_config_with_cache
|
|
|
|
_echo_succ "Config syned to \`$config_file\` file."
|
|
|
|
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
build_target="all"
|
|
|
|
else
|
|
|
|
build_target="$1"
|
|
|
|
fi
|
|
|
|
|
|
|
|
_echo_info "Building..."
|
|
|
|
cmake --build $cmake_build_dir --target $build_target --parallel $(nproc)
|
|
|
|
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
_echo_succ "Succeeded to build all targets"
|
|
|
|
else
|
|
|
|
_echo_succ "Succeeded to build \`$build_target\`"
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
clean() {
|
|
|
|
_echo_info "Cleaning..."
|
|
|
|
|
|
|
|
if [ -z "$1" ]; then
|
|
|
|
if [ -f $cmake_cache_file ]; then
|
|
|
|
rm -rf $cmake_build_dir
|
|
|
|
_config_default
|
|
|
|
cmake --build $cmake_build_dir --target clean-all
|
|
|
|
rm -rf $cmake_build_dir
|
|
|
|
_echo_succ "Succeeded to clean all targets"
|
|
|
|
elif [ -d $cmake_build_dir ]; then
|
|
|
|
rm -rf $cmake_build_dir $cmake_user_build_dir $cmake_kernel_build_dir $cmake_libc_build_dirs
|
|
|
|
_echo_warn "Succeeded to clean all targets, but some object files may be left"
|
|
|
|
else
|
|
|
|
_echo_info "Nothing to clean"
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
if [ -f $cmake_cache_file ]; then
|
|
|
|
cmake --build $cmake_build_dir --target $1-clean
|
|
|
|
_echo_succ "Succeeded to clean \`$1\`"
|
|
|
|
else
|
|
|
|
_echo_err "Cannot clean \`$1\`, please try \`$self clean\` to clean all"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
distclean() {
|
|
|
|
clean
|
|
|
|
_echo_info "Removing config file..."
|
|
|
|
rm -rf $config_file
|
|
|
|
|
|
|
|
_echo_succ "Succeeded to distclean"
|
|
|
|
}
|
|
|
|
|
|
|
|
_print_help() {
|
|
|
|
echo -e "\
|
|
|
|
${BOLD}USAGE:${NONE}
|
|
|
|
|
|
|
|
${BOLD}$self [options] [command]${NONE}
|
|
|
|
|
|
|
|
${BOLD}OPTIONS:${NONE}
|
|
|
|
|
|
|
|
${BOLD}--local, -l${NONE} run command in local environment (rather than docker)
|
|
|
|
|
|
|
|
${BOLD}COMMANDS:${NONE}
|
|
|
|
|
|
|
|
Local:
|
|
|
|
|
|
|
|
${BOLD}help, --help, -h${NONE} print this help text
|
|
|
|
${BOLD}update-submodules${NONE} update Git submodules according to config file
|
|
|
|
|
|
|
|
Local or Docker:
|
|
|
|
|
|
|
|
${BOLD}defconfig [platform]${NONE} generate default config (\`raspi3\` if \`platform\` is not specified)
|
|
|
|
${BOLD}config${NONE} run configuration step (interactively ask for config value if not set)
|
|
|
|
${BOLD}menuconfig${NONE} use TUI menu to edit config
|
|
|
|
${BOLD}build [target]${NONE} build the project (\`target\` can be \`libc\`, \`user\`, \`kernel\` or empty)
|
|
|
|
${BOLD}clean [target]${NONE} clean the project (\`target\` can be \`libc\`, \`user\`, \`kernel\` or empty)
|
|
|
|
${BOLD}distclean${NONE} clean the project and remove config file
|
|
|
|
"
|
|
|
|
}
|
|
|
|
|
|
|
|
_update_submodules() {
|
|
|
|
if [ -d $cmake_build_dir/local ]; then
|
|
|
|
rm -rf $cmake_build_dir/local
|
|
|
|
fi
|
|
|
|
|
|
|
|
_echo_info "Configuring CMake in local environment..."
|
|
|
|
cmake -B $cmake_build_dir/local -C $cmake_init_cache_abort
|
|
|
|
|
|
|
|
_echo_info "Updating Git submodules..."
|
|
|
|
cmake --build $cmake_build_dir/local --target update-submodules
|
|
|
|
|
|
|
|
rm -rf $cmake_build_dir/local
|
|
|
|
|
|
|
|
_echo_succ "Succeeded to update submodules"
|
|
|
|
}
|
|
|
|
|
|
|
|
_docker_run() {
|
|
|
|
if [ -f /.dockerenv ]; then
|
|
|
|
# we are already in docker container
|
|
|
|
$@
|
|
|
|
else
|
|
|
|
test -t 1 && use_tty="-t"
|
2023-09-09 22:13:16 +08:00
|
|
|
docker run -i $use_tty --rm \
|
|
|
|
-u $(id -u ${USER}):$(id -g ${USER}) \
|
2023-08-31 19:41:37 +08:00
|
|
|
-v $(pwd):/chos -w /chos \
|
|
|
|
promisivia/treesls_chcore_builder:v2.2 \
|
|
|
|
$self $@
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
_main() {
|
|
|
|
run_in_docker=true
|
|
|
|
while [ $# -gt 0 ]; do
|
|
|
|
case $1 in
|
|
|
|
help | --help | -h)
|
|
|
|
_print_help
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
--local | -l)
|
|
|
|
run_in_docker=false
|
|
|
|
;;
|
|
|
|
-*)
|
|
|
|
_echo_err "$self: invalid option \`$1\`\n"
|
|
|
|
break
|
|
|
|
;;
|
|
|
|
update-submodules)
|
|
|
|
# need Git SSH key authentication, so must run in local env
|
|
|
|
_update_submodules
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
if [[ "$1" == "_"* || $(type -t "$1") != function ]]; then
|
|
|
|
_echo_err "$self: invalid command \`$1\`\n"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [[ $run_in_docker == true ]]; then
|
|
|
|
_docker_run $@
|
|
|
|
else
|
|
|
|
$@
|
|
|
|
fi
|
|
|
|
exit
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
# no command is run
|
|
|
|
_print_help
|
|
|
|
exit 1
|
|
|
|
}
|
|
|
|
|
|
|
|
_main $@
|