install_filegroups.bzl 5.2 KB

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