diff --git a/aliases/virtual/kernel/linux.yaml b/aliases/virtual/kernel/linux.yaml new file mode 100644 index 00000000..c8bbe1ef --- /dev/null +++ b/aliases/virtual/kernel/linux.yaml @@ -0,0 +1,6 @@ +multiPackage: + image: ${CONFIG_SELECT_LINUX:-kernel::linux}-image + modules: ${CONFIG_SELECT_LINUX:-kernel::linux}-modules + dtbs: ${CONFIG_SELECT_LINUX:-kernel::linux}-dtbs + kmod-dist: ${CONFIG_SELECT_LINUX:-kernel::linux}-kmod-dist + headers: ${CONFIG_SELECT_LINUX:-kernel::linux}-headers diff --git a/classes/linux.yaml b/classes/linux.yaml new file mode 100644 index 00000000..f63cc081 --- /dev/null +++ b/classes/linux.yaml @@ -0,0 +1,125 @@ +# Convenience methods for creating a Linux kernel +# +# Here we define helper methods for building the linux kernel and everything +# around it. This means the kernel modules, any dtb's and dev targets like the +# headers or an kmod-dist for building out-of-tree kernel modules. +# +# In its simplest form the usage looks something like the following. Note, that +# the kernel is downloaded into the "linux" directory and that the +# configuration files are put into the "conf" directory. Obviously you are free +# to arrange this somehow differently. Of course you only need to implement the +# targets required by your other recipes: +# +# inherit: [linux] +# +# ... +# +# metaEnvironment: +# PKG_VERSION: 6.1.114 +# +# checkoutSCM: +# - scm: url +# url: ${KERNEL_MIRROR}/linux/kernel/v6.x/linux-${PKG_VERSION}.tar.xz +# digestSHA1: 72f98a7aa831dba4d56b6c28b1a5333b04fbae35 +# stripComponents: 1 +# dir: linux +# - scm: import +# url: src/linux +# dir: conf +# +# buildScript: | +# linuxConfig $1/linux $1/conf/linux.config +# +# multiPackage: +# "": +# buildScript: linuxBuild +# +# multiPackage: +# image: +# inherit: [linux::image] +# packageScript: linuxInstallImage $1 +# +# modules: +# inherit: [linux::modules] +# packageScript: linuxInstallModules $1 +# +# kmod-dist: +# inherit: [linux::kmod-dist] +# packageScript: linuxInstallKmodDist $1 +# +# dtbs: +# inherit: [linux::dtbs] +# buildScript: linuxBuildDtbs +# packageScript: linuxInstallDtbs $1 +# +# headers: +# inherit: [linux::headers] +# buildScript: linuxBuildHeaders +# packageScript: linuxInstallHeaders $1 +# +inherit: [cpackage, make, pkg-config] + +depends: + - tools: + target-toolchain: host-compat-toolchain + depends: + - libs::elfutils-libelf-dev + - libs::openssl-dev + - name: kernel::kmod + use: [tools] + +privateEnvironment: + LINUX_ARCH: "$(if-then-else,$(or,$(eq,${ARCH},i386),$(eq,${ARCH},x86_64)),x86,$(if-then-else,\ + $(or,$(eq,${ARCH},sh),$(eq,${ARCH},sh64)),sh,$(if-then-else,$(or,$(eq,${ARCH},sparc32),\ + $(eq,${ARCH},sparc64)),sparc,$ARCH)))" + +checkoutSCM: + # Always download a script for extracting the files required to build + # external kernel modules. If the kernel itself doesn't have one, we will + # use this one. + scm: url + url: https://raw.githubusercontent.com/torvalds/linux/refs/tags/v6.11/scripts/package/install-extmod-build + digestSHA1: 47eb760cf215cb3a15752186a18715fb04d9ab95 + dir: kmod-script + +buildVars: [LINUX_ARCH, ARCH, CROSS_COMPILE, CC] +buildTools: [m4, bison, flex, target-toolchain, host-toolchain] +buildSetup: | + # make sure we find our kmod-dist script in the package step + ln -sf $1/kmod-script . + + # Build the initial linux config. This will be used by all other steps. + # + # $1: linux kernel source directory + # $2: defconfig (optional) + # - if this is an actual file, use it as the config + # - if this is not a file, check if a defconfig for the target arch by + # that name exists and if yes, use that one + linuxConfig() + { + DEF_CFG=${2:-$1/arch/${LINUX_ARCH}/configs/defconfig} + if [[ -f "$1/arch/${LINUX_ARCH}/configs/${DEF_CFG}" ]] ; then + DEF_CFG=$1/arch/${LINUX_ARCH}/configs/${DEF_CFG} + fi + # check if the defconfig file exists + if [[ ! -f "$DEF_CFG" ]]; then + >&2 echo "Don't know how to use '$DEF_CFG' as linux kernel config!" + false + fi + # check if the source file is newer than .config + if [[ -f .config && .config -nt $DEF_CFG ]]; then + return 0 + fi + # redo the .config file + cp -u "$DEF_CFG" .config + makeSequential -C $1 O=$PWD \ + olddefconfig + } + + # Build the actual target linux image and all configured modules + linuxBuild() + { + makeParallel \ + CC="$CC" \ + $(basename $(make -s image_name)) modules + } diff --git a/classes/linux/dtbs.yaml b/classes/linux/dtbs.yaml new file mode 100644 index 00000000..6c9b25c7 --- /dev/null +++ b/classes/linux/dtbs.yaml @@ -0,0 +1,34 @@ +inherit: [linux] + +buildTools: [target-toolchain] +buildVars: [CROSS_COMPILE] +buildSetup: | + # Build the device tree files. + # + # $1: device tree file(s) (optional) + # - if this isn't provided, all default dtb's in the kernel directory + # are build + linuxBuildDtbs() + { + makeParallel ${1:-dtbs} "${@:2}" + } + +packageSetup: | + # Install the device tree files. + # + # $1: linux kernel build directory + # $2: device tree file(s) (optional) + # - if this isn't provided, all default dtb's in the kernel directory + # are installed + linuxInstallDtbs() + { + if [[ -n "${2:-}" ]]; then + if [[ -d "$1/arch/$LINUX_ARCH/boot/dts" ]] ; then + make -C "$1" INSTALL_DTBS_PATH="$PWD" dtbs_install + fi + else + for i in "${@:2}" ; do + cp "$1/arch/${LINUX_ARCH}/boot/dts/$i" "$PWD" + done + fi + } diff --git a/classes/linux/headers.yaml b/classes/linux/headers.yaml new file mode 100644 index 00000000..b3fbf183 --- /dev/null +++ b/classes/linux/headers.yaml @@ -0,0 +1,17 @@ +inherit: [linux] + +buildSetup: | + # Build the linux kernel headers. + linuxBuildHeaders() + { + make headers_install + } + +packageSetup: | + # Install the linux kernel headers. + # + # $1: linux kernel build directory + linuxInstallHeaders() + { + cp -a $1/usr . + } diff --git a/classes/linux/image.yaml b/classes/linux/image.yaml new file mode 100644 index 00000000..c0c9ebae --- /dev/null +++ b/classes/linux/image.yaml @@ -0,0 +1,22 @@ +inherit: [linux] + +packageVars: [BASEMENT_DEBUG] +packageSetup: | + # Install the linux kernel image, the system.map and the .config used to + # build the kernel. + # + # $1: linux kernel build directory + # $2: destination image name (optional) + linuxInstallImage() + { + src_img_name=$(make -s -C "$1" image_name) + dst_img_name=${2:-$(basename $src_img_name)} + cp "$1/$src_img_name" "${dst_img_name}" + cp "$1/System.map" "${dst_img_name}-System.map" + cp "$1/.config" "${dst_img_name}-config" + + if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then + mkdir -p .debug + cp "$1/$src_img_name" ".debug/${dst_img_name}" + fi + } diff --git a/classes/linux/kmod-dist.yaml b/classes/linux/kmod-dist.yaml new file mode 100644 index 00000000..3eb2b2f0 --- /dev/null +++ b/classes/linux/kmod-dist.yaml @@ -0,0 +1,25 @@ +inherit: [linux] + +packageSetup: | + _SCRIPT_DIR=$1/kmod-script + + # Install the linux kernel modules distribution for building out-of-tree + # kernel modules. + # + # $1: linux kernel build directory + linuxInstallKmodDist() + { + OUT=$PWD + # If the kernel itself provides a script for extracting the files required to + # build external kernel modules, use that, otherwise use the downloaded fixed + # version. + # Default is kernel built-in script: + SCRIPT=$1/source/scripts/package/install-extmod-build + if [[ ! -e $SCRIPT ]]; then + SCRIPT=$_SCRIPT_DIR/install-extmod-build + fi + pushd $1 + MAKE=make HOSTCC=gcc SRCARCH=$LINUX_ARCH srctree=$1/source KCONFIG_CONFIG=$1/.config \ + sh "$SCRIPT" "$OUT" + popd + } diff --git a/classes/linux/menuconfig.yaml b/classes/linux/menuconfig.yaml new file mode 100644 index 00000000..4983e16c --- /dev/null +++ b/classes/linux/menuconfig.yaml @@ -0,0 +1,31 @@ +inherit: [linux] + +depends: + - tools: + target-toolchain: host-compat-toolchain + depends: + - libs::ncurses-dev + +buildSetup: | + # Calls the linux savedefconfig target + # + # Especially in the sandbox this can be tricky. Provide some convenience method. + linuxSavedefconfig() + { + makeParallel savedefconfig + } + + # Calls the linux menuconfig target + # + # Especially in the sandbox this can be tricky. Provide some convenience method. + linuxMenuconfig() + { + NCDEP=${BOB_DEP_PATHS[libs::ncurses-dev]} + makeParallel \ + HOSTCC="gcc" \ + HOSTCFLAGS="-I${NCDEP}/usr/include -DCURSES_LOC=\"\" -DLOCALE" \ + HOSTLDLIBS="-L$(gcc --print-sysroot)/usr/lib -L${NCDEP}/usr/lib -lncurses -ltinfo" \ + menuconfig + # Always save a defconfig + linuxSavedefconfig + } diff --git a/classes/linux/modules.yaml b/classes/linux/modules.yaml new file mode 100644 index 00000000..839aa0b7 --- /dev/null +++ b/classes/linux/modules.yaml @@ -0,0 +1,30 @@ +inherit: [linux] + +packageToolsWeak: [kmod] +packageVars: [BASEMENT_DEBUG, OBJCOPY] +packageSetup: | + # Install the built-in linux kernel modules. + # + # $1: linux kernel build directory + linuxInstallModules() + { + make -C "$1" \ + INSTALL_MOD_PATH="$PWD" modules_install + rm lib/modules/*/build + + # Strip all modules. Shamelessly ripped from builddeb... + for module in $(find lib/modules/ -name *.ko -printf '%P\n'); do + module=lib/modules/$module + mkdir -p $(dirname lib/debug/$module) + # only keep debug symbols in the debug file + if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then + $OBJCOPY --only-keep-debug $module lib/debug/$module + fi + # strip original module from debug symbols + $OBJCOPY --strip-debug $module + # then add a link to those + if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then + $OBJCOPY --add-gnu-debuglink=lib/debug/$module $module + fi + done + } diff --git a/recipes/kernel/linux.yaml b/recipes/kernel/linux.yaml index bf8850d0..50a50448 100644 --- a/recipes/kernel/linux.yaml +++ b/recipes/kernel/linux.yaml @@ -4,7 +4,7 @@ # To use a custom defconfig create a package kernel::linux-custom-config and # set LINUX_CUSTOM_CONFIG to the name of your custom defconfig file. -inherit: [make, patch] +inherit: ["linux"] depends: - if: "${LINUX_CUSTOM_CONFIG:-}" @@ -18,113 +18,48 @@ checkoutSCM: url: ${KERNEL_MIRROR}/linux/kernel/v6.x/linux-${PKG_VERSION}.tar.xz digestSHA256: "ee7650996ba75aa29fe66f309b413097f249a03e7001f2a41128c7c95205226a" stripComponents: 1 + dir: linux -buildTools: [bison, flex, host-toolchain, m4] -buildVars: [ARCH, LINUX_CONFIG, LINUX_CUSTOM_CONFIG, LINUX_CUSTOM_CONFIG_PKG] +buildVars: [LINUX_CONFIG, LINUX_CUSTOM_CONFIG, LINUX_CUSTOM_CONFIG_PKG] buildScript: | # prevent timestamps in configuration export KCONFIG_NOTIMESTAMP=1 export KBUILD_BUILD_TIMESTAMP='Mon Dec 28 22:49:40 CET 2015' - # Compute the arch path, since i386 and x86_64 are in arch/x86 and not - # in arch/$(KERNEL_ARCH). Even if the kernel creates symbolic links - # for bzImage, arch/i386 and arch/x86_64 do not exist when copying the - # defconfig file. - case "$ARCH" in - i386|x86_64) - LINUX_ARCH_PATH=arch/x86 - ;; - sh|sh64) - LINUX_ARCH_PATH=arch/sh - ;; - sparc32|sparc64) - LINUX_ARCH_PATH=arch/sparc - ;; - *) - LINUX_ARCH_PATH=arch/${ARCH} - ;; - esac - echo "$LINUX_ARCH_PATH" > .arch-path - # Use plain "defconfig" if we have no specific target. Otherwise check if # defconfig has changed. if [[ ${LINUX_CUSTOM_CONFIG:+true} ]] ; then PKG="${LINUX_CUSTOM_CONFIG_PKG:-kernel::linux-custom-config}" - cp -u "${BOB_DEP_PATHS[$PKG]}/$LINUX_CUSTOM_CONFIG" .config - make -C "$1" O=$PWD olddefconfig + LCFG="${BOB_DEP_PATHS[$PKG]}/$LINUX_CUSTOM_CONFIG" elif [[ ${LINUX_CONFIG:+true} ]] ; then - if [[ ( ! -e ".config" ) || - ( "$1/${LINUX_ARCH_PATH}/configs/${LINUX_CONFIG}_defconfig" -nt ".config" ) ]] ; - then - make -C "$1" O=$PWD "${LINUX_CONFIG}_defconfig" - fi + LCFG="${LINUX_CONFIG}" else - if [[ ! -e ".config" ]] ; then - make -C "$1" O=$PWD defconfig - fi + LCFG="defconfig" fi + linuxConfig $1/linux $LCFG + multiPackage: "": - inherit: [pkg-config] - depends: - - tools: - target-toolchain: host-compat-toolchain - depends: - - libs::elfutils-libelf-dev - - libs::openssl-dev - - name: kernel::kmod - use: [tools] - - buildTools: [target-toolchain] - buildVars: [CROSS_COMPILE] - buildScript: | - makeParallel + buildScript: linuxBuild multiPackage: image: - packageVars: [PKG_VERSION, BASEMENT_DEBUG] - packageScript: | - read LINUX_ARCH_PATH < $1/.arch-path - mkdir -p boot - - cp "$1/$(make -s -C "$1" image_name)" "boot/vmlinux-$PKG_VERSION" - cp "$1/System.map" "boot/System.map-$PKG_VERSION" - cp "$1/.config" "boot/config-$PKG_VERSION" - - if [[ -d "$1/$LINUX_ARCH_PATH/boot/dts" ]] ; then - make -C "$1" INSTALL_DTBS_PATH="$PWD/boot/dtbs/$PKG_VERSION" dtbs_install - fi - - if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then - mkdir -p boot/.debug - cp "$1/vmlinux" "boot/.debug/vmlinux-$PKG_VERSION" - fi + inherit: ["linux::image"] + packageScript: linuxInstallImage $1 modules: - packageToolsWeak: [kmod] - packageVars: [PKG_VERSION, BASEMENT_DEBUG, OBJCOPY] - packageScript: | - make -C "$1" INSTALL_MOD_PATH="$PWD" modules_install - rm lib/modules/"${PKG_VERSION}"/{build,source} + inherit: ["linux::modules"] + packageScript: linuxInstallModules $1 - # Strip all modules. Shamelessly ripped from builddeb... - for module in $(find lib/modules/ -name *.ko -printf '%P\n'); do - module=lib/modules/$module - mkdir -p $(dirname usr/lib/debug/$module) - # only keep debug symbols in the debug file - if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then - $OBJCOPY --only-keep-debug $module usr/lib/debug/$module - fi - # strip original module from debug symbols - $OBJCOPY --strip-debug $module - # then add a link to those - if [[ ${BASEMENT_DEBUG:-0} != "0" ]] ; then - $OBJCOPY --add-gnu-debuglink=usr/lib/debug/$module $module - fi - done + kmod-dist: + inherit: ["linux::kmod-dist"] + packageScript: linuxInstallKmodDist $1 - depmod -b "$PWD" "$PKG_VERSION" + dtbs: + inherit: ["linux::dtbs"] + buildScript: linuxBuildDtbs + packageScript: linuxInstallDtbs $1 # This package is only for other recipes that need special kernel headers # that are not available in the generic toolchain. Depending on this @@ -132,10 +67,9 @@ multiPackage: # added/modified driver headers. It will make your package dependent on # this kernel and it's particular configuration! headers: - buildScript: | - make headers_install - packageScript: | - cp -a $1/usr . + inherit: ["linux::headers"] + buildScript: linuxBuildHeaders + packageScript: linuxInstallHeaders $1 provideVars: LINUX_VERSION: "$PKG_VERSION"