require.bzl 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. def _needs_install(name, dep, hkeys=["sha256", "sha1", "tag"], verbose=0, strict=False):
  2. # Does it already exist?
  3. existing_rule = native.existing_rule(name)
  4. if not existing_rule:
  5. return True
  6. # If it has already been defined and our dependency lists a
  7. # hash, do these match? If a hash mismatch is encountered, has
  8. # the user specifically granted permission to continue?
  9. for hkey in hkeys:
  10. expected = dep.get(hkey)
  11. actual = existing_rule.get(hkey)
  12. if expected:
  13. # By guarding the check of expected vs actual with a
  14. # pre-check for actual=None (or empty string), we're
  15. # basically saying "If the user did not bother to set a
  16. # sha256 or sha1 hash for the rule, they probably don't
  17. # care about overriding a dependency either, so don't
  18. # complain about it." In particular, rules_go does not a
  19. # set a sha256 for their com_google_protobuf http_archive
  20. # rule, so this gives us a convenient loophole to prevent
  21. # collisions on this dependency. The "strict" flag can be
  22. # used as as master switch to disable blowing up the
  23. # loading phase due to dependency collisions.
  24. if actual and expected != actual and strict:
  25. msg = """
  26. An existing {0} rule '{1}' was already loaded with a {2} value of '{3}'. Refusing to overwrite this with the requested value ('{4}').
  27. Either remove the pre-existing rule from your WORKSPACE or exclude it from loading by rules_protobuf (strict={5}.
  28. """.format(existing_rule["kind"], name, hkey, actual, expected, strict)
  29. fail(msg)
  30. else:
  31. if verbose > 1: print("Skip reload %s: %s = %s" % (name, hkey, actual))
  32. return False
  33. # No kheys for this rule - in this case no reload; first one loaded wins.
  34. if verbose > 1: print("Skipping reload of existing target %s" % name)
  35. return False
  36. def _install(deps, verbose, strict):
  37. """Install a list if dependencies for matching native rules.
  38. Return:
  39. list of deps that have no matching native rule.
  40. """
  41. todo = []
  42. for d in deps:
  43. name = d.get("name")
  44. rule = d.pop("rule", None)
  45. if not rule:
  46. fail("Missing attribute 'rule': %s" % name)
  47. if hasattr(native, rule):
  48. rule = getattr(native, rule)
  49. if verbose: print("Loading %s)" % name)
  50. rule(**d)
  51. else:
  52. d["rule"] = rule
  53. todo.append(d)
  54. return todo
  55. def require(keys,
  56. deps = {},
  57. overrides = {},
  58. excludes = [],
  59. verbose = 0,
  60. strict = False):
  61. #
  62. # Make a list of non-excluded required deps with merged data.
  63. #
  64. required = []
  65. for key in keys:
  66. dep = deps.get(key)
  67. if not dep:
  68. fail("Unknown workspace dependency: %s" % key)
  69. d = dict(**dep) # copy the 'frozen' object.
  70. if not key in excludes:
  71. over = overrides.get(key)
  72. data = d + over if over else d
  73. if _needs_install(key, data, verbose=verbose, strict=strict):
  74. data["name"] = key
  75. required.append(data)
  76. return _install(required, verbose, strict)