makefile.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. """ Functions for working with Makefiles
  2. """
  3. import os
  4. import glob
  5. import re
  6. import qmk.path
  7. from qmk.errors import NoSuchKeyboardError
  8. def parse_rules_mk(file_path):
  9. """ Parse a rules.mk file
  10. Args:
  11. file_path: path to the rules.mk file
  12. Returns:
  13. a dictionary with the file's content
  14. """
  15. # regex to match lines uncommented lines and get the data
  16. # group(1) = option's name
  17. # group(2) = operator (eg.: '=', '+=')
  18. # group(3) = value(s)
  19. rules_mk_regex = re.compile(r"^\s*(\w+)\s*([\?\:\+\-]?=)\s*(\S.*?)(?=\s*(\#|$))")
  20. parsed_file = dict()
  21. mk_content = qmk.path.file_lines(file_path)
  22. for line in mk_content:
  23. found = rules_mk_regex.search(line)
  24. if found:
  25. parsed_file[found.group(1)] = dict(operator = found.group(2), value = found.group(3))
  26. return parsed_file
  27. def merge_rules_mk_files(base, revision):
  28. """ Merge a keyboard revision's rules.mk file with
  29. the 'base' rules.mk file
  30. Args:
  31. base: the base rules.mk file's content as dictionary
  32. revision: the revision's rules.mk file's content as dictionary
  33. Returns:
  34. a dictionary with the merged content
  35. """
  36. return {**base, **revision}
  37. def get_rules_mk(keyboard, revision = ""):
  38. """ Get a rules.mk for a keyboard
  39. Args:
  40. keyboard: name of the keyboard
  41. revision: revision of the keyboard
  42. Returns:
  43. a dictionary with the content of the rules.mk file
  44. """
  45. base_path = os.path.join(os.getcwd(), "keyboards", keyboard) + os.path.sep
  46. rules_mk = dict()
  47. if os.path.exists(base_path + os.path.sep + revision):
  48. rules_mk_path_wildcard = os.path.join(base_path, "**", "rules.mk")
  49. rules_mk_regex = re.compile(r"^" + base_path + "(?:" + revision + os.path.sep + ")?rules.mk")
  50. paths = [path for path in glob.iglob(rules_mk_path_wildcard, recursive = True) if rules_mk_regex.search(path)]
  51. for file_path in paths:
  52. rules_mk[revision if revision in file_path else "base"] = parse_rules_mk(file_path)
  53. else:
  54. raise NoSuchKeyboardError("The requested keyboard and/or revision does not exist.")
  55. # if the base or the revision directory does not contain a rules.mk
  56. if len(rules_mk) == 1:
  57. rules_mk = rules_mk[revision]
  58. # if both directories contain rules.mk files
  59. elif len(rules_mk) == 2:
  60. rules_mk = merge_rules_mk_files(rules_mk["base"], rules_mk[revision])
  61. return rules_mk