build_defs.bzl 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. """Internal rules for building upb."""
  2. load(":upb_proto_library.bzl", "GeneratedSrcsInfo")
  3. def _librule(name):
  4. return name + "_lib"
  5. def _get_real_short_path(file):
  6. # For some reason, files from other archives have short paths that look like:
  7. # ../com_google_protobuf/google/protobuf/descriptor.proto
  8. short_path = file.short_path
  9. if short_path.startswith("../"):
  10. second_slash = short_path.index("/", 3)
  11. short_path = short_path[second_slash + 1:]
  12. return short_path
  13. def _get_real_root(file):
  14. real_short_path = _get_real_short_path(file)
  15. return file.path[:-len(real_short_path) - 1]
  16. def _get_real_roots(files):
  17. roots = {}
  18. for file in files:
  19. real_root = _get_real_root(file)
  20. if real_root:
  21. roots[real_root] = True
  22. return roots.keys()
  23. def lua_cclibrary(name, srcs, hdrs = [], deps = [], luadeps = []):
  24. lib_rule = name + "_lib"
  25. so_rule = "lib" + name + ".so"
  26. so_file = _remove_prefix(name, "lua/") + ".so"
  27. native.cc_library(
  28. name = _librule(name),
  29. hdrs = hdrs,
  30. srcs = srcs,
  31. deps = deps + [_librule(dep) for dep in luadeps] + ["@lua//:liblua_headers"],
  32. )
  33. native.cc_binary(
  34. name = so_rule,
  35. linkshared = True,
  36. deps = [_librule(name)],
  37. linkopts = select({
  38. ":darwin": [
  39. "-undefined dynamic_lookup",
  40. ],
  41. "//conditions:default": [],
  42. }),
  43. )
  44. native.genrule(
  45. name = name + "_copy",
  46. srcs = [":" + so_rule],
  47. outs = [so_file],
  48. cmd = "cp $< $@",
  49. )
  50. native.filegroup(
  51. name = name,
  52. data = [so_file],
  53. )
  54. def _remove_prefix(str, prefix):
  55. if not str.startswith(prefix):
  56. fail("%s doesn't start with %s" % (str, prefix))
  57. return str[len(prefix):]
  58. def _remove_suffix(str, suffix):
  59. if not str.endswith(suffix):
  60. fail("%s doesn't end with %s" % (str, suffix))
  61. return str[:-len(suffix)]
  62. def lua_library(name, srcs, strip_prefix, luadeps = []):
  63. outs = [_remove_prefix(src, strip_prefix + "/") for src in srcs]
  64. native.genrule(
  65. name = name + "_copy",
  66. srcs = srcs,
  67. outs = outs,
  68. cmd = "cp $(SRCS) $(@D)",
  69. )
  70. native.filegroup(
  71. name = name,
  72. data = outs + luadeps,
  73. )
  74. def make_shell_script(name, contents, out):
  75. contents = contents.replace("$", "$$")
  76. native.genrule(
  77. name = "gen_" + name,
  78. outs = [out],
  79. cmd = "(cat <<'HEREDOC'\n%s\nHEREDOC\n) > $@" % contents,
  80. )
  81. def _lua_binary_or_test(name, luamain, luadeps, rule):
  82. script = name + ".sh"
  83. make_shell_script(
  84. name = "gen_" + name,
  85. out = script,
  86. contents = """
  87. BASE=$(dirname $(rlocation upb/upb_c.so))
  88. export LUA_CPATH="$BASE/?.so"
  89. export LUA_PATH="$BASE/?.lua"
  90. $(rlocation lua/lua) $(rlocation upb/tools/upbc.lua) "$@"
  91. """,
  92. )
  93. rule(
  94. name = name,
  95. srcs = [script],
  96. data = ["@lua//:lua", luamain] + luadeps,
  97. )
  98. def lua_binary(name, luamain, luadeps = []):
  99. _lua_binary_or_test(name, luamain, luadeps, native.sh_binary)
  100. def lua_test(name, luamain, luadeps = []):
  101. _lua_binary_or_test(name, luamain, luadeps, native.sh_test)
  102. def generated_file_staleness_test(name, outs, generated_pattern):
  103. """Tests that checked-in file(s) match the contents of generated file(s).
  104. The resulting test will verify that all output files exist and have the
  105. correct contents. If the test fails, it can be invoked with --fix to
  106. bring the checked-in files up to date.
  107. Args:
  108. name: Name of the rule.
  109. outs: the checked-in files that are copied from generated files.
  110. generated_pattern: the pattern for transforming each "out" file into a
  111. generated file. For example, if generated_pattern="generated/%s" then
  112. a file foo.txt will look for generated file generated/foo.txt.
  113. """
  114. script_name = name + ".py"
  115. script_src = "//:tools/staleness_test.py"
  116. # Filter out non-existing rules so Blaze doesn't error out before we even
  117. # run the test.
  118. existing_outs = native.glob(include = outs)
  119. # The file list contains a few extra bits of information at the end.
  120. # These get unpacked by the Config class in staleness_test_lib.py.
  121. file_list = outs + [generated_pattern, native.package_name() or ".", name]
  122. native.genrule(
  123. name = name + "_makescript",
  124. outs = [script_name],
  125. srcs = [script_src],
  126. testonly = 1,
  127. cmd = "cat $(location " + script_src + ") > $@; " +
  128. "sed -i.bak -e 's|INSERT_FILE_LIST_HERE|" + "\\\n ".join(file_list) + "|' $@",
  129. )
  130. native.py_test(
  131. name = name,
  132. srcs = [script_name],
  133. data = existing_outs + [generated_pattern % file for file in outs],
  134. deps = [
  135. "//:staleness_test_lib",
  136. ],
  137. )
  138. # upb_amalgamation() rule, with file_list aspect.
  139. SrcList = provider(
  140. fields = {
  141. "srcs": "list of srcs",
  142. },
  143. )
  144. def _file_list_aspect_impl(target, ctx):
  145. if GeneratedSrcsInfo in target:
  146. srcs = target[GeneratedSrcsInfo]
  147. return [SrcList(srcs = srcs.srcs + srcs.hdrs)]
  148. srcs = []
  149. for src in ctx.rule.attr.srcs:
  150. srcs += src.files.to_list()
  151. for hdr in ctx.rule.attr.hdrs:
  152. srcs += hdr.files.to_list()
  153. for hdr in ctx.rule.attr.textual_hdrs:
  154. srcs += hdr.files.to_list()
  155. return [SrcList(srcs = srcs)]
  156. _file_list_aspect = aspect(
  157. implementation = _file_list_aspect_impl,
  158. )
  159. def _upb_amalgamation(ctx):
  160. inputs = []
  161. for lib in ctx.attr.libs:
  162. inputs += lib[SrcList].srcs
  163. srcs = [src for src in inputs if src.path.endswith("c")]
  164. ctx.actions.run(
  165. inputs = inputs,
  166. outputs = ctx.outputs.outs,
  167. arguments = [ctx.bin_dir.path + "/"] + [f.path for f in srcs] + ["-I" + root for root in _get_real_roots(inputs)],
  168. progress_message = "Making amalgamation",
  169. executable = ctx.executable.amalgamator,
  170. )
  171. return []
  172. upb_amalgamation = rule(
  173. attrs = {
  174. "amalgamator": attr.label(
  175. executable = True,
  176. cfg = "host",
  177. ),
  178. "libs": attr.label_list(aspects = [_file_list_aspect]),
  179. "outs": attr.output_list(),
  180. },
  181. implementation = _upb_amalgamation,
  182. )
  183. def licenses(*args):
  184. # No-op (for Google-internal usage).
  185. pass