symlink_helpers.bzl 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. """Rules for symlinking in ways that assist install_filegroups."""
  5. def _symlink_file_impl(ctx):
  6. executable = None
  7. if ctx.attr.symlink_binary:
  8. out = ctx.actions.declare_file(ctx.label.name)
  9. ctx.actions.symlink(
  10. output = out,
  11. target_file = ctx.file.symlink_binary,
  12. is_executable = True,
  13. )
  14. executable = out
  15. elif ctx.attr.symlink_label:
  16. out = ctx.actions.declare_file(ctx.label.name)
  17. ctx.actions.symlink(
  18. output = out,
  19. target_file = ctx.file.symlink_label,
  20. )
  21. else:
  22. fail("Missing symlink target")
  23. return [
  24. DefaultInfo(
  25. executable = executable,
  26. files = depset(direct = [out]),
  27. default_runfiles = ctx.runfiles(files = [out]),
  28. ),
  29. ]
  30. symlink_file = rule(
  31. doc = "Symlinks a single file, with support for multiple approaches.",
  32. implementation = _symlink_file_impl,
  33. attrs = {
  34. "symlink_binary": attr.label(
  35. allow_single_file = True,
  36. executable = True,
  37. cfg = "target",
  38. ),
  39. "symlink_label": attr.label(allow_single_file = True),
  40. },
  41. )
  42. def _symlink_filegroup_impl(ctx):
  43. prefix = ctx.attr.out_prefix
  44. outputs = []
  45. for f in ctx.files.srcs:
  46. # We normalize the path to be package-relative in order to ensure
  47. # consistent paths across possible repositories.
  48. relative_path = f.short_path.removeprefix(f.owner.package)
  49. out = ctx.actions.declare_file(prefix + relative_path)
  50. outputs.append(out)
  51. ctx.actions.symlink(output = out, target_file = f)
  52. if len(ctx.files.srcs) != len(outputs):
  53. fail("Output count mismatch!")
  54. return [
  55. DefaultInfo(
  56. files = depset(direct = outputs),
  57. default_runfiles = ctx.runfiles(files = outputs),
  58. ),
  59. ]
  60. symlink_filegroup = rule(
  61. doc = "Symlinks an entire filegroup, preserving its structure",
  62. implementation = _symlink_filegroup_impl,
  63. attrs = {
  64. "out_prefix": attr.string(mandatory = True),
  65. "srcs": attr.label_list(mandatory = True),
  66. },
  67. )