run_tool.bzl 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. # Exceptions. See /LICENSE for license information.
  3. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. """Supports running a tool from the install filegroup."""
  5. _RUN_TOOL_TMPL = """#!/usr/bin/env python3
  6. import os
  7. import sys
  8. # These will be relative locations in bazel-out.
  9. _SCRIPT_LOCATION = "{0}"
  10. _TOOL_LOCATION = "{1}"
  11. # Drop shared parent portions so that we're working with a minimum suffix.
  12. # This is so that both `bazel-out` and manual `bazel-bin` invocations work.
  13. script_parts = _SCRIPT_LOCATION.split('/')
  14. tool_parts = _TOOL_LOCATION.split('/')
  15. while script_parts and tool_parts and script_parts[0] == tool_parts[0]:
  16. del script_parts[0]
  17. del tool_parts[0]
  18. script_suffix = '/' + '/'.join(script_parts)
  19. tool_suffix = '/' + '/'.join(tool_parts)
  20. # Make sure we have the expected structure.
  21. if not __file__.endswith(script_suffix):
  22. exit(
  23. "Unable to figure out path:\\n"
  24. f" __file__: {{__file__}}\\n"
  25. f" script: {{script_suffix}}\\n"
  26. )
  27. # Run the tool using the absolute path, forwarding arguments.
  28. tool_path = __file__.removesuffix(script_suffix) + tool_suffix
  29. os.execv(tool_path, [tool_path] + sys.argv[1:])
  30. """
  31. def _run_tool_impl(ctx):
  32. content = _RUN_TOOL_TMPL.format(ctx.outputs.executable.path, ctx.file.tool.path)
  33. ctx.actions.write(
  34. output = ctx.outputs.executable,
  35. is_executable = True,
  36. content = content,
  37. )
  38. return [
  39. DefaultInfo(
  40. runfiles = ctx.runfiles(files = ctx.files.data),
  41. ),
  42. RunEnvironmentInfo(environment = ctx.attr.env),
  43. ]
  44. run_tool = rule(
  45. doc = "Helper for running a tool in a filegroup.",
  46. implementation = _run_tool_impl,
  47. attrs = {
  48. "data": attr.label_list(allow_files = True),
  49. "env": attr.string_dict(),
  50. "tool": attr.label(
  51. allow_single_file = True,
  52. executable = True,
  53. cfg = "target",
  54. mandatory = True,
  55. ),
  56. },
  57. executable = True,
  58. )