|
#!/bin/bash |
|
set -euo pipefail |
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)" |
|
BASE="${BASE:-$HOME}" |
|
|
|
REQUESTED_VERSION="${KERNEL:-$(uname -r | cut -d- -f1)}" |
|
cat <<EOF |
|
Trying to build linux kernel version $REQUESTED_VERSION. |
|
EOF |
|
|
|
function get_git() { |
|
repo="$1" |
|
out="$2" |
|
if [[ -d "$out" ]]; then |
|
pushd "$out" |
|
git fetch |
|
popd |
|
else |
|
git clone "$repo" "$out" |
|
fi |
|
} |
|
|
|
set -x |
|
cd "$BASE" |
|
sudo apt remove -y "linux-tools*" "linux-cloud-tools*" >/dev/null |
|
sudo apt update >/dev/null |
|
# 1. wslu: contains wslvar |
|
# 2. block: kernel deps |
|
# 3. block: additional deps for bcc |
|
sudo apt install -y \ |
|
wslu \ |
|
build-essential bison flex \ |
|
libncurses-dev gawk openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf bc \ |
|
libunwind-dev libzstd-dev libcap-dev libdw-dev dwarves \ |
|
cmake zip libedit-dev \ |
|
libllvm14 llvm-14-dev libclang-14-dev python3 zlib1g-dev libfl-dev python3-setuptools \ |
|
liblzma-dev libdebuginfod-dev arping netperf iperf \ |
|
python-is-python3 |
|
|
|
# Set path so that `sudo perf` and `sudo execsnoop` etc work |
|
cat <<EOF | sudo tee /etc/sudoers.d/kernel_tools_path |
|
Defaults secure_path="/root/bin:/usr/share/bcc/tools:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin" |
|
EOF |
|
|
|
# get kernel source and prepare |
|
get_git https://github.com/microsoft/WSL2-Linux-Kernel "$BASE/WSL2-Linux-Kernel" |
|
pushd "$BASE/WSL2-Linux-Kernel" |
|
KERNEL_TAG="$(git tag | grep "$REQUESTED_VERSION")" |
|
if [[ -z "$KERNEL_TAG" ]]; then |
|
set +x |
|
cat <<EOF |
|
Error: no kernel source tag was found for your kernel $(uname -r) |
|
Check the output of 'git tag' in '$BASE/WSL2-Linux-Kernel/'. |
|
EOF |
|
exit 1 |
|
else |
|
echo "Found kernel version: $KERNEL_TAG" |
|
fi |
|
if [[ "$(git describe --tags)" != "$KERNEL_TAG" ]]; then |
|
# New version found, rebuild clean |
|
git checkout "$KERNEL_TAG" |
|
sudo make clean |
|
sudo make -C tools/perf clean |
|
fi |
|
# Make sure it's clean if someone aborted before |
|
git reset --hard |
|
|
|
cp Microsoft/config-wsl .config |
|
make olddefconfig |
|
KERNELVERSION="$(make kernelrelease)" |
|
popd |
|
|
|
# Build and install kernel |
|
pushd "$BASE/WSL2-Linux-Kernel" |
|
make CONFIG_IKHEADERS=m -j$(nproc) --silent |
|
sudo make headers_install INSTALL_HDR_PATH="/usr/src/linux-headers-$KERNELVERSION" --silent |
|
# Not sure why this isn't installed... |
|
sudo cp -f include/linux/user.h /usr/src/linux-headers-$KERNELVERSION/include/linux/ |
|
|
|
sudo mkdir -p "/lib/modules/$KERNELVERSION" |
|
sudo ln -sf "$(pwd)" "/lib/modules/$KERNELVERSION/build" |
|
|
|
# Installing kernel |
|
mkdir -p /mnt/c/wslkernel |
|
|
|
kernel_out="$(pwd)/arch/x86/boot/bzImage" |
|
kernel_path=/mnt/c/wslkernel |
|
kernel_file=latest |
|
|
|
if ! cp "$kernel_out" "$kernel_path/$kernel_file"; then |
|
kernel_file="latest-$RANDOM" |
|
set +x |
|
cat <<EOF |
|
You're already running a custom kernel, right? |
|
Anyway, I'm going to use a different file path then: $kernel_path/$kernel_file |
|
EOF |
|
set -x |
|
cp "$kernel_out" "$kernel_path/$kernel_file" |
|
fi |
|
# The file needs to conain escaped backslashes |
|
echo -e "[wsl2]\nkernel = $(wslpath -m "$kernel_path/$kernel_file" | sed 's/\\/\\\\/g')" \ |
|
>"$(wslpath "$(wslvar USERPROFILE)")/.wslconfig" |
|
popd |
|
|
|
# Install perf from source |
|
pushd "$BASE/WSL2-Linux-Kernel/tools/perf" |
|
make -j$(nproc) >/dev/null |
|
sudo make install >/dev/null |
|
popd |
|
|
|
# Install BCC |
|
get_git https://github.com/iovisor/bcc.git "$BASE/bcc" |
|
pushd "$BASE/bcc" |
|
# New version found, rebuild clean |
|
if [[ "$(git rev-parse origin/master)" != "$(git rev-parse HEAD)" ]]; then |
|
rm -rf build |
|
fi |
|
git reset --hard origin/master |
|
patch -p1 < "$SCRIPT_DIR/bcc-python3.patch" |
|
popd |
|
mkdir -p "$BASE/bcc/build" |
|
pushd "$BASE/bcc/build" |
|
# Note that this uses `uname -r` to find the kernel headers. |
|
# So if you try to build a different kernel than `git tag | grep $(uname -r | cut -d- -f1)` (from above), this won't find them. |
|
# And you'll get a useless bcc collection. |
|
# To fix, re-run this script after rebooting WSL. |
|
cmake .. |
|
make -j$(nproc) >/dev/null |
|
sudo apt remove -y bpfcc-tools libbpfcc libbpfcc-dev > /dev/null |
|
sudo make install >/dev/null |
|
cmake -DPYTHON_CMD=python3 .. |
|
pushd src/python/ |
|
make -j$(nproc) |
|
sudo make install >/dev/null |
|
popd |
|
popd |
|
|
|
set +x |
|
cat <<EOF |
|
Done! |
|
Press enter to shutdown your WSL instance, and run 'uname -a' after that. |
|
(Or, press Ctrl+C to keep running your WSL instance) |
|
You should have the new kernel version, and bpf tools like 'sudo execsnoop' or 'sudo trace', or even 'sudo memleak' available. |
|
|
|
expected version: $KERNELVERSION |
|
EOF |
|
read |
|
echo "Please wait a few seconds..." |
|
wsl.exe --shutdown |