You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

72 lines
2.4 KiB

  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