defs.bzl 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  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. """Provides rules for building Carbon files using the toolchain."""
  5. def _carbon_binary_impl(ctx):
  6. toolchain_driver = ctx.executable.internal_exec_toolchain_driver
  7. toolchain_data = ctx.files.internal_exec_toolchain_data
  8. # If the exec driver isn't provided, that means we're trying to use a target
  9. # config toolchain, likely to avoid build overhead of two configs.
  10. if toolchain_driver == None:
  11. toolchain_driver = ctx.executable.internal_target_toolchain_driver
  12. toolchain_data = ctx.files.internal_target_toolchain_data
  13. # Build object files for the prelude and for the binary itself.
  14. # TODO: Eventually the prelude should be build as a separate `carbon_library`.
  15. srcs_and_flags = [
  16. (ctx.files.prelude_srcs, ["--no-prelude-import"]),
  17. (ctx.files.srcs, []),
  18. ]
  19. objs = []
  20. for (srcs, extra_flags) in srcs_and_flags:
  21. for src in srcs:
  22. # Build each source file. For now, we pass all sources to each compile
  23. # because we don't have visibility into dependencies and have no way to
  24. # specify multiple output files. Object code for each input is written
  25. # into the output file in turn, so the final carbon source file
  26. # specified ends up determining the contents of the object file.
  27. #
  28. # TODO: This is a hack; replace with something better once the toolchain
  29. # supports doing so.
  30. #
  31. # TODO: Switch to the `prefix_root` based rule similar to linking when
  32. # the prelude moves there.
  33. out = ctx.actions.declare_file("_objs/{0}/{1}o".format(
  34. ctx.label.name,
  35. src.short_path.removeprefix(ctx.label.package).removesuffix(src.extension),
  36. ))
  37. objs.append(out)
  38. srcs_reordered = [s for s in srcs if s != src] + [src]
  39. ctx.actions.run(
  40. outputs = [out],
  41. inputs = srcs_reordered,
  42. executable = toolchain_driver,
  43. tools = depset(toolchain_data),
  44. arguments = ["compile", "--output=" + out.path] + [s.path for s in srcs_reordered] + extra_flags,
  45. mnemonic = "CarbonCompile",
  46. progress_message = "Compiling " + src.short_path,
  47. )
  48. bin = ctx.actions.declare_file(ctx.label.name)
  49. ctx.actions.run(
  50. outputs = [bin],
  51. inputs = objs,
  52. executable = toolchain_driver,
  53. tools = depset(toolchain_data),
  54. arguments = ["link", "--output=" + bin.path] + [o.path for o in objs],
  55. mnemonic = "CarbonLink",
  56. progress_message = "Linking " + bin.short_path,
  57. )
  58. return [DefaultInfo(files = depset([bin]), executable = bin)]
  59. _carbon_binary_internal = rule(
  60. implementation = _carbon_binary_impl,
  61. attrs = {
  62. # The exec config toolchain driver and data. These will be `None` when
  63. # using the target config and populated when using the exec config. We
  64. # have to use duplicate attributes here and below to have different
  65. # `cfg` settings, as that isn't `select`-able, and we'll use `select`s
  66. # when populating these.
  67. "internal_exec_toolchain_data": attr.label(
  68. cfg = "exec",
  69. ),
  70. "internal_exec_toolchain_driver": attr.label(
  71. allow_single_file = True,
  72. executable = True,
  73. cfg = "exec",
  74. ),
  75. # The target config toolchain driver and data. These will be 'None' when
  76. # using the exec config and populated when using the target config. We
  77. # have to use duplicate attributes here and below to have different
  78. # `cfg` settings, as that isn't `select`-able, and we'll use `select`s
  79. # when populating these.
  80. "internal_target_toolchain_data": attr.label(
  81. cfg = "target",
  82. ),
  83. "internal_target_toolchain_driver": attr.label(
  84. allow_single_file = True,
  85. executable = True,
  86. cfg = "target",
  87. ),
  88. "prelude_srcs": attr.label_list(allow_files = [".carbon"]),
  89. "srcs": attr.label_list(allow_files = [".carbon"]),
  90. },
  91. executable = True,
  92. )
  93. def carbon_binary(name, srcs):
  94. """Compiles a Carbon binary.
  95. Args:
  96. name: The name of the build target.
  97. srcs: List of Carbon source files to compile.
  98. """
  99. _carbon_binary_internal(
  100. name = name,
  101. srcs = srcs,
  102. prelude_srcs = ["//core:prelude_files"],
  103. # We synthesize two sets of attributes from mirrored `select`s here
  104. # because we want to select on an internal property of these attributes
  105. # but that isn't `select`-able. Instead, we have both attributes and
  106. # `select` which one we use.
  107. internal_exec_toolchain_driver = select({
  108. "//bazel/carbon_rules:use_target_config_carbon_rules_config": None,
  109. "//conditions:default": "//toolchain/install:prefix_root/bin/carbon",
  110. }),
  111. internal_exec_toolchain_data = select({
  112. "//bazel/carbon_rules:use_target_config_carbon_rules_config": None,
  113. "//conditions:default": "//toolchain/install:install_data",
  114. }),
  115. internal_target_toolchain_driver = select({
  116. "//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/install:prefix_root/bin/carbon",
  117. "//conditions:default": None,
  118. }),
  119. internal_target_toolchain_data = select({
  120. "//bazel/carbon_rules:use_target_config_carbon_rules_config": "//toolchain/install:install_data",
  121. "//conditions:default": None,
  122. }),
  123. )