pmbootstrap/helpers/envkernel.sh

279 lines
6.0 KiB
Bash

#!/bin/sh
# Copyright 2018 Oliver Smith
# SPDX-License-Identifier: GPL-3.0-or-later
#
# usage example:
# $ cd ~/code/linux
# $ source ~/code/pmbootstrap/helpers/envkernel.sh
check_kernel_folder() {
[ -e "Kbuild" ] && return
echo "ERROR: This folder is not a linux source tree: $PWD"
return 1
}
clean_kernel_src_dir() {
if [ -f ".config" ] || [ -d "include/config" ]; then
echo "Source directory is not clean, running 'make mrproper'."
tmp_dir=""
if [ -d ".output" ]; then
echo " * Preserving existing build output."
tmp_dir=$(mktemp -d)
sudo mv ".output" "$tmp_dir"
fi;
# backslash is prefixed to disable the alias
# shellcheck disable=SC1001
\make mrproper
if [ ! -z "$tmp_dir" ]; then
sudo mv "$tmp_dir/.output" ".output"
sudo rmdir "$tmp_dir"
fi;
fi;
}
export_pmbootstrap_dir() {
# Get pmbootstrap dir based on this script's location
# See also: <https://stackoverflow.com/a/29835459>
# shellcheck disable=SC2039
if [ -n "${BASH_SOURCE[0]}" ]; then
script_dir="$(dirname "${BASH_SOURCE[0]}")"
else
script_dir="$(dirname "$1")"
fi
# Fail with debug information
# shellcheck disable=SC2155
export pmbootstrap_dir=$(realpath "$script_dir/..")
if ! [ -e "$pmbootstrap_dir/pmbootstrap.py" ]; then
echo "ERROR: Failed to get the script's location with your shell."
echo "Please adjust export_pmbootstrap_dir in envkernel.sh. Debug info:"
echo "\$1: $1"
echo "\$pmbootstrap_dir: $pmbootstrap_dir"
return 1
fi
}
set_alias_pmbootstrap() {
pmbootstrap="$pmbootstrap_dir"/pmbootstrap.py
# shellcheck disable=SC2139
alias pmbootstrap="$pmbootstrap"
if [ -e ~/.config/pmbootstrap.cfg ]; then
$pmbootstrap work_migrate
else
echo "NOTE: First run of pmbootstrap, running 'pmbootstrap init'"
$pmbootstrap init
fi
}
export_chroot_device_deviceinfo() {
chroot="$($pmbootstrap config work)/chroot_native"
device="$($pmbootstrap config device)"
deviceinfo="$pmbootstrap_dir/aports/device/device-$device/deviceinfo"
export chroot device deviceinfo
}
check_device() {
[ -e "$deviceinfo" ] && return
echo "ERROR: Please select a valid device in 'pmbootstrap init'"
return 1
}
initialize_chroot() {
gcc_pkgname="gcc"
if [ "$gcc6_arg" = "1" ]; then
gcc_pkgname="gcc6"
fi
# Don't initialize twice
flag="$chroot/tmp/envkernel/${gcc_pkgname}_setup_done"
[ -e "$flag" ] && return
# Install needed packages
echo "Initializing Alpine chroot (details: 'pmbootstrap log')"
# shellcheck disable=SC2154
$pmbootstrap -q chroot -- apk -q add \
abuild \
bc \
binutils-"$deviceinfo_arch" \
binutils \
bison \
flex \
"$gcc_pkgname"-"$deviceinfo_arch" \
"$gcc_pkgname" \
linux-headers \
libressl-dev \
make \
musl-dev \
ncurses-dev \
perl || return 1
# Create /mnt/linux
sudo mkdir -p "$chroot/mnt/linux"
# Mark as initialized
mkdir -p "$chroot/tmp/envkernel"
touch "$flag"
}
mount_kernel_source() {
[ -e "$chroot/mnt/linux/Kbuild" ] && return
sudo mount --bind "$PWD" "$chroot/mnt/linux"
}
create_output_folder() {
[ -d "$chroot/mnt/linux/.output" ] && return
mkdir -p ".output"
$pmbootstrap -q chroot -- chown -R pmos:pmos "/mnt/linux/.output"
}
set_alias_make() {
# Cross compiler prefix
# shellcheck disable=SC1090
prefix="$(. "$chroot/usr/share/abuild/functions.sh";
arch_to_hostspec "$deviceinfo_arch")"
# Kernel architecture
case "$deviceinfo_arch" in
aarch64*) arch="arm64" ;;
arm*) arch="arm" ;;
esac
if [ "$gcc6_arg" = "1" ]; then
cross_compiler="/usr/bin/gcc6-$prefix-"
else
cross_compiler="/usr/bin/$prefix-"
fi
# Build make command
cmd="echo '*** pmbootstrap envkernel.sh active for $PWD! ***';"
cmd="$cmd pmbootstrap -q chroot --"
cmd="$cmd ARCH=$arch"
cmd="$cmd CROSS_COMPILE=$cross_compiler"
cmd="$cmd make -C /mnt/linux O=/mnt/linux/.output"
# shellcheck disable=SC2139
alias make="$cmd"
}
set_alias_pmbroot_kernelroot() {
# shellcheck disable=SC2139
alias pmbroot="cd '$pmbootstrap_dir'"
# shellcheck disable=SC2139
alias kernelroot="cd '$PWD'"
}
cross_compiler_version() {
pmbootstrap chroot --user -- "${cross_compiler}gcc" --version \
2> /dev/null | grep "^.*gcc " | \
awk -F'[()]' '{ print $1 "("$2")" }'
}
print_usage() {
# shellcheck disable=SC2039
if [ -n "${BASH_SOURCE[0]}" ]; then
echo "usage: source $(basename "${BASH_SOURCE[0]}")"
else
echo "usage: source $(basename "$1")"
fi
echo "optional arguments:"
echo " --fish Print fish alias syntax (internally used)"
echo " --gcc6 Use GCC6 cross compiler"
echo " --help Show this help message"
}
parse_args() {
unset fish_arg
unset gcc6_arg
while [ "${1:-}" != "" ]; do
case $1 in
--fish)
fish_arg="$1"
shift
;;
--gcc6)
gcc6_arg=1
shift
;;
--help)
shift
return 0
;;
*)
echo "Invalid argument: $1"
shift
return 0
;;
esac
done
return 1
}
main() {
# Stop executing once a function fails
# shellcheck disable=SC1090
if check_kernel_folder \
&& clean_kernel_src_dir \
&& export_pmbootstrap_dir "$1" \
&& set_alias_pmbootstrap \
&& export_chroot_device_deviceinfo \
&& check_device \
&& . "$deviceinfo" \
&& initialize_chroot \
&& mount_kernel_source \
&& create_output_folder \
&& set_alias_make \
&& set_alias_pmbroot_kernelroot; then
# Success
echo "pmbootstrap envkernel.sh activated successfully."
echo " * kernel source: $PWD"
echo " * output folder: $PWD/.output"
echo " * architecture: $arch ($device is $deviceinfo_arch)"
echo " * cross compile: $(cross_compiler_version)"
echo " * aliases: make, kernelroot, pmbootstrap, pmbroot" \
"(see 'type make' etc.)"
else
# Failure
echo "See also: <https://postmarketos.org/troubleshooting>"
return 1
fi
}
# Print fish alias syntax (when called from envkernel.fish)
fish_compat() {
[ "$1" = "--fish" ] || return
for name in make kernelroot pmbootstrap pmbroot; do
echo "alias $(alias $name | sed 's/=/ /')"
done
}
if parse_args "$@"; then
print_usage "$0"
return 1
fi
# Run main() with all output redirected to stderr
# Afterwards print fish compatible syntax to stdout
main "$0" >&2 && fish_compat "$fish_arg"