summaryrefslogtreecommitdiffstats
path: root/commands
diff options
context:
space:
mode:
Diffstat (limited to 'commands')
-rwxr-xr-xcommands/build-all15
-rwxr-xr-xcommands/build-arch67
-rwxr-xr-xcommands/check16
-rwxr-xr-xcommands/copy-modules168
-rwxr-xr-xcommands/find-dups24
-rwxr-xr-xcommands/find-unpackaged35
-rwxr-xr-xcommands/gen-control98
-rwxr-xr-xcommands/gen-deps35
-rwxr-xr-xcommands/help12
-rwxr-xr-xcommands/install-files170
-rwxr-xr-xcommands/preprocess224
11 files changed, 864 insertions, 0 deletions
diff --git a/commands/build-all b/commands/build-all
new file mode 100755
index 0000000..afb677f
--- /dev/null
+++ b/commands/build-all
@@ -0,0 +1,15 @@
+#!/bin/sh
+# This is a wrapper script that can be used to build all architectures.
+#
+# The script builds all architectures listed in kernel-versions.
+# It expects to have the unpacked kernel packages for various arches in
+# ../alpha, etc. modules.dep files have to be put in there too if they are
+# not shipped in the .deb (varies)
+#
+# dpkg-cross must be installed, but you do not need a cross compiler.
+
+set -e
+
+for arch in $(cut -d ' ' -f 1 kernel-versions | grep -v ^# | uniq); do
+ kernel-wedge build-arch "$arch"
+done
diff --git a/commands/build-arch b/commands/build-arch
new file mode 100755
index 0000000..5b910ab
--- /dev/null
+++ b/commands/build-arch
@@ -0,0 +1,67 @@
+#!/bin/sh
+# This is a wrapper script to build a specific architecture.
+#
+# It takes the architecture to be built as parameter and that architecture
+# needs to be listed in kernel-versions.
+# It expects to have the unpacked kernel packages for the architecture in
+# e.g. ../alpha. modules.dep files have to be put in there too if they are
+# not shipped in the .deb (varies)
+#
+# dpkg-cross must be installed, but you do not need a cross compiler.
+
+set -e
+
+buildpackage () {
+ dpkg-buildpackage -d -us -uc -rfakeroot -tc -I $@
+}
+
+# Build source package. Binaries are built below.
+buildpackage -S
+
+# Directory for stubs, added to PATH.
+arch="$1"
+trap 'rm -rf $tmpdir' EXIT
+tmpdir=$(mktemp -d)
+PATH=$PATH:$tmpdir
+export PATH
+
+if [ -z "$arch" ]; then
+ echo "** Error: architecture not specified"
+ exit 1
+fi
+if ! cut -d ' ' -f 1 kernel-versions | grep -v "^$arch$"; then
+ echo "** Error: arch $arch not listed in kernel-versions"
+ exit 1
+fi
+
+if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then
+ # Generate cross-compiler stub, this is needed to get the
+ # debian build system to cross-build the given arch w/o a
+ # real cross compiler.
+ CC=$tmpdir/$arch-linux-gcc
+ echo "#!/bin/sh" > $CC
+ echo "echo $arch-linux" >> $CC
+ chmod +x $CC
+ # Not only must it be in the path, but CC needs to be
+ # exported as well.
+ export CC
+else
+ # native build
+ unset CC
+fi
+
+if [ -d ../$arch ]; then
+ export SOURCEDIR=`pwd`/../$arch
+else
+ unset SOURCEDIR
+fi
+
+if [ "$arch" != "`dpkg-architecture -qDEB_BUILD_ARCH`" ]; then
+ if [ -z "$SOURCEDIR" ]; then
+ echo "** Warning: no SOURCEDIR for arch $arch" >&2
+ fi
+ buildpackage -b -a$arch
+else
+ # native build
+ buildpackage
+fi
diff --git a/commands/check b/commands/check
new file mode 100755
index 0000000..4b416d1
--- /dev/null
+++ b/commands/check
@@ -0,0 +1,16 @@
+#!/bin/sh -e
+empty=
+if [ $# -ge 1 ]; then
+ packages="$*"
+else
+ packages="$(dh_listpackages -s)"
+fi
+for pkg in $packages; do
+ if [ -z "$(find debian/$pkg -type f)" ]; then
+ echo "$pkg will be empty" >&2
+ empty=1
+ fi
+done
+if [ "$empty" -a -z "$KW_CHECK_NONFATAL" ]; then
+ exit 1
+fi
diff --git a/commands/copy-modules b/commands/copy-modules
new file mode 100755
index 0000000..30f9dc5
--- /dev/null
+++ b/commands/copy-modules
@@ -0,0 +1,168 @@
+#!/bin/bash
+#
+# Copy modules into the right directories in preparation for building udebs.
+# This script is named after the its counterpart in the original
+# kernel-image-di package by Joey Hess <joeyh@debian.org>.
+#
+# Copyright (c) 2001-2002 Herbert Xu <herbert@debian.org>
+#
+# Usage: copy-modules version flavour installedname
+
+set -e
+
+deplist() {
+ local deps=$1
+ local list=$2
+
+ cp $list $tmpdir/work
+
+ # recursively append external dependencies to $list
+ while :; do
+
+ # list external dependencies of $work
+ join -o 2.2 $tmpdir/work $deps | sort -u | comm -23 - $list \
+ > $tmpdir/work.new
+ mv $tmpdir/work.new $tmpdir/work
+
+ # exit if work is empty
+ [ -s $tmpdir/work ] || break
+
+ # append work to $list
+ sort -um -o $list $list $tmpdir/work
+ done
+}
+
+version=$1-$2
+flavour=$2
+installedname=$3
+configdir=$(readlink -f ${KW_CONFIG_DIR:-.})
+arch=$(dpkg-architecture -qDEB_HOST_ARCH)
+os=$(dpkg-architecture -qDEB_HOST_ARCH_OS)
+home=$PWD
+
+trap 'rm -rf $tmpdir' EXIT
+tmpdir=$(mktemp -d)
+
+# SOURCEDIR may be set externally to control where to copy from.
+if [ -n "$SOURCEDIR" ]; then
+ moddir=$SOURCEDIR/lib/modules/$installedname
+else
+ moddir=/lib/modules/$installedname
+fi
+
+if [ ! -d $moddir ]; then
+ exit 0
+fi
+
+# The directory of modules lists to use.
+if [ -d $configdir/modules/$arch-$flavour ]; then
+ modlistdir=$configdir/modules/$arch-$flavour
+elif [ -d $configdir/modules/$flavour ]; then
+ modlistdir=$configdir/modules/$flavour
+else
+ modlistdir=$configdir/modules/$arch
+fi
+
+if [ "$os" = "linux" ] ; then
+ if [ "$SOURCEDIR" ]; then
+ modulesdep=$tmpdir/modules.dep
+ PATH="/usr/sbin:/sbin:$PATH" depmod \
+ -b $SOURCEDIR $installedname -n \
+ | sed '/^#/d; /^alias /,$d' >$modulesdep
+ elif [ -e "$moddir/modules.dep" ]; then
+ modulesdep=$moddir/modules.dep
+ else
+ echo "Installed kernel package is missing $moddir/modules.dep" >&2
+ exit 1
+ fi
+
+ # get module dependencies from modules.dep
+ # sort it by field 2
+ perl -lne '
+ @words=split(" ");
+ s!'/lib/modules/$installedname'/!! foreach (@words);
+ if ($words[0] =~ /:$/) {
+ $words[0]=~s/:$//;
+ $module=shift @words;
+ }
+ foreach (@words) {
+ print "$module\t$_" unless $_ eq "\\";
+ }
+ ' $modulesdep | sort -k 2,2 > $tmpdir/deps
+
+ if [ ! -s $tmpdir/deps ] && [ ! -e $configdir/no-modules ]; then
+ echo "No module interdependencies found. This probably means your modules.dep is broken." >&2
+ echo "If this is intentional, touch $configdir/no-modules" >&2
+ exit 1
+ fi
+else
+ touch $tmpdir/deps
+fi
+
+mkdir $tmpdir/module-deps $tmpdir/module-list
+
+# generate module interrelationships from package-list file
+kernel-wedge gen-deps $flavour > $tmpdir/module-deps.packages
+
+code=0
+# loop over all udebs, sort that all dependent modules are processed first
+for i in $(
+ {
+ find $modlistdir/ -maxdepth 1 \( -type f -or -type l \) -not -name '*.lnk' -printf "%f\t%f\n"
+ cat $tmpdir/module-deps.packages
+ } | tsort | tac
+); do
+ # write dependent (direct and indirect) udebs to exclude
+ # write dependencies to module-deps/$i
+ echo $i | join -o 2.2 - $tmpdir/module-deps.packages | { # dependent modules
+ cd $tmpdir/module-deps
+ xargs -r sh -c 'printf "%s\n" "$@"; cat "$@"' sh # direct and indirect deps
+ } | sort -u | tee $tmpdir/module-deps/$i | { # write deps
+ cd $tmpdir/module-list
+ xargs -r cat
+ } | sort -u > $tmpdir/exclude # modules to exclude
+
+ # preprocess file, handle includes and excludes and sort so that
+ # the joins work, no matter what the order of the input.
+ kernel-wedge preprocess $modlistdir/$i $moddir |
+ sort > $tmpdir/module-list/$i
+ test ${PIPESTATUS[0]} = 0
+
+ # exclude modules in exclude from dependency list
+ join -o 2.1,2.2 -2 2 -v 2 $tmpdir/exclude $tmpdir/deps |
+ sort -k 1,1 > $tmpdir/tmpdeps
+
+ # include dependent modules which are not in a
+ # dependent udeb into module-list/$i
+ deplist $tmpdir/tmpdeps $tmpdir/module-list/$i
+
+ if [ -s $tmpdir/module-list/$i ] && dh_listpackages | grep -qx "$i-$version-di"; then
+ # copy kernel modules to package build dir
+ cd $moddir
+ ret=$( ( (
+ set +e
+ tar cfT - $tmpdir/module-list/$i
+ printf $? >&3
+ ) | (
+ set +e
+ dir=$home/debian/$i-$version-di/lib/modules/$installedname
+ mkdir -p $dir
+ cd $dir
+ tar xf -
+ printf $? >&3
+ ) ) 3>&1)
+ if [ "$ret" != "00" ]; then
+ echo "tar failed" >&2
+ exit $ret
+ fi
+ cd $home
+
+ if [ "$os" = linux ]; then
+ cat >"debian/$i-$version-di.postinst" <<EOF
+#!/bin/sh -e
+depmod $installedname
+EOF
+ fi
+ fi
+done
+exit $code
diff --git a/commands/find-dups b/commands/find-dups
new file mode 100755
index 0000000..7c4d45a
--- /dev/null
+++ b/commands/find-dups
@@ -0,0 +1,24 @@
+#!/bin/bash -e
+# Find duplicate modules. Pass the kernel name.
+kernel=$1
+(
+ shopt -s nullglob
+ for dir in debian/*-modules-$kernel-di; do
+ cd $dir
+ find lib -type f -printf "$dir %p\n"
+ cd ../..
+ done
+) | sort -k2 | perl -ne '
+ my $configdir = ($ENV{KW_CONFIG_DIR} || ".");
+ while (<>) {
+ ($d, $f)=split;
+ if ($f eq $lf) { print "$d $f\n$ld $lf\n"; $dups++ }
+ $lf=$f;
+ $ld=$d
+ }
+ if ($dups) {
+ print STDERR "some modules are in more than one package\n";
+ exit 1 unless (-e "$configdir/ignore-dups" ||
+ length($ENV{KW_CHECK_NONFATAL}));
+ }
+'
diff --git a/commands/find-unpackaged b/commands/find-unpackaged
new file mode 100755
index 0000000..a7bcf6d
--- /dev/null
+++ b/commands/find-unpackaged
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+# Find unpackaged modules. Pass the kernel name and installed name
+# (normally the same).
+use strict;
+use warnings;
+use File::Find ();
+use File::Spec;
+
+my $kernel = $ARGV[0];
+my $installedname = $ARGV[1];
+
+my $moddir = "/lib/modules/$installedname";
+my $sourcedir = $ENV{SOURCEDIR} || '';
+
+my %unpackaged;
+my $dir = "$sourcedir$moddir";
+File::Find::find(
+ sub {
+ $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)} = 1
+ if /\.k?o$/;
+ },
+ $dir);
+for my $dir (glob("debian/*-modules-$kernel-di$moddir")) {
+ File::Find::find(
+ sub {
+ delete $unpackaged{File::Spec->abs2rel($File::Find::name, $dir)}
+ if /\.k?o$/;
+ },
+ $dir);
+}
+
+print "These modules from $kernel are unpackaged:\n";
+for my $path (sort(keys(%unpackaged))) {
+ print "\t\t$path\n";
+}
diff --git a/commands/gen-control b/commands/gen-control
new file mode 100755
index 0000000..67922d8
--- /dev/null
+++ b/commands/gen-control
@@ -0,0 +1,98 @@
+#!/usr/bin/perl
+# Generate a debian/control from the control stub, the kernel-versions
+# files, and the package-list.
+use strict;
+use warnings;
+
+use KernelWedge qw(CONFIG_DIR CONTROL_FIELDS read_kernel_versions
+ read_package_lists for_each_package);
+
+my @builddeps;
+my %excluded;
+
+my $fixkernelversion = $ARGV[0];
+
+if (open(EXCLUDED, CONFIG_DIR . "/exclude-packages")) {
+ while (<EXCLUDED>) {
+ chomp;
+ $excluded{$_}=1;
+ }
+ close EXCLUDED;
+}
+
+my $versions = read_kernel_versions($fixkernelversion);
+
+for my $ver (@$versions) {
+ (my $arch, my $kernelversion, undef, undef, undef, my $builddep) =
+ @$ver;
+ if (defined($fixkernelversion)) {
+ $ver->[1] = $fixkernelversion;
+ }
+ elsif ($kernelversion eq "-") {
+ die "kernel version not set in file or on command line";
+ }
+ if ($builddep ne "-") {
+ foreach my $pkg (split(", ", $builddep)) {
+ push @builddeps, "$pkg [$arch]";
+ }
+ }
+}
+
+# Building with installed kernel package, or as part of a package?
+if (@builddeps) {
+ open(STUB, "debian/control.stub") || die "debian/control.stub: $!";
+ while (<STUB>) {
+ chomp;
+ if (/^Build-Depends:/) {
+ $_=join(", ", $_, @builddeps);
+ }
+ print $_."\n";
+ }
+ close STUB;
+}
+
+my $packages = read_package_lists();
+
+for_each_package($packages, $versions, sub {
+ my ($arch, $kernelversion, $flavour, $modlistdir, $template) = @_;
+
+ my %override;
+ $override{Architecture}=$arch;
+ $override{Package}=$template->("Package")."-".$kernelversion."-".$flavour."-di";
+ $override{'Package-Type'}="udeb";
+ $override{'Kernel-Version'}=$kernelversion."-".$flavour;
+
+ return if $excluded{$override{Package}};
+
+ print "\n";
+
+ if (! defined $template->("Section") || $template->("Section") !~ /debian-installer$/) {
+ $override{Section}="debian-installer";
+ }
+
+ if (defined $template->("Depends")) {
+ $override{Depends}=join(", ",
+ map { $_."-".$kernelversion."-".$flavour."-di" }
+ # Remove force marker.
+ map { s/!$//; $_ }
+ # If the dep is not built for this arch,
+ # skip it, unless it's forced.
+ grep { -e "$modlistdir/$_" || /!$/ }
+ split(", ", $template->("Depends")));
+ }
+
+ foreach my $field (CONTROL_FIELDS) {
+ my $value = $override{$field} || $template->($field);
+ if ($field eq 'Provides') {
+ if (defined $value) {
+ print $field.": ".$template->("Package").", ".$value."\n";
+ }
+ else {
+ print $field.": ".$template->("Package")."\n";
+ }
+ }
+ else {
+ print $field.": ".$value."\n" if defined $value;
+ }
+ }
+});
diff --git a/commands/gen-deps b/commands/gen-deps
new file mode 100755
index 0000000..3a1a90c
--- /dev/null
+++ b/commands/gen-deps
@@ -0,0 +1,35 @@
+#!/usr/bin/perl
+# Generates from debian/control a dependency file, suitable to be fed to
+# tsort. The file has the base package name on the left, and the package it
+# depends on is on the right. It is sorted.
+use strict;
+use warnings;
+
+use KernelWedge qw(read_kernel_versions read_package_lists for_each_package);
+
+my $arch=`dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $arch;
+
+my $flavour=$ARGV[0];
+
+my @out;
+
+my $versions = [[$arch, '-', $flavour]];
+my $packages = read_package_lists();
+
+for_each_package($packages, $versions, sub {
+ my ($arch, $kernelversion, $flavour, $modlistdir, $package) = @_;
+ my $pkg_name = $package->("Package");
+ my @depends = split(", ", $package->("Depends") || "");
+
+ @out = grep(!/^$pkg_name\t/, @out);
+
+ foreach my $dep (@depends) {
+ # Skip depends that are not built for this
+ # architecture.
+ next unless -e "$modlistdir/$dep";
+ push @out, "$pkg_name\t$dep\n";
+ }
+});
+
+print sort @out;
diff --git a/commands/help b/commands/help
new file mode 100755
index 0000000..4a7a73f
--- /dev/null
+++ b/commands/help
@@ -0,0 +1,12 @@
+#!/bin/sh
+LIBDIR=/usr/share/kernel-wedge/commands
+set -e
+command=$1
+if [ -z "$command" ]; then
+ kernel-wedge
+fi
+if [ ! -x "$LIBDIR/$command" ]; then
+ echo "No such command."
+ exit 1
+fi
+exec man 1 "kernel-wedge-$command"
diff --git a/commands/install-files b/commands/install-files
new file mode 100755
index 0000000..c88e29a
--- /dev/null
+++ b/commands/install-files
@@ -0,0 +1,170 @@
+#!/usr/bin/perl -w
+# Create and populate the package build directories.
+
+sub doit {
+ print "\t".join(" ", @_)."\n";
+ my $ret=(system(@_) >> 8);
+ if ($ret != 0) {
+ die "command exited with status $ret\n";
+ }
+}
+
+my $hostarch=`dpkg-architecture -qDEB_HOST_ARCH`;
+chomp $hostarch;
+my $hostos=`dpkg-architecture -qDEB_HOST_ARCH_OS`;
+chomp $hostos;
+
+my $configdir = ($ENV{KW_CONFIG_DIR} || '.');
+my $fixsourcedir = $ENV{SOURCEDIR};
+
+my $fixkernelversion = $ARGV[0];
+
+open(KVERS, "$configdir/kernel-versions") || die "kernel-versions: $!";
+my $version = 0;
+while (<KVERS>) {
+ chomp;
+ next if /^#/ || ! length;
+
+ my ($arch, $kernelversion, $flavour, $installedname, $suffix, $builddep)=split(' ', $_, 6);
+ if (! length $arch || ! length $kernelversion ||
+ ! length $installedname || ! length $flavour ||
+ ! length $builddep ) {
+ die "parse error: $_";
+ }
+ next unless $arch eq $hostarch;
+
+ if (defined($fixkernelversion)) {
+ $kernelversion = $fixkernelversion;
+ }
+ elsif ($kernelversion eq "-") {
+ die "kernel version not set in file or on command line";
+ }
+
+ if ($installedname eq "-") {
+ $installedname = "$kernelversion-$flavour";
+ }
+
+ my $sourcedir;
+ my $bootwrapper_sourcedir;
+ if (defined $fixsourcedir) {
+ $sourcedir = $fixsourcedir;
+ }
+ else {
+ # Building with installed kernel package, or as part
+ # of a package?
+ if ($builddep ne "-") {
+ $sourcedir = "";
+ }
+ elsif ($arch =~ /^kfreebsd-/) {
+ $sourcedir = "debian/kfreebsd-image-$installedname";
+ }
+ else {
+ ($sourcedir) = grep {-d}
+ ("debian/linux-image-$installedname",
+ "debian/linux-image-$installedname-unsigned");
+ ($bootwrapper_sourcedir) = grep {-d}
+ "debian/linux-bootwrapper-$kernelversion";
+ }
+ # Set SOURCEDIR for copy-modules
+ $ENV{SOURCEDIR} = $sourcedir;
+ }
+
+ my $extraname="";
+ if ($suffix =~ /^[yY]/) {
+ $extraname="-$kernelversion-$flavour";
+ }
+ elsif ($suffix =~ /^-.+/) {
+ $extraname="$suffix";
+ }
+
+ my $modlistdir;
+ if (-d "$configdir/modules/$arch-$flavour") {
+ $modlistdir = "$configdir/modules/$arch-$flavour";
+ }
+ elsif (-d "$configdir/modules/$flavour") {
+ $modlistdir = "$configdir/modules/$flavour";
+ }
+ else {
+ $modlistdir = "$configdir/modules/$arch";
+ }
+
+ if (! -e "$modlistdir/kernel-image") {
+ # copy no kernel
+ }
+ elsif ($hostos eq 'linux') {
+ if (-e "$sourcedir/boot/vmlinux-$installedname") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/vmlinux-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinux$extraname");
+ }
+ elsif (-e "$sourcedir/boot/vmlinuz-$installedname") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/vmlinuz-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/vmlinuz$extraname");
+ }
+ else {
+ die "could not find kernel image";
+ }
+ if (-e "$sourcedir/lib/modules/$installedname") {
+ doit("install", "-d",
+ "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname");
+ doit("install", "-m", 644,
+ "$sourcedir/lib/modules/$installedname/modules.builtin",
+ "$sourcedir/lib/modules/$installedname/modules.order",
+ "debian/kernel-image-$kernelversion-$flavour-di/lib/modules/$installedname/");
+ }
+ }
+ elsif (-e "$sourcedir/boot/kfreebsd-$installedname.gz") {
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/kfreebsd-$installedname.gz",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/kfreebsd$extraname.gz");
+ }
+ else {
+ die "could not find kernel image";
+ }
+ doit("install", "-D", "-m", 644,
+ "$sourcedir/boot/System.map-$installedname",
+ "debian/kernel-image-$kernelversion-$flavour-di/boot/System.map$extraname")
+ if -e "$sourcedir/boot/System.map-$installedname" &&
+ -e "$modlistdir/kernel-image";
+
+ # Include extra files to help the d-i build process build kernels
+ # for certain subarchitectures. This is powerpc-specific at the
+ # moment.
+ if (-d "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour") {
+ my $installdir =
+ "debian/kernel-image-$kernelversion-$flavour-di" .
+ "/usr/lib/linux-image-$installedname";
+
+ doit("install", "-d",
+ "debian/kernel-image-$kernelversion-$flavour-di/usr/lib");
+ doit("cp", "-a",
+ "$sourcedir/usr/lib/linux-image-$kernelversion-$flavour",
+ $installdir);
+
+ # Replace symlinks into linux-bootwrapper with the target
+ # files, rather than building yet another udeb.
+ if (defined($bootwrapper_sourcedir)) {
+ opendir(my $dh, $installdir)
+ or die "opendir: $installdir: $!";
+ for my $name (readdir($dh)) {
+ my $fullname = "$installdir/$name";
+ my $target = readlink($fullname);
+ next unless defined($target) &&
+ $target eq "../linux-bootwrapper-$kernelversion/$name";
+ unlink($fullname)
+ or die "unlink: $fullname: $!";
+ doit("cp", "-a",
+ $bootwrapper_sourcedir .
+ "/usr/lib/linux-bootwrapper-$kernelversion/$name",
+ $fullname);
+ }
+ closedir($dh);
+ }
+ }
+
+ doit("kernel-wedge", "copy-modules", $kernelversion, $flavour, $installedname);
+ doit("kernel-wedge", "find-dups", "$kernelversion-$flavour");
+ doit("kernel-wedge", "find-unpackaged", "$kernelversion-$flavour", $installedname);
+}
+close KVERS;
diff --git a/commands/preprocess b/commands/preprocess
new file mode 100755
index 0000000..7cd1041
--- /dev/null
+++ b/commands/preprocess
@@ -0,0 +1,224 @@
+#!/usr/bin/perl
+use strict;
+use warnings;
+use File::Find ();
+use File::Spec ();
+
+# Dummy filename for when we find that a module is actually built-in
+use constant BUILTIN => "<builtin>";
+
+my $defconfigdir = $ENV{KW_DEFCONFIG_DIR};
+if (!defined($defconfigdir)) {
+ print STDERR "$0: Required environment variable \$KW_DEFCONFIG_DIR is not defined\n";
+ exit 2;
+}
+my $sysdir="$defconfigdir/modules/";
+my $os = `dpkg-architecture -qDEB_HOST_ARCH_OS`;
+chomp $os;
+
+my @module_files;
+my @modules_builtin;
+my %modules;
+my %missing;
+my %loaded;
+
+sub find_all_modules {
+ my ($moddir) = @_;
+
+ File::Find::find({
+ follow => 1, # If $moddir is a symlink, follow it.
+ wanted => sub {
+ if (/\.ko(?:\.(?:xz|zstd))?$/) {
+ push @module_files,
+ File::Spec->abs2rel($File::Find::name,
+ $moddir);
+ }
+ }
+ }, $moddir);
+
+ if ($os eq 'linux') {
+ if (open(my $builtin, "$moddir/modules.builtin")) {
+ while (<$builtin>) {
+ chomp;
+ push @modules_builtin, $_;
+ }
+ close($builtin);
+ }
+ }
+}
+
+sub wildcard_to_regexp {
+ my ($pattern) = @_;
+
+ # Convert to regexp syntax. We handle '**' as a recursive
+ # match-all. We don't bother to handle '\' or '[...]'.
+ my %glob_re = ('?' => '[^/]',
+ '*' => '[^/]*',
+ '**' => '.*',
+ '' => '');
+ my $extra_wild;
+ if ($os eq 'linux') {
+ # Linux treats '-' and '_' as equivalent, and neither
+ # is used consistently. So let each match the other.
+ $glob_re{'-'} = $glob_re{'_'} = '[-_]';
+ $extra_wild = '|[-_]';
+ } else {
+ $extra_wild = '';
+ }
+ $pattern =~ s/(.*?)(\*\*|[?*]$extra_wild|)/
+ quotemeta($1) . $glob_re{$2}/eg;
+
+ return $pattern;
+}
+
+sub is_really_wild {
+ my ($pattern) = @_;
+
+ return scalar($pattern =~ /[?*]/);
+}
+
+sub find_modules {
+ my ($moddir, $pattern, $optional) = @_;
+ my $wild = is_really_wild($pattern);
+
+ my @regexps;
+ if ($wild) {
+ my $re;
+ if ($pattern =~ m|^([^?*]*)/(.*)|) {
+ my $subdir = $1;
+ if (! -d "$moddir/$subdir") {
+ if (-d "$moddir/kernel/$subdir") {
+ $subdir = "kernel/$subdir";
+ } elsif (!$optional) {
+ print STDERR "pattern $pattern refers to nonexistent subdirectory\n";
+ unless ($ENV{KW_CHECK_NONFATAL}) {
+ $! = 1;
+ die;
+ }
+ } else {
+ return ();
+ }
+ }
+ $re = quotemeta($subdir) . '/' . wildcard_to_regexp($2);
+ } else {
+ $re = wildcard_to_regexp($pattern);
+ }
+
+ # Add module suffix; anchor at start and end of string
+ @regexps = ('^' . $re . '\.ko(?:\.(?:xz|zstd))?$');
+ } else {
+ # If pattern doesn't include a wildcard, find the
+ # module in any subdir, but prefer a module in the
+ # kernel subdir. We still do wildcard processing
+ # to handle equivalence of '-' and '_' for Linux.
+ my $re = wildcard_to_regexp($pattern);
+ @regexps = ('^kernel/(?:.*/)?' . $re . '\.ko(?:\.(?:xz|zstd))?$',
+ '(?:^|/)' . $re . '\.ko(?:\.(?:xz|zstd))?$');
+ }
+
+ my @modules;
+ regexp_loop:
+ for my $re (@regexps) {
+ for (@module_files) {
+ if (/$re/) {
+ push @modules, $_;
+ last regexp_loop unless $wild;
+ }
+ }
+ if (!$wild && grep(/$re/, @modules_builtin)) {
+ push @modules, BUILTIN;
+ last;
+ }
+ }
+
+ return @modules;
+}
+
+sub loadlist {
+ my ($list, $moddir) = @_;
+
+ if ($loaded{$list}) {
+ $! = 1;
+ die "include loop detected loading $list\n";
+ }
+ $loaded{$list}=1;
+
+ my $fh;
+ unless (open($fh, $list)) {
+ $! = 1;
+ die "cannot read $list\n";
+ }
+ while (<$fh>) {
+ s/^\s*//;
+ s/\s*$//;
+ if (/^#include\s+<(.*)>$/) {
+ my $basename=$1;
+ loadlist($sysdir.$basename, $moddir);
+ }
+ elsif (/^#include\s+"(.*)"$/) {
+ my $include=$1;
+ my ($dirname)=$list=~m!(.*/).*!;
+ loadlist($dirname.$include, $moddir);
+ }
+ elsif (/^$/) {
+ next;
+ }
+ elsif (/^#/) {
+ next;
+ }
+ elsif (/^(.*) -$/) {
+ # If this was explicitly included and is missing,
+ # we no longer care
+ delete $missing{$1};
+
+ for (find_modules($moddir, $1, 1)) {
+ delete $modules{$_};
+ }
+ }
+ else {
+ my ($pattern, $optional, @found);
+
+ if (/^(.*) \?$/) {
+ ($pattern, $optional) = ($1, 1);
+ }
+ # Support dash prefixing for backwards compatibility.
+ elsif (/^-(.*)/) {
+ ($pattern, $optional) = ($1, 1);
+ } else {
+ ($pattern, $optional) = ($_, 0);
+ }
+
+ @found = find_modules($moddir, $pattern, $optional);
+ for (@found) {
+ $modules{$_} = 1 unless $_ eq BUILTIN;
+ }
+
+ # Check for missing required module. This is not
+ # yet an error as it might be excluded later.
+ if (!is_really_wild($pattern) && !$optional
+ && !@found) {
+ $missing{$pattern} = 1;
+ }
+ }
+ }
+ close $fh;
+}
+
+if (@ARGV < 2) {
+ print STDERR "$0: Required parameters missing\n";
+ exit 2;
+}
+my ($file, $moddir) = @ARGV;
+find_all_modules($moddir);
+loadlist($file, $moddir);
+
+if (keys %missing) {
+ for (keys %missing) {
+ print STDERR "missing module $_\n";
+ }
+ exit 1 unless $ENV{'KW_CHECK_NONFATAL'};
+}
+
+foreach my $m (sort keys %modules) {
+ print "$m\n";
+}