-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix python variant of merge_config #5417
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,50 +3,91 @@ | |
import argparse | ||
import re | ||
|
||
|
||
def arguments_parse(): | ||
parser = argparse.ArgumentParser() | ||
parser.add_argument('-q', dest="quiet", action='store_true') | ||
parser.add_argument('-m', dest='runmake', action='store_false', | ||
help='only merge the fragments, do not execute the make command') | ||
parser.add_argument('-n', dest='alltarget', action='store_const', const='allnoconfig', default='alldefconfig', | ||
help='use allnoconfig instead of alldefconfig') | ||
parser.add_argument('-r', dest='warnredun', action='store_true', | ||
help='list redundant entries when merging fragments') | ||
help='list redundant entries when merging fragments') | ||
parser.add_argument('-O', dest='output_dir', | ||
help='to put generated output files', default='.') | ||
help='to put generated output files', default='.') | ||
parser.add_argument('config', nargs='+') | ||
|
||
return parser.parse_args() | ||
|
||
|
||
def get_config_name(line): | ||
# '# CONFIG_FOO is not set' should be treated by merge_config as a | ||
# state like any other | ||
|
||
is_not_set_pattern = re.compile('^# (CONFIG_[a-zA-Z0-9_]*) is not set.*') | ||
pattern = re.compile('^(CONFIG_[a-zA-Z0-9_]*)[= ].*') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This has issues:
I think two changes are needed:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That is a minor problem because that is invalid syntax, but it would be great for
I don't see how this affects the user, but if you can find a clean fix then why not :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Glad you agree it's OK to fix. It's fixed in my patch.
This script prints warnings on overrides. Warnings affect users. |
||
|
||
match = pattern.match(line) | ||
match_is_not_set = is_not_set_pattern.match(line) | ||
|
||
if match_is_not_set: | ||
return match_is_not_set.group(1) | ||
elif match: | ||
return match.group(1) | ||
|
||
return "" # No match | ||
|
||
def main(): | ||
args = arguments_parse() | ||
|
||
pattern = re.compile('^(CONFIG_[a-zA-Z0-9_]*)[= ].*') | ||
config_values = {} | ||
|
||
for config_file in args.config[:]: | ||
print("Merging %s" % config_file) | ||
with open(config_file, 'r') as file: | ||
for line in file: | ||
match = pattern.match(line) | ||
if match: | ||
config_name = match.group(1) | ||
config_full = match.group(0) | ||
if config_name in config_values: | ||
if config_values[config_name] != config_full and not args.quiet: | ||
print("Value of %s is redefined by fragment %s" % (config_name, config_file)) | ||
print("Previous value %s" % config_values[config_name]) | ||
print("new value %s" % config_full) | ||
elif args.warnredun: | ||
print("Value of %s is redundant by fragment %s" % (config_name, config_file)) | ||
config_values[config_name] = config_full | ||
|
||
if args.runmake: | ||
print("Running make not yet supported") | ||
|
||
with open('%s/.config' % args.output_dir, 'w') as out_config: | ||
out_config.write('\n'.join(map(lambda x: x[1], config_values.items()))) | ||
# Create a datastructure in 'conf' that looks like this: | ||
# [ | ||
# ("CONFIG_UART", "CONFIG_UART=y"), | ||
# ("CONFIG_ARM", "# CONFIG_ARM is not set") | ||
# ] | ||
# In other words [(config_name, config_line), ... ] | ||
# | ||
# Note that "# CONFIG_ARM is not set" is not the same as a | ||
# comment, it has meaning (for now). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really think the confusing "is not set" syntax is the "correct" syntax within kconfig. Some data on "# CONFIG_FOO is not set" versus "CONFIG_FOO=n":
All of the following also seem to say that "is not set" is valid:
So I think that the Zephyr habit of writing CONFIG_FOO=n directly in the .conf fragments should probably be deprecated. Don't get me wrong; I think this is an extremely annoying and confusing "feature" of Kconfig. It's even worse that CONFIG_FOO=n usage happens sometimes, even in upstream Linux. But I think it's important to preserve behavior in the Python re-implementations as long as Zephyr still uses Kconfig. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree. IMHO "# is not set" should eventually be deprecated in favour of "=n" for obvious reasons. Zephyr usability trumps Linux kernel Kconfig compatibility. EDIT: #5443 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I can see why you say so. There are many more people who are familiar with the Linux style than the Zephyr style, though, and I think it's "obvious" that we want to obey principle of least surprise, especially since Zephyr is a Linux Foundation project. @nashif, what's your decision? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I may weigh in, I think that both formats should be supported and should do exactly the same:
Should both turn Bluetooth OFF if present in the .conf or defconfig files There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe I've missed something, but does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To get this merged, I suggest we retain KBuild compatibilty for now, and then we can discuss the long-term Kconfig syntax at a later point. |
||
# https://github.com/zephyrproject-rtos/zephyr/issues/5443 | ||
conf = [] | ||
for i, fragment_path in enumerate(args.config): | ||
with open(fragment_path, "r") as f: | ||
fragment = f.read() | ||
fragment_list = fragment.split("\n") | ||
|
||
fragment_conf = [] | ||
for line in fragment_list: | ||
config_name = get_config_name(line) | ||
if config_name: | ||
fragment_conf.append( (config_name, line) ) | ||
|
||
if i == 0: | ||
print("-- Using {} as base".format(fragment_path)) | ||
else: | ||
print("-- Merging {}".format(fragment_path)) | ||
|
||
for config_name, line in fragment_conf: | ||
for (i, (prev_config_name, prev_line)) in enumerate(list(conf)): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the worst case, if there are |
||
if config_name == prev_config_name: | ||
# The fragment is defining a config that has | ||
# already been defined, the fragment has | ||
# priority, so we remove the existing entry | ||
# and then possibly issue a warning. | ||
conf.pop(i) | ||
|
||
is_redundant = line == prev_line | ||
is_redefine = line != prev_line | ||
if not args.quiet: | ||
if is_redefine: | ||
print("-- Value of {} is redefined by fragment {}".format(config_name, fragment_path)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it'd be an improvement to print these to stderr |
||
print("-- Previous value: {}".format(prev_line)) | ||
print("-- New value: {}".format(line)) | ||
|
||
if is_redundant and args.warnredun: | ||
print("-- Value of {} is redundant by fragment {}".format(config_name, fragment_path)) | ||
|
||
conf.extend(fragment_conf) | ||
|
||
with open('{}/.config'.format(args.output_dir), 'w') as f: | ||
for (config_name, line) in conf: | ||
f.write("{}\n".format(line)) | ||
|
||
if __name__ == "__main__": | ||
main() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this change a lot.