repo.bzl 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. # Copyright 2017 The TensorFlow Authors. All rights reserved.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. """Utilities for defining TensorFlow Bazel dependencies."""
  15. _SINGLE_URL_WHITELIST = depset([
  16. "arm_compiler",
  17. "ortools_archive",
  18. ])
  19. def _is_windows(ctx):
  20. return ctx.os.name.lower().find("windows") != -1
  21. def _wrap_bash_cmd(ctx, cmd):
  22. if _is_windows(ctx):
  23. bazel_sh = _get_env_var(ctx, "BAZEL_SH")
  24. if not bazel_sh:
  25. fail("BAZEL_SH environment variable is not set")
  26. cmd = [bazel_sh, "-l", "-c", " ".join(cmd)]
  27. return cmd
  28. def _get_env_var(ctx, name):
  29. if name in ctx.os.environ:
  30. return ctx.os.environ[name]
  31. else:
  32. return None
  33. # Executes specified command with arguments and calls 'fail' if it exited with
  34. # non-zero code
  35. def _execute_and_check_ret_code(repo_ctx, cmd_and_args):
  36. result = repo_ctx.execute(cmd_and_args, timeout=10)
  37. if result.return_code != 0:
  38. fail(("Non-zero return code({1}) when executing '{0}':\n" + "Stdout: {2}\n"
  39. + "Stderr: {3}").format(" ".join(cmd_and_args), result.return_code,
  40. result.stdout, result.stderr))
  41. def _repos_are_siblings():
  42. return Label("@foo//bar").workspace_root.startswith("../")
  43. # Apply a patch_file to the repository root directory
  44. # Runs 'patch -p1'
  45. def _apply_patch(ctx, patch_file):
  46. # Don't check patch on Windows, because patch is only available under bash.
  47. if not _is_windows(ctx) and not ctx.which("patch"):
  48. fail("patch command is not found, please install it")
  49. cmd = _wrap_bash_cmd(
  50. ctx, ["patch", "-p1", "-d", ctx.path("."), "-i", ctx.path(patch_file)])
  51. _execute_and_check_ret_code(ctx, cmd)
  52. def _apply_delete(ctx, paths):
  53. for path in paths:
  54. if path.startswith("/"):
  55. fail("refusing to rm -rf path starting with '/': " + path)
  56. if ".." in path:
  57. fail("refusing to rm -rf path containing '..': " + path)
  58. cmd = _wrap_bash_cmd(ctx, ["rm", "-rf"] + [ctx.path(path) for path in paths])
  59. _execute_and_check_ret_code(ctx, cmd)
  60. def _bili_http_archive(ctx):
  61. """"
  62. if ("mirror.bazel.build" not in ctx.attr.urls[0] or
  63. (len(ctx.attr.urls) < 2 and
  64. ctx.attr.name not in _SINGLE_URL_WHITELIST)):
  65. fail("bili_http_archive(urls) must have redundant URLs. The " +
  66. "mirror.bazel.build URL must be present and it must come first. " +
  67. "Even if you don't have permission to mirror the file, please " +
  68. "put the correctly formatted mirror URL there anyway, because " +
  69. "someone will come along shortly thereafter and mirror the file.")
  70. """
  71. ctx.download_and_extract(
  72. ctx.attr.urls,
  73. "",
  74. ctx.attr.sha256,
  75. ctx.attr.type,
  76. ctx.attr.strip_prefix)
  77. if ctx.attr.delete:
  78. _apply_delete(ctx, ctx.attr.delete)
  79. if ctx.attr.patch_file != None:
  80. _apply_patch(ctx, ctx.attr.patch_file)
  81. if ctx.attr.build_file != None:
  82. ctx.template("BUILD", ctx.attr.build_file, {
  83. "%prefix%": ".." if _repos_are_siblings() else "external",
  84. }, False)
  85. bili_http_archive = repository_rule(
  86. implementation=_bili_http_archive,
  87. attrs={
  88. "sha256": attr.string(mandatory=True),
  89. "urls": attr.string_list(mandatory=True, allow_empty=False),
  90. "strip_prefix": attr.string(),
  91. "type": attr.string(),
  92. "delete": attr.string_list(),
  93. "patch_file": attr.label(),
  94. "build_file": attr.label(),
  95. })
  96. """Downloads and creates Bazel repos for dependencies.
  97. This is a swappable replacement for both http_archive() and
  98. new_http_archive() that offers some additional features. It also helps
  99. ensure best practices are followed.
  100. """