From: Prarit Bhargava <pra...@redhat.com> redhat: Replace build_configs.sh with python equivalent
Replace the build_configs.sh script with an equivalent python script. Signed-off-by: Prarit Bhargava <pra...@redhat.com> diff --git a/redhat/Makefile b/redhat/Makefile index blahblah..blahblah 100644 --- a/redhat/Makefile +++ b/redhat/Makefile @@ -578,8 +578,8 @@ dist-configs-check: dist-configs-prep +cd $(REDHAT)/configs; ./process_configs.sh $(PROCESS_CONFIGS_CHECK_OPTS) "" "" dist-configs-prep: dist-clean-configs - +cd $(REDHAT)/configs; ./build_configs.sh "partial" "snip" - +cd $(REDHAT)/configs; ./build_configs.sh "$(SPECPACKAGE_NAME)" "$(FLAVOR)" + +cd $(REDHAT)/configs; ./build_configs.py "partial" "snip" + +cd $(REDHAT)/configs; ./build_configs.py "$(SPECPACKAGE_NAME)" "$(FLAVOR)" dist-configs-arch: ##configuration Same as dist-configs but for single architecture only. dist-configs-arch: ARCH_MACH = $(MACH) diff --git a/redhat/configs/build_configs.py b/redhat/configs/build_configs.py new file mode 100755 index blahblah..blahblah 100755 --- /dev/null +++ b/redhat/configs/build_configs.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +import os +import sys +import shutil +import subprocess +from pathlib import Path +import locale +from multiprocessing import Pool +import argparse + +locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + +# --- Helper Functions --- +def cleanup(): + for f in Path('.').glob('config-*'): + f.unlink(missing_ok=True) + Path('.flavors').unlink(missing_ok=True) + +def die(msg): + print(msg) + cleanup() + sys.exit(1) + +def combine_config_layer(dir_path): + dir_path = Path(dir_path) + file_name = f"config-{str(dir_path).replace('/', '-')}" + config_files = sorted([f for f in dir_path.glob('CONFIG_*') if not f.name.endswith('~')]) + if not config_files: + Path(file_name).touch() + return + with open(file_name, 'w') as outfile: + for cf in config_files: + outfile.write(cf.read_text()) + +def merge_configs(archvar, configs, order, flavor, count, output_dir, specpackage_name, enable_werror): + arch = archvar.split('-')[0] + name = os.path.join(output_dir, f"{specpackage_name}-{archvar}-{flavor}.config") + print(f"Building {name} ... ") + merging_file = f"config-merging.{count}" + merged_file = f"config-merged.{count}" + Path(merging_file).touch() + Path(merged_file).touch() + skip_if_missing = False + for o in order: + for config in configs: + cfile = f"config-{o}-{config}" + if skip_if_missing and not Path(cfile).exists(): + continue + try: + result = subprocess.run([sys.executable, 'merge.py', cfile, merging_file], + capture_output=True, text=True, check=True) + with open(merged_file, 'w') as mf: + mf.write(result.stdout) + shutil.move(merged_file, merging_file) + except subprocess.CalledProcessError as e: + die(f"Failed to merge {cfile}: {e.stderr}") + except FileNotFoundError: + die(f"merge.py not found in {os.getcwd()}") + except PermissionError: + die(f"Permission denied when trying to merge {cfile}") + except Exception as e: + die(f"Unexpected error while merging {cfile}: {str(e)}") + skip_if_missing = True + arch_headers = { + 'aarch64': '# arm64', + 'ppc64le': '# powerpc', + 's390x': '# s390', + 'riscv64': '# riscv', + } + try: + with open(name, 'w') as out: + out.write(arch_headers.get(arch, f"# {arch}") + '\n') + with open(merging_file, 'r') as mf: + lines = sorted(mf.readlines()) + out.writelines(lines) + if enable_werror: + with open(name, 'r') as f: + content = f.read() + content = content.replace('# CONFIG_WERROR is not set', 'CONFIG_WERROR=y') + content = content.replace('# CONFIG_KVM_WERROR is not set', 'CONFIG_KVM_WERROR=y') + with open(name, 'w') as f: + f.write(content) + except IOError as e: + die(f"Failed to write config file {name}: {str(e)}") + finally: + Path(merged_file).unlink(missing_ok=True) + Path(merging_file).unlink(missing_ok=True) + print(f"Building {name} complete") + +def build_flavor(flavor, output_dir, specpackage_name, arch_mach, enable_werror, rhjobs): + control_file = f"priority.{flavor}" + count = 0 + order = [] + tasks = [] + + try: + with open(control_file, 'r') as cf: + for line in cf: + line = line.strip() + if not line or line.startswith('#'): + continue + if line.startswith('EMPTY'): + empty = line.split('=')[1] + for a in empty.split(): + try: + with open(os.path.join(output_dir, f"{specpackage_name}-{a}-{flavor}.config"), 'w') as f: + f.write('# EMPTY\n') + except IOError as e: + die(f"Failed to write empty config for {a}: {str(e)}") + elif line.startswith('ORDER'): + order = line.split('=')[1].split() + for o in order: + for d in Path(o).glob('**/'): + combine_config_layer(d) + else: + try: + arch, configs = line.split('=') + except ValueError: + die(f"Invalid line format in {control_file}: {line}") + if arch_mach and not arch.startswith(arch_mach): + continue + configs_list = configs.split(':') + tasks.append((arch, configs_list, order, flavor, count, output_dir, specpackage_name, enable_werror)) + count += 1 + except FileNotFoundError: + die(f"Control file {control_file} not found") + except IOError as e: + die(f"Error reading control file {control_file}: {str(e)}") + + # Use a process pool to handle the tasks + with Pool(processes=rhjobs) as pool: + try: + pool.starmap(merge_configs, tasks) + except Exception as e: + die(f"Error in process pool: {str(e)}") + +def main(): + parser = argparse.ArgumentParser(description='Merge kernel config files for RHEL builds.') + parser.add_argument('specpackage_name', nargs='?', default='kernel', help='Package name (default: kernel)') + parser.add_argument('flavor', nargs='?', help='Flavor to build (default: all in flavors file)') + parser.add_argument('--arch-mach', default='', help='ARCH_MACH filter') + parser.add_argument('--enable-werror', action='store_true', help='Enable WERROR configs') + parser.add_argument('--rhjobs', type=int, default=4, help='Number of parallel jobs (default: 4)') + args = parser.parse_args() + + output_dir = os.getcwd() + script_dir = os.path.dirname(os.path.abspath(__file__)) + os.chdir(script_dir) + + try: + if args.flavor is None or args.flavor == "": + try: + with open('flavors', 'r') as f: + flavors = [line.strip() for line in f if line.strip()] + except FileNotFoundError: + die("flavors file not found") + except IOError as e: + die(f"Error reading flavors file: {str(e)}") + else: + flavors = [args.flavor] + try: + with open('.flavors', 'w') as f: + f.write('\n'.join(flavors) + '\n') + except IOError as e: + die(f"Error writing .flavors file: {str(e)}") + for flavor in flavors: + build_flavor(flavor, output_dir, args.specpackage_name, args.arch_mach, args.enable_werror, args.rhjobs) + finally: + cleanup() + +if __name__ == '__main__': + if os.environ.get('RHTEST'): + sys.exit(0) + main() \ No newline at end of file diff --git a/redhat/configs/build_configs.sh b/redhat/configs/build_configs.sh deleted file mode 100755 index blahblah..blahblah 0 --- a/redhat/configs/build_configs.sh +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash -# -# This script merges together the hierarchy of CONFIG_* files under generic -# and debug to form the necessary $SPECPACKAGE_NAME<version>-<arch>-<variant>.config -# files for building RHEL kernels, based on the contents of a control file - -test -n "$RHTEST" && exit 0 - -SPECPACKAGE_NAME="${1:-kernel}" # defines the package name used -if [ -z "$2" ]; then - cat flavors > .flavors -else - echo "$2" > .flavors -fi - -SCRIPT=$(readlink -f "$0") -OUTPUT_DIR="$PWD" -SCRIPT_DIR=$(dirname "$SCRIPT") - -LANG=en_US.UTF-8 - -# to handle this script being a symlink -cd "$SCRIPT_DIR" - -set errexit -set nounset - -cleanup() -{ - rm -f config-* - rm -f .flavors -} - -die() -{ - echo "$1" - cleanup - exit 1 -} - -function combine_config_layer() -{ - dir=$1 - file="config-${dir//\//-}" - - # shellcheck disable=SC2010 - if [ "$(ls "$dir"/ | grep -c "^CONFIG_")" -eq 0 ]; then - touch "$file" - return - fi - - # avoid picking up editor backup files - # shellcheck disable=SC2046 - # shellcheck disable=SC2010 - cat $(ls -1 "$dir"/CONFIG_* | grep -v "~$") > "$file" -} - -function merge_configs() -{ - local archvar - local arch - local configs - local order - local flavor - local count - local name - local skip_if_missing - - archvar=$1 - arch=$(echo "$archvar" | cut -f1 -d"-") - configs=$2 - order=$3 - flavor=$4 - count=$5 - - name=$OUTPUT_DIR/$SPECPACKAGE_NAME-$archvar-$flavor.config - echo "Building $name ... " - touch config-merging."$count" config-merged."$count" - - # apply based on order - skip_if_missing="" - for o in $order - do - for config in ${configs//:/ } - do - cfile="config-$o-$config" - - test -n "$skip_if_missing" && test ! -e "$cfile" && continue - - if ! ./merge.py "$cfile" config-merging."$count" > config-merged."$count"; then - die "Failed to merge $cfile" - fi - mv config-merged."$count" config-merging."$count" - done - - # first configs in $order is baseline, all files should be - # there. second pass is overrides and can be missing. - skip_if_missing="1" - done - - case "$arch" in - "aarch64") - echo "# arm64" > "$name";; - "ppc64le") - echo "# powerpc" > "$name";; - "s390x") - echo "# s390" > "$name";; - "riscv64") - echo "# riscv" > "$name";; - *) - echo "# $arch" > "$name";; - esac - - sort config-merging."$count" >> "$name" - - if [ -n "$ENABLE_WERROR" ]; then - sed -i "s|# CONFIG_WERROR is not set|CONFIG_WERROR=y|g" "$name" - sed -i "s|# CONFIG_KVM_WERROR is not set|CONFIG_KVM_WERROR=y|g" "$name" - fi - - rm -f config-merged."$count" config-merging."$count" - echo "Building $name complete" -} - -function build_flavor() -{ - flavor=$1 - control_file="priority".$flavor - while read -r line - do - if [ "$(echo "$line" | grep -c "^#")" -ne 0 ]; then - continue - elif [ "$(echo "$line" | grep -c "^$")" -ne 0 ]; then - continue - elif [ "$(echo "$line" | grep -c "^EMPTY")" -ne 0 ]; then - empty=$(echo "$line" | cut -f2 -d"=") - for a in $empty - do - echo "# EMPTY" > "$OUTPUT_DIR/$SPECPACKAGE_NAME-$a-$flavor".config - - done - elif [ "$(echo "$line" | grep -c "^ORDER")" -ne 0 ]; then - order=$(echo "$line" | cut -f2 -d"=") - for o in $order - do - glist=$(find "$o" -type d) - for d in $glist - do - combine_config_layer "$d" - done - done - else - arch=$(echo "$line" | cut -f1 -d"=") - configs=$(echo "$line" | cut -f2 -d"=") - - if [ -n "$ARCH_MACH" ]; then - case $arch in - $ARCH_MACH*) - ;; - *) - continue - esac - fi - - merge_configs "$arch" "$configs" "$order" "$flavor" "$count" & - # shellcheck disable=SC2004 - waitpids[$count]=$! - ((count++)) - while [ "$(jobs | grep -c Running)" -ge "$RHJOBS" ]; do :; done - fi - done < "$control_file" - - # shellcheck disable=SC2048 - for pid in ${waitpids[*]}; do - wait "$pid" - done -} - -while read -r line -do - build_flavor "$line" -done < .flavors - -cleanup -- https://gitlab.com/cki-project/kernel-ark/-/merge_requests/3860 -- _______________________________________________ kernel mailing list -- kernel@lists.fedoraproject.org To unsubscribe send an email to kernel-le...@lists.fedoraproject.org Fedora Code of Conduct: https://docs.fedoraproject.org/en-US/project/code-of-conduct/ List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines List Archives: https://lists.fedoraproject.org/archives/list/kernel@lists.fedoraproject.org Do not reply to spam, report it: https://pagure.io/fedora-infrastructure/new_issue