201 lines
9.3 KiB
Python
201 lines
9.3 KiB
Python
|
#!/usr/bin/env python
|
||
|
#
|
||
|
# Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES.
|
||
|
# Apache-2.0
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
#
|
||
|
|
||
|
import os
|
||
|
import io
|
||
|
import sys
|
||
|
import argparse
|
||
|
import shutil
|
||
|
import copy
|
||
|
import difflib
|
||
|
import configparser
|
||
|
|
||
|
from helper import *
|
||
|
|
||
|
################################################################################
|
||
|
#### KConfig Processing ####
|
||
|
################################################################################
|
||
|
|
||
|
class KCFGData:
|
||
|
x86_base = OrderedDict()
|
||
|
x86_updated = OrderedDict()
|
||
|
arm_base = OrderedDict()
|
||
|
arm_updated = OrderedDict()
|
||
|
x86_incl = OrderedDict()
|
||
|
arm_incl = OrderedDict()
|
||
|
x86_excl = OrderedDict()
|
||
|
arm_excl = OrderedDict()
|
||
|
x86_down = OrderedDict()
|
||
|
arm_down = OrderedDict()
|
||
|
noarch_incl = OrderedDict()
|
||
|
noarch_excl = OrderedDict()
|
||
|
noarch_down = OrderedDict()
|
||
|
|
||
|
|
||
|
class KConfigTask():
|
||
|
def __init__(self, args):
|
||
|
self.args = args
|
||
|
|
||
|
|
||
|
def read_data(self):
|
||
|
KCFGData.x86_base = FileHandler.read_kconfig(self.args.config_base_amd)
|
||
|
KCFGData.x86_updated = FileHandler.read_kconfig(self.args.config_inc_amd)
|
||
|
if os.path.isfile(self.args.config_inc_down_amd):
|
||
|
print(" -> Downstream Config for x86 found..")
|
||
|
KCFGData.x86_down = FileHandler.read_kconfig(self.args.config_inc_down_amd)
|
||
|
|
||
|
KCFGData.arm_base = FileHandler.read_kconfig(self.args.config_base_arm)
|
||
|
KCFGData.arm_updated = FileHandler.read_kconfig(self.args.config_inc_arm)
|
||
|
if os.path.isfile(self.args.config_inc_down_arm):
|
||
|
print(" -> Downstream Config for arm64 found..")
|
||
|
KCFGData.arm_down = FileHandler.read_kconfig(self.args.config_inc_down_arm)
|
||
|
return
|
||
|
|
||
|
|
||
|
def parse_inc_exc(self, base: OrderedDict, updated: OrderedDict):
|
||
|
# parse the updates/deletions in the Kconfig
|
||
|
add, remove = OrderedDict(), copy.deepcopy(base)
|
||
|
for (key, val) in updated.items():
|
||
|
if val != base.get(key, "empty"):
|
||
|
add[key] = val
|
||
|
# items remaining in remove are the ones to be excluded
|
||
|
if key in remove:
|
||
|
del remove[key]
|
||
|
return add, remove
|
||
|
|
||
|
|
||
|
def parse_noarch_inc_exc(self):
|
||
|
# Filter the common inc/excl out from the arch specific inc/excl
|
||
|
x86_incl_base = copy.deepcopy(KCFGData.x86_incl)
|
||
|
for (key, val) in x86_incl_base.items():
|
||
|
if key in KCFGData.arm_incl and val == KCFGData.arm_incl[key]:
|
||
|
print("-> INFO: NoArch KConfig Inclusion {}:{} found and moving to common marker".format(key, val))
|
||
|
del KCFGData.arm_incl[key]
|
||
|
del KCFGData.x86_incl[key]
|
||
|
KCFGData.noarch_incl[key] = val
|
||
|
|
||
|
x86_excl_base = copy.deepcopy(KCFGData.x86_excl)
|
||
|
for (key, val) in x86_excl_base.items():
|
||
|
if key in KCFGData.arm_excl:
|
||
|
print("-> INFO: NoArch KConfig Exclusion {} found and moving to common marker".format(key))
|
||
|
del KCFGData.arm_excl[key]
|
||
|
del KCFGData.x86_excl[key]
|
||
|
KCFGData.noarch_excl[key] = val
|
||
|
|
||
|
if not (KCFGData.x86_down or KCFGData.arm_down):
|
||
|
return
|
||
|
|
||
|
# Filter the common inc config from the downstream kconfig
|
||
|
x86_down_base = copy.deepcopy(KCFGData.x86_down)
|
||
|
for (key, val) in x86_down_base.items():
|
||
|
if key in KCFGData.arm_down:
|
||
|
print("-> INFO: NoArch KConfig Downstream Inclusion {} found and moving to common marker".format(key))
|
||
|
del KCFGData.arm_down[key]
|
||
|
del KCFGData.x86_down[key]
|
||
|
KCFGData.noarch_down[key] = val
|
||
|
|
||
|
def insert_arm64_section(self, raw_lines: list, arm_data: OrderedDict, is_exclusion=False, section=MLNX_ARM_KFG_SECTION) -> list:
|
||
|
# For arm64, config is not added under markers, but it is added under the section [mellanox-arm64]
|
||
|
# This design decision is taken because of the possibility that there might be conflicting options
|
||
|
# present between two different arm64 platforms
|
||
|
try:
|
||
|
# comment_prefixes needed to also read comments under a section
|
||
|
configParser = configparser.ConfigParser(allow_no_value=True, strict=False, comment_prefixes='////')
|
||
|
configParser.optionxform = str
|
||
|
configParser.read_string("".join(raw_lines))
|
||
|
if not configParser.has_section(MLNX_ARM_KFG_SECTION):
|
||
|
configParser.add_section(MLNX_ARM_KFG_SECTION)
|
||
|
for (key, val) in arm_data.items():
|
||
|
if not is_exclusion:
|
||
|
configParser.set(MLNX_ARM_KFG_SECTION, key, val)
|
||
|
else:
|
||
|
configParser.set(MLNX_ARM_KFG_SECTION, key)
|
||
|
str_io = io.StringIO()
|
||
|
configParser.write(str_io, space_around_delimiters=False)
|
||
|
return str_io.getvalue().splitlines(True)
|
||
|
except Exception as e:
|
||
|
print("-> FATAL: Exception {} found while adding opts under arm".format(str(e)))
|
||
|
raise e
|
||
|
return raw_lines
|
||
|
|
||
|
|
||
|
def get_kconfig_inc(self) -> list:
|
||
|
kcfg_inc_raw = FileHandler.read_raw(os.path.join(self.args.build_root, SLK_KCONFIG))
|
||
|
# Insert common config
|
||
|
noarch_start, noarch_end = FileHandler.find_marker_indices(kcfg_inc_raw, MLNX_NOARCH_MARKER)
|
||
|
kcfg_inc_raw = FileHandler.insert_kcfg_data(kcfg_inc_raw, noarch_start, noarch_end, KCFGData.noarch_incl)
|
||
|
# Insert x86 config
|
||
|
x86_start, x86_end = FileHandler.find_marker_indices(kcfg_inc_raw, MLNX_KFG_MARKER)
|
||
|
kcfg_inc_raw = FileHandler.insert_kcfg_data(kcfg_inc_raw, x86_start, x86_end, KCFGData.x86_incl)
|
||
|
# Insert arm config
|
||
|
kcfg_inc_raw = self.insert_arm64_section(kcfg_inc_raw, KCFGData.arm_incl)
|
||
|
print("\n -> INFO: kconfig-inclusion file is generated \n {}".format("".join(kcfg_inc_raw)))
|
||
|
return kcfg_inc_raw
|
||
|
|
||
|
|
||
|
def get_downstream_kconfig_inc(self, new_kcfg_upstream) -> list:
|
||
|
kcfg_final = copy.deepcopy(new_kcfg_upstream)
|
||
|
# insert common Kconfig
|
||
|
noarch_start, noarch_end = FileHandler.find_marker_indices(kcfg_final, MLNX_NOARCH_MARKER)
|
||
|
noarch_final = OrderedDict(list(KCFGData.noarch_incl.items()) + list(KCFGData.noarch_down.items()))
|
||
|
kcfg_final = FileHandler.insert_kcfg_data(kcfg_final, noarch_start, noarch_end, noarch_final)
|
||
|
# insert x86 Kconfig
|
||
|
x86_start, x86_end = FileHandler.find_marker_indices(kcfg_final, MLNX_KFG_MARKER)
|
||
|
x86_final = OrderedDict(list(KCFGData.x86_incl.items()) + list(KCFGData.x86_down.items()))
|
||
|
kcfg_final = FileHandler.insert_kcfg_data(kcfg_final, x86_start, x86_end, x86_final)
|
||
|
# insert arm Kconfig
|
||
|
arm_final = OrderedDict(list(KCFGData.arm_incl.items()) + list(KCFGData.arm_down.items()))
|
||
|
kcfg_final = self.insert_arm64_section(kcfg_final, arm_final)
|
||
|
# generate diff
|
||
|
diff = difflib.unified_diff(new_kcfg_upstream, kcfg_final, fromfile='a/patch/kconfig-inclusions', tofile="b/patch/kconfig-inclusions", lineterm="\n")
|
||
|
lines = []
|
||
|
for line in diff:
|
||
|
lines.append(line)
|
||
|
print("\n -> INFO: kconfig-inclusion.patch file is generated \n{}".format("".join(lines)))
|
||
|
return lines
|
||
|
|
||
|
|
||
|
def get_kconfig_excl(self) -> list:
|
||
|
# noarch_excl
|
||
|
kcfg_excl_raw = FileHandler.read_raw(os.path.join(self.args.build_root, SLK_KCONFIG_EXCLUDE))
|
||
|
# insert common Kconfig
|
||
|
noarch_start, noarch_end = FileHandler.find_marker_indices(kcfg_excl_raw, MLNX_NOARCH_MARKER)
|
||
|
kcfg_excl_raw = FileHandler.insert_kcfg_excl_data(kcfg_excl_raw, noarch_start, noarch_end, KCFGData.noarch_excl)
|
||
|
# insert x86 Kconfig
|
||
|
x86_start, x86_end = FileHandler.find_marker_indices(kcfg_excl_raw, MLNX_KFG_MARKER)
|
||
|
kcfg_excl_raw = FileHandler.insert_kcfg_excl_data(kcfg_excl_raw, x86_start, x86_end, KCFGData.x86_excl)
|
||
|
# insert arm Kconfig
|
||
|
kcfg_excl_raw = self.insert_arm64_section(kcfg_excl_raw, KCFGData.arm_excl, True)
|
||
|
print("\n -> INFO: kconfig-exclusion file is generated \n{}".format("".join(kcfg_excl_raw)))
|
||
|
return kcfg_excl_raw
|
||
|
|
||
|
|
||
|
def perform(self):
|
||
|
self.read_data()
|
||
|
KCFGData.x86_incl, KCFGData.x86_excl = self.parse_inc_exc(KCFGData.x86_base, KCFGData.x86_updated)
|
||
|
KCFGData.arm_incl, KCFGData.arm_excl = self.parse_inc_exc(KCFGData.arm_base, KCFGData.arm_updated)
|
||
|
self.parse_noarch_inc_exc()
|
||
|
# Get the updated kconfig-inclusions
|
||
|
kcfg_inc_upstream = self.get_kconfig_inc()
|
||
|
FileHandler.write_lines(os.path.join(self.args.build_root, SLK_KCONFIG), kcfg_inc_upstream, True)
|
||
|
# Get the updated kconfig-exclusions
|
||
|
kcfg_excl_upstream = self.get_kconfig_excl()
|
||
|
FileHandler.write_lines(os.path.join(self.args.build_root, SLK_KCONFIG_EXCLUDE), kcfg_excl_upstream, True)
|
||
|
# return the kconfig-inclusions diff
|
||
|
return self.get_downstream_kconfig_inc(kcfg_inc_upstream)
|