aboutsummaryrefslogtreecommitdiff
path: root/lib/python/qmk/makefile.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python/qmk/makefile.py')
-rw-r--r--lib/python/qmk/makefile.py94
1 files changed, 51 insertions, 43 deletions
diff --git a/lib/python/qmk/makefile.py b/lib/python/qmk/makefile.py
index 6ed6b4b70..c53f12ac7 100644
--- a/lib/python/qmk/makefile.py
+++ b/lib/python/qmk/makefile.py
@@ -1,72 +1,80 @@
1""" Functions for working with Makefiles 1""" Functions for working with Makefiles
2""" 2"""
3import os 3import os
4import glob
5import re
6 4
7import qmk.path 5import qmk.path
8from qmk.errors import NoSuchKeyboardError 6from qmk.errors import NoSuchKeyboardError
9 7
10def parse_rules_mk(file_path): 8def parse_rules_mk_file(file, rules_mk=None):
11 """ Parse a rules.mk file 9 """Turn a rules.mk file into a dictionary.
12 10
13 Args: 11 Args:
14 file_path: path to the rules.mk file 12 file: path to the rules.mk file
13 rules_mk: already parsed rules.mk the new file should be merged with
15 14
16 Returns: 15 Returns:
17 a dictionary with the file's content 16 a dictionary with the file's content
18 """ 17 """
19 # regex to match lines uncommented lines and get the data 18 if not rules_mk:
20 # group(1) = option's name 19 rules_mk = {}
21 # group(2) = operator (eg.: '=', '+=')
22 # group(3) = value(s)
23 rules_mk_regex = re.compile(r"^\s*(\w+)\s*([\?\:\+\-]?=)\s*(\S.*?)(?=\s*(\#|$))")
24 parsed_file = dict()
25 mk_content = qmk.path.file_lines(file_path)
26 for line in mk_content:
27 found = rules_mk_regex.search(line)
28 if found:
29 parsed_file[found.group(1)] = dict(operator = found.group(2), value = found.group(3))
30 return parsed_file
31 20
32def merge_rules_mk_files(base, revision): 21 if os.path.exists(file):
33 """ Merge a keyboard revision's rules.mk file with 22 rules_mk_lines = qmk.path.file_lines(file)
34 the 'base' rules.mk file
35 23
36 Args: 24 for line in rules_mk_lines:
37 base: the base rules.mk file's content as dictionary 25 # Filter out comments
38 revision: the revision's rules.mk file's content as dictionary 26 if line.strip().startswith("#"):
27 continue
39 28
40 Returns: 29 # Strip in-line comments
41 a dictionary with the merged content 30 if '#' in line:
42 """ 31 line = line[:line.index('#')].strip()
43 return {**base, **revision} 32
33 if '=' in line:
34 # Append
35 if '+=' in line:
36 key, value = line.split('+=', 1)
37 if key.strip() not in rules_mk:
38 rules_mk[key.strip()] = value.strip()
39 else:
40 rules_mk[key.strip()] += ' ' + value.strip()
41 # Set if absent
42 elif "?=" in line:
43 key, value = line.split('?=', 1)
44 if key.strip() not in rules_mk:
45 rules_mk[key.strip()] = value.strip()
46 else:
47 if ":=" in line:
48 line.replace(":","")
49 key, value = line.split('=', 1)
50 rules_mk[key.strip()] = value.strip()
44 51
45def get_rules_mk(keyboard, revision = ""): 52 return rules_mk
53
54def get_rules_mk(keyboard):
46 """ Get a rules.mk for a keyboard 55 """ Get a rules.mk for a keyboard
47 56
48 Args: 57 Args:
49 keyboard: name of the keyboard 58 keyboard: name of the keyboard
50 revision: revision of the keyboard 59
60 Raises:
61 NoSuchKeyboardError: when the keyboard does not exists
51 62
52 Returns: 63 Returns:
53 a dictionary with the content of the rules.mk file 64 a dictionary with the content of the rules.mk file
54 """ 65 """
55 base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep 66 # Start with qmk_firmware/keyboards
56 rules_mk = dict() 67 kb_path = os.path.join(os.getcwd(), "keyboards")
57 if os.path.exists(base_path + os.path.sep + revision): 68 # walk down the directory tree
58 rules_mk_path_wildcard = os.path.join(base_path, "**", "rules.mk") 69 # and collect all rules.mk files
59 rules_mk_regex = re.compile(r"^" + base_path + "(?:" + revision + os.path.sep + ")?rules.mk") 70 if os.path.exists(os.path.join(kb_path, keyboard)):
60 paths = [path for path in glob.iglob(rules_mk_path_wildcard, recursive = True) if rules_mk_regex.search(path)] 71 rules_mk = dict()
61 for file_path in paths: 72 for directory in keyboard.split(os.path.sep):
62 rules_mk[revision if revision in file_path else "base"] = parse_rules_mk(file_path) 73 kb_path = os.path.join(kb_path, directory)
74 rules_mk_path = os.path.join(kb_path, "rules.mk")
75 if os.path.exists(rules_mk_path):
76 rules_mk = parse_rules_mk_file(rules_mk_path, rules_mk)
63 else: 77 else:
64 raise NoSuchKeyboardError("The requested keyboard and/or revision does not exist.") 78 raise NoSuchKeyboardError("The requested keyboard and/or revision does not exist.")
65 79
66 # if the base or the revision directory does not contain a rules.mk
67 if len(rules_mk) == 1:
68 rules_mk = rules_mk[revision]
69 # if both directories contain rules.mk files
70 elif len(rules_mk) == 2:
71 rules_mk = merge_rules_mk_files(rules_mk["base"], rules_mk[revision])
72 return rules_mk 80 return rules_mk