install_filegroups.bzl 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 constructing install information."""
  5. load("@rules_pkg//pkg:mappings.bzl", "pkg_attributes", "pkg_filegroup", "pkg_files", "pkg_mklink", "strip_prefix")
  6. load("symlink_helpers.bzl", "symlink_file", "symlink_filegroup")
  7. def install_filegroup(name, filegroup_target):
  8. """Adds a filegroup for install.
  9. Used in the `install_dirs` dict.
  10. Args:
  11. name: The base directory for the filegroup.
  12. filegroup_target: The bazel filegroup target to install.
  13. """
  14. return {
  15. "filegroup": filegroup_target,
  16. "is_driver": False,
  17. "name": name,
  18. }
  19. def install_symlink(name, symlink_to, is_driver = False):
  20. """Adds a symlink for install.
  21. Used in the `install_dirs` dict.
  22. Args:
  23. name: The filename to use.
  24. symlink_to: A relative path for the symlink.
  25. is_driver: False if it should be included in the `no_driver_name`
  26. filegroup.
  27. """
  28. return {
  29. "is_driver": is_driver,
  30. "name": name,
  31. "symlink": symlink_to,
  32. }
  33. def install_target(name, target, executable = False, is_driver = False):
  34. """Adds a target for install.
  35. Used in the `install_dirs` dict.
  36. Args:
  37. name: The filename to use.
  38. target: The bazel target being installed.
  39. executable: True if executable.
  40. is_driver: False if it should be included in the `no_driver_name`
  41. filegroup.
  42. """
  43. return {
  44. "executable": executable,
  45. "is_driver": is_driver,
  46. "name": name,
  47. "target": target,
  48. }
  49. def make_install_filegroups(name, no_driver_name, pkg_name, install_dirs, prefix):
  50. """Makes filegroups of install data.
  51. Args:
  52. name: The name of the main filegroup, that contains all install_data.
  53. no_driver_name: The name of a filegroup which excludes the driver. This is
  54. for the driver to depend on and get other files, without a circular
  55. dependency.
  56. pkg_name: The name of a pkg_filegroup for tar.
  57. install_dirs: A dict of {directory: [install_* rules]}. This is used to
  58. structure files to be installed.
  59. prefix: A prefix for files in the native (non-pkg) filegroups.
  60. """
  61. all_srcs = []
  62. no_driver_srcs = []
  63. pkg_srcs = []
  64. for dir, entries in install_dirs.items():
  65. for entry in entries:
  66. path = "{0}/{1}".format(dir, entry["name"])
  67. prefixed_path = "{0}/{1}".format(prefix, path)
  68. all_srcs.append(prefixed_path)
  69. if not entry["is_driver"]:
  70. no_driver_srcs.append(prefixed_path)
  71. pkg_path = path + ".pkg"
  72. pkg_srcs.append(pkg_path)
  73. if "target" in entry:
  74. if entry["executable"]:
  75. symlink_file(
  76. name = prefixed_path,
  77. symlink_binary = entry["target"],
  78. )
  79. mode = "0755"
  80. else:
  81. symlink_file(
  82. name = prefixed_path,
  83. symlink_label = entry["target"],
  84. )
  85. mode = "0644"
  86. pkg_files(
  87. name = pkg_path,
  88. srcs = [entry["target"]],
  89. attributes = pkg_attributes(mode = mode),
  90. renames = {entry["target"]: path},
  91. )
  92. elif "filegroup" in entry:
  93. symlink_filegroup(
  94. name = prefixed_path,
  95. out_prefix = prefixed_path,
  96. srcs = [entry["filegroup"]],
  97. )
  98. pkg_files(
  99. name = pkg_path,
  100. srcs = [prefixed_path],
  101. strip_prefix = strip_prefix.from_pkg(prefix),
  102. )
  103. elif "symlink" in entry:
  104. symlink_to = "{0}/{1}/{2}".format(prefix, dir, entry["symlink"])
  105. # For bazel, we need to resolve relative symlinks.
  106. if "../" in symlink_to:
  107. parts = symlink_to.split("/")
  108. result = []
  109. for part in parts:
  110. if part == "..":
  111. result = result[:-1]
  112. else:
  113. result.append(part)
  114. symlink_to = "/".join(result)
  115. symlink_file(
  116. name = prefixed_path,
  117. symlink_binary = symlink_to,
  118. )
  119. # For the distributed package, we retain relative symlinks.
  120. pkg_mklink(
  121. name = pkg_path,
  122. link_name = path,
  123. target = entry["symlink"],
  124. )
  125. else:
  126. fail("Unrecognized structure: {0}".format(entry))
  127. native.filegroup(name = name, srcs = all_srcs)
  128. native.filegroup(name = no_driver_name, srcs = no_driver_srcs)
  129. pkg_filegroup(name = pkg_name, srcs = pkg_srcs)