aboutsummaryrefslogtreecommitdiff
path: root/lib/python/qmk/makefile.py
diff options
context:
space:
mode:
authorErovia <erovia@users.noreply.github.com>2019-10-28 09:23:06 +0100
committerskullydazed <skullydazed@users.noreply.github.com>2020-02-15 15:19:03 -0800
commit988bfffca2715df3f227c462533d350ecbeac6c0 (patch)
tree975be087ae9944b31516a44f193b595791d93ed2 /lib/python/qmk/makefile.py
parent8ff72d9517132fe82c6e2d1dc8fc56f7cab4b6a0 (diff)
downloadqmk_firmware-988bfffca2715df3f227c462533d350ecbeac6c0.tar.gz
qmk_firmware-988bfffca2715df3f227c462533d350ecbeac6c0.zip
Major rework, no regex/globbing, more walking
Instead of using regexes and globbing to find the rules.mk and keymap.c files, walk the directory tree to find them. Also, do away with the concept of revision.
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