scripts: update build_kernel.sh to support build in docker
Usage: Run on the top of linux directory ./scripts/build_kernel.sh [-c] [-d] [-x] Change-Id: If33a505cae9cdbc8560aeaee62cad5a0524a0d54
This commit is contained in:
@@ -1,65 +1,319 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
SCRIPT="./scripts/build_kernel.sh"
|
||||
PACKAGE_SRC_NAME="linux-riscv-spacemit"
|
||||
CLEAN_CMD="make distclean &&
|
||||
VERSION=\$(grep -oP '^VERSION\\s*=\\s*\\K\\d+' Makefile)
|
||||
PATCHLEVEL=\$(grep -oP '^PATCHLEVEL\\s*=\\s*\\K\\d+' Makefile)
|
||||
SUBLEVEL=\$(grep -oP '^SUBLEVEL\\s*=\\s*\\K\\d+' Makefile)
|
||||
export KERNELRELEASE=\$VERSION.\$PATCHLEVEL.\$SUBLEVEL &&
|
||||
rm -f ../linux-headers-\$KERNELRELEASE_*_riscv64.deb &&
|
||||
rm -f ../linux-image-\$KERNELRELEASE_*_riscv64.deb &&
|
||||
rm -f ../linux-image-\$KERNELRELEASE-dbg_*_riscv64.deb &&
|
||||
rm -f ../linux-tools-\$KERNELRELEASE_*_riscv64.deb &&
|
||||
rm -f ../linux-libc-dev_*_riscv64.deb &&
|
||||
rm -f ../linux-tools-common_*_all.deb &&
|
||||
rm -f ../linux-riscv-spacemit_*_riscv64.*
|
||||
"
|
||||
BUILD_CMD='make k1_defconfig && make -j$(nproc)'
|
||||
BUILD_DEB_CMD="make k1_defconfig &&
|
||||
sed -i '/CONFIG_INITRAMFS_SOURCE=/d' arch/riscv/configs/k1_defconfig
|
||||
VERSION=\$(grep -oP '^VERSION\\s*=\\s*\\K\\d+' Makefile)
|
||||
PATCHLEVEL=\$(grep -oP '^PATCHLEVEL\\s*=\\s*\\K\\d+' Makefile)
|
||||
SUBLEVEL=\$(grep -oP '^SUBLEVEL\\s*=\\s*\\K\\d+' Makefile)
|
||||
export KERNELRELEASE=\$VERSION.\$PATCHLEVEL.\$SUBLEVEL
|
||||
export LOCALVERSION=\"\"
|
||||
KDEB_SOURCENAME=$PACKAGE_SRC_NAME \\
|
||||
KDEB_PKGVERSION=\$KERNELRELEASE-\$(TZ=Asia/Shanghai date +\"%Y%m%d%H%M%S\") \\
|
||||
KDEB_CHANGELOG_DIST=noble-porting \\
|
||||
make -j\$(nproc) bindeb-pkg
|
||||
"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SOURCE_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
SOURCE_PARENT_DIR="$(cd "$SOURCE_DIR/.." && pwd)"
|
||||
DOCKER_REPO="${DOCKER_REPO:-harbor.spacemit.com/bianbu-linux}"
|
||||
IMAGE_NAME="${IMAGE_NAME:-bianbu-linux-builder:latest}"
|
||||
CROSS_COMPILE="${CROSS_COMPILE:-riscv64-unknown-linux-gnu-}"
|
||||
TOOLCHAIN_PATH="${TOOLCHAIN_PATH:-/opt/spacemit-toolchain-linux-glibc-x86_64-v1.0.0/bin}"
|
||||
DIRECT_BUILD="${DIRECT_BUILD:-0}"
|
||||
|
||||
CLEAN=false
|
||||
BUILD_DEB=false
|
||||
ACTION="build"
|
||||
DEBUG=false
|
||||
|
||||
while getopts "cdh" opt
|
||||
do
|
||||
case $opt in
|
||||
c)
|
||||
# Function to handle symlinks within git directory
|
||||
handle_git_internal_symlinks() {
|
||||
local git_dir="$1"
|
||||
local container_git_dir="$2"
|
||||
local -n git_mounts_ref="$3" # Reference to the git mounts array
|
||||
|
||||
[ "$DEBUG" = true ] && echo "Scanning for symlinks in git directory: $git_dir"
|
||||
|
||||
# Find all symlinks in the git directory
|
||||
while IFS= read -r -d '' symlink; do
|
||||
if [ -L "$symlink" ]; then
|
||||
local real_target
|
||||
real_target="$(readlink -f "$symlink")"
|
||||
local relative_path="${symlink#$git_dir/}"
|
||||
local container_target="$container_git_dir/$relative_path"
|
||||
|
||||
if [ -e "$real_target" ]; then
|
||||
[ "$DEBUG" = true ] && echo "Found symlink: $relative_path -> $real_target"
|
||||
# Store mounts in the array - add both -v and the mount path
|
||||
git_mounts_ref+=("-v" "$real_target:$container_target")
|
||||
else
|
||||
[ "$DEBUG" = true ] && echo "Warning: Broken symlink found: $symlink -> $real_target"
|
||||
fi
|
||||
fi
|
||||
done < <(find "$git_dir" -type l -print0 2>/dev/null)
|
||||
}
|
||||
|
||||
# Function to setup all container volume mounts (including git handling)
|
||||
setup_volume_mounts() {
|
||||
local project_dir="$1"
|
||||
local package_dir="$2"
|
||||
local git_path="$package_dir/.git"
|
||||
local container_base
|
||||
container_base="/workspace/$(basename "$package_dir")"
|
||||
|
||||
# Local git_mounts array for this function
|
||||
local git_mounts=()
|
||||
|
||||
[ "$DEBUG" = true ] && echo "Setting up container volume mounts..."
|
||||
|
||||
# Initialize with basic mounts
|
||||
VOLUME_MOUNTS=("-v" "$project_dir:/workspace" "-w" "$container_base")
|
||||
|
||||
# Handle git directory if exists
|
||||
if [ -e "$git_path" ]; then
|
||||
local actual_git_dir
|
||||
local container_git_path="$container_base/.git"
|
||||
|
||||
if [ -L "$git_path" ]; then
|
||||
[ "$DEBUG" = true ] && echo "Detected .git as symbolic link, resolving real git directory..."
|
||||
actual_git_dir="$(readlink -f "$git_path")"
|
||||
|
||||
if [ ! -d "$actual_git_dir" ]; then
|
||||
echo "Error: Cannot find real git directory: $actual_git_dir"
|
||||
echo "Please ensure the git repository is accessible."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Set up main git directory mount
|
||||
git_mounts+=("-v" "$actual_git_dir:$container_git_path")
|
||||
[ "$DEBUG" = true ] && echo "Will mount real git directory: $actual_git_dir -> $container_git_path"
|
||||
|
||||
elif [ -d "$git_path" ]; then
|
||||
[ "$DEBUG" = true ] && echo "Found normal .git directory"
|
||||
actual_git_dir="$git_path"
|
||||
# For normal directories, no additional mount needed as it's part of the main project mount
|
||||
|
||||
else
|
||||
[ "$DEBUG" = true ] && echo "Warning: .git exists but is neither a directory nor a symlink"
|
||||
actual_git_dir=""
|
||||
fi
|
||||
|
||||
# Handle symlinks within the git directory
|
||||
if [ -n "$actual_git_dir" ]; then
|
||||
handle_git_internal_symlinks "$actual_git_dir" "$container_git_path" git_mounts
|
||||
fi
|
||||
else
|
||||
[ "$DEBUG" = true ] && echo "Warning: No .git directory found, some git operations may fail"
|
||||
fi
|
||||
|
||||
# Add all git mounts (both main directory and internal symlinks)
|
||||
if [ ${#git_mounts[@]} -gt 0 ]; then
|
||||
VOLUME_MOUNTS+=("${git_mounts[@]}")
|
||||
[ "$DEBUG" = true ] && echo "Added $(( ${#git_mounts[@]} / 2 )) git-related mounts"
|
||||
fi
|
||||
|
||||
[ "$DEBUG" = true ] && echo "Total volume mounts configured: $(( (${#VOLUME_MOUNTS[@]} + 1) / 2 ))"
|
||||
# fix this function will exit if bash set -e
|
||||
return 0
|
||||
}
|
||||
|
||||
# Setup container volume mounts (includes git handling)
|
||||
setup_volume_mounts "$SOURCE_PARENT_DIR" "$SOURCE_DIR"
|
||||
|
||||
usage() {
|
||||
echo "Container-based build wrapper (universal version)"
|
||||
echo "Usage: $(basename "$0") [OPTIONS] [COMMAND]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -c, --clean Clean build (CLEAN_CMD before BUILD[_DEB]_CMD)"
|
||||
echo " -d, --deb Build DEB packages (BUILD_DEB_CMD)"
|
||||
echo " -h, --help Show this help message"
|
||||
echo " -x, --debug Enable debug output (show docker command)"
|
||||
echo ""
|
||||
echo "Commands (run inside container):"
|
||||
echo " build Build (BUILD_CMD, default)"
|
||||
echo " shell Interactive shell"
|
||||
echo ""
|
||||
echo "Examples:"
|
||||
echo " $(basename "$0") # Build in container"
|
||||
echo " $(basename "$0") -c -d # Clean build with DEB packages"
|
||||
echo " $(basename "$0") shell # Interactive container shell"
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-c|--clean)
|
||||
CLEAN=true
|
||||
shift
|
||||
;;
|
||||
d)
|
||||
-d|--deb)
|
||||
BUILD_DEB=true
|
||||
shift
|
||||
;;
|
||||
?)
|
||||
echo "Usage: Run on the top of linux directory"
|
||||
echo "$SCRIPT [-c] [-d]"
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
-x|--debug)
|
||||
DEBUG=true
|
||||
shift
|
||||
;;
|
||||
build|shell)
|
||||
ACTION="$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ $0 != $SCRIPT ]
|
||||
then
|
||||
echo "Run $(basename $SCRIPT) on the top of linux directory"
|
||||
# Check if Docker is available
|
||||
if ! command -v docker &> /dev/null; then
|
||||
echo "Error: Docker not found. Please install Docker."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
command -v riscv64-unknown-linux-gnu-gcc > /dev/null || \
|
||||
(echo "Install cross compile and add to PATH" && exit 1)
|
||||
|
||||
VERSION=$(grep -oP '^VERSION\s*=\s*\K\d+' Makefile)
|
||||
PATCHLEVEL=$(grep -oP '^PATCHLEVEL\s*=\s*\K\d+' Makefile)
|
||||
SUBLEVEL=$(grep -oP '^SUBLEVEL\s*=\s*\K\d+' Makefile)
|
||||
export ARCH=riscv
|
||||
export CROSS_COMPILE=riscv64-unknown-linux-gnu-
|
||||
export KERNELRELEASE=$VERSION.$PATCHLEVEL.$SUBLEVEL
|
||||
export LOCALVERSION=""
|
||||
|
||||
if [ $CLEAN = true ]
|
||||
then
|
||||
make distclean
|
||||
if [ $BUILD_DEB = true ]
|
||||
then
|
||||
rm -f ../linux-headers-$KERNELRELEASE_*_riscv64.deb
|
||||
rm -f ../linux-image-$KERNELRELEASE_*_riscv64.deb
|
||||
rm -f ../linux-image-$KERNELRELEASE-dbg_*_riscv64.deb
|
||||
rm -f ../linux-libc-dev_*_riscv64.deb
|
||||
rm -f ../linux-riscv-spacemit_*_riscv64.*
|
||||
# Set DEBEMAIL and DEBFULLNAME environment variable
|
||||
if [ -z "$DEBEMAIL" ]; then
|
||||
if [ -n "$MAIL" ]; then
|
||||
DEBEMAIL="$MAIL"
|
||||
else
|
||||
DEBEMAIL="$(id -nu)@$(hostname -f 2>/dev/null || hostname)"
|
||||
fi
|
||||
fi
|
||||
|
||||
make k1_defconfig
|
||||
|
||||
if [ $BUILD_DEB = true ]
|
||||
then
|
||||
KDEB_SOURCENAME=linux-riscv-spacemit \
|
||||
KDEB_PKGVERSION=$KERNELRELEASE-$(TZ=Asia/Shanghai date +"%Y%m%d%H%M%S") \
|
||||
KDEB_CHANGELOG_DIST=mantic-porting \
|
||||
make -j$(nproc) bindeb-pkg
|
||||
else
|
||||
make -j$(nproc)
|
||||
if [ -z "$DEBFULLNAME" ]; then
|
||||
if [ -n "$NAME" ]; then
|
||||
DEBFULLNAME="$NAME"
|
||||
elif echo "$DEBEMAIL" | grep -qE '^([^<]+)\s*<[^>]+>$'; then
|
||||
# If DEBEMAIL matches "name <email>", extract name as DEBFULLNAME
|
||||
DEBFULLNAME="$(echo "$DEBEMAIL" | sed -n 's/^\([^<][^<]*\)<.*$/\1/p' | sed 's/[[:space:]]*$//')"
|
||||
else
|
||||
DEBFULLNAME="$(id -nu)"
|
||||
fi
|
||||
fi
|
||||
|
||||
CONTAINER_ENV=("-e" "ARCH=riscv" "-e" "CROSS_COMPILE=$CROSS_COMPILE" "-e" "PATH=$TOOLCHAIN_PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" "-e" "DEBEMAIL=$DEBEMAIL" "-e" "DEBFULLNAME=$DEBFULLNAME")
|
||||
|
||||
# Function to create user permission files for container
|
||||
create_user_files() {
|
||||
local current_user current_group
|
||||
current_user="$(whoami):x:$(id -u):$(id -g):$(whoami),,,:/home/$(whoami):/bin/bash"
|
||||
current_group="$(id -gn):x:$(id -g):"
|
||||
|
||||
# Create or update .passwd and .group files
|
||||
if [ ! -f "$SOURCE_DIR/.passwd" ] || \
|
||||
[ ! -f "$SOURCE_DIR/.group" ] || \
|
||||
[ "$current_user" != "$(grep "^$(whoami):" "$SOURCE_DIR/.passwd" 2>/dev/null)" ] || \
|
||||
[ "$current_group" != "$(grep "^$(id -gn):" "$SOURCE_DIR/.group" 2>/dev/null)" ]; then
|
||||
cp /etc/passwd "$SOURCE_DIR/.passwd.tmp"
|
||||
cp /etc/group "$SOURCE_DIR/.group.tmp"
|
||||
|
||||
if ! grep -q "^$(whoami):" "$SOURCE_DIR/.passwd.tmp"; then
|
||||
echo "$current_user" >> "$SOURCE_DIR/.passwd.tmp"
|
||||
fi
|
||||
|
||||
if ! grep -q "^$(id -gn):" "$SOURCE_DIR/.group.tmp"; then
|
||||
echo "$current_group" >> "$SOURCE_DIR/.group.tmp"
|
||||
fi
|
||||
|
||||
mv "$SOURCE_DIR/.passwd.tmp" "$SOURCE_DIR/.passwd"
|
||||
mv "$SOURCE_DIR/.group.tmp" "$SOURCE_DIR/.group"
|
||||
fi
|
||||
}
|
||||
|
||||
# Create user permission files
|
||||
create_user_files
|
||||
|
||||
# Function to run command in container
|
||||
run_in_container() {
|
||||
local cmd="$1"
|
||||
|
||||
if [ "$DEBUG" = true ]; then
|
||||
echo "--- Docker/Podman full command ---"
|
||||
local full_cmd
|
||||
full_cmd="docker run --rm -it --init"
|
||||
for v in "${VOLUME_MOUNTS[@]}"; do
|
||||
full_cmd+=" $v"
|
||||
done
|
||||
for e in "${CONTAINER_ENV[@]}"; do
|
||||
full_cmd+=" $e"
|
||||
done
|
||||
full_cmd+=" -v $SOURCE_DIR/.passwd:/etc/passwd:ro"
|
||||
full_cmd+=" -v $SOURCE_DIR/.group:/etc/group:ro"
|
||||
full_cmd+=" -u $(id -u):$(id -g)"
|
||||
full_cmd+=" $DOCKER_REPO/$IMAGE_NAME"
|
||||
full_cmd+=" bash -c \"$cmd\""
|
||||
echo "$full_cmd"
|
||||
echo "--- End docker command ---"
|
||||
fi
|
||||
|
||||
docker run --rm -it --init \
|
||||
"${VOLUME_MOUNTS[@]}" \
|
||||
"${CONTAINER_ENV[@]}" \
|
||||
-v "$SOURCE_DIR/.passwd:/etc/passwd:ro" \
|
||||
-v "$SOURCE_DIR/.group:/etc/group:ro" \
|
||||
-u "$(id -u):$(id -g)" \
|
||||
"$DOCKER_REPO/$IMAGE_NAME" \
|
||||
bash -c "$cmd"
|
||||
}
|
||||
|
||||
# Run command directly or in container based on DIRECT_BUILD
|
||||
run_command() {
|
||||
local cmd="$1"
|
||||
if [ -n "$DIRECT_BUILD" ] && [ "$DIRECT_BUILD" != "0" ]; then
|
||||
[ "$DEBUG" = true ] && echo "[DIRECT_BUILD] Executing locally: $cmd"
|
||||
command -v riscv64-unknown-linux-gnu-gcc > /dev/null || \
|
||||
(echo "Install cross compile and add to PATH" && exit 1)
|
||||
export ARCH=riscv
|
||||
export CROSS_COMPILE=riscv64-unknown-linux-gnu-
|
||||
bash -c "$cmd"
|
||||
else
|
||||
[ "$DEBUG" = true ] && echo "Building in container..."
|
||||
run_in_container "$cmd"
|
||||
fi
|
||||
}
|
||||
|
||||
# Execute container actions
|
||||
case "$ACTION" in
|
||||
build)
|
||||
if [[ "$CLEAN" == true ]]; then
|
||||
run_command "$CLEAN_CMD"
|
||||
fi
|
||||
if [[ "$BUILD_DEB" == true ]]; then
|
||||
run_command "$BUILD_DEB_CMD"
|
||||
else
|
||||
run_command "$BUILD_CMD"
|
||||
fi
|
||||
echo "Build completed successfully!"
|
||||
;;
|
||||
shell)
|
||||
run_in_container "bash"
|
||||
echo "Container shell session ended."
|
||||
;;
|
||||
*)
|
||||
echo "Unknown action: $ACTION"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -155,7 +155,7 @@ else
|
||||
fi
|
||||
sourcename=${KDEB_SOURCENAME:-linux-upstream}
|
||||
|
||||
kernelgitver=$(git rev-parse --short HEAD)
|
||||
kernelgitver=$(git rev-parse --short HEAD) || echo ""
|
||||
|
||||
if [ "$ARCH" = "um" ] ; then
|
||||
packagename=user-mode-linux
|
||||
|
||||
Reference in New Issue
Block a user