proto_library.gni 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. # Copyright 2019 the V8 project authors. All rights reserved.
  2. # Use of this source code is governed by a BSD-style license that can be
  3. # found in the LICENSE file.
  4. import("//build_overrides/build.gni")
  5. # This file should not be pulled in chromium builds.
  6. assert(!build_with_chromium)
  7. if (host_os == "win") {
  8. _host_executable_suffix = ".exe"
  9. } else {
  10. _host_executable_suffix = ""
  11. }
  12. template("proto_library") {
  13. assert(defined(invoker.sources))
  14. proto_sources = invoker.sources
  15. # All the proto imports should be relative to the project root.
  16. proto_in_dir = "//"
  17. if (defined(invoker.proto_in_dir)) {
  18. proto_in_dir = invoker.proto_in_dir
  19. }
  20. assert(defined(invoker.proto_out_dir),
  21. "proto_out_dir must be explicitly defined")
  22. proto_out_dir = invoker.proto_out_dir
  23. # We don't support generate_python in the standalone build, but still must
  24. # check that the caller sets this to false. This is because when building in
  25. # the chromium tree, chromium's proto_library.gni in chrome (!= this) defaults
  26. # generate_python = true.
  27. assert(defined(invoker.generate_python) && !invoker.generate_python)
  28. import_dirs = []
  29. if (defined(invoker.import_dirs)) {
  30. import_dirs = invoker.import_dirs
  31. }
  32. # If false will not generate the default .pb.{cc,h} files. Used for custom
  33. # codegen plugins.
  34. generate_cc = true
  35. if (defined(invoker.generate_cc)) {
  36. generate_cc = invoker.generate_cc
  37. }
  38. generate_descriptor = ""
  39. if (defined(invoker.generate_descriptor)) {
  40. generate_descriptor = invoker.generate_descriptor
  41. }
  42. if (defined(invoker.generator_plugin_label)) {
  43. plugin_host_label = invoker.generator_plugin_label + "($host_toolchain)"
  44. plugin_path =
  45. get_label_info(plugin_host_label, "root_out_dir") + "/" +
  46. get_label_info(plugin_host_label, "name") + _host_executable_suffix
  47. generate_with_plugin = true
  48. } else if (defined(invoker.generator_plugin_script)) {
  49. plugin_path = invoker.generator_plugin_script
  50. generate_with_plugin = true
  51. } else {
  52. generate_with_plugin = false
  53. }
  54. if (generate_with_plugin) {
  55. if (defined(invoker.generator_plugin_suffix)) {
  56. generator_plugin_suffixes = [
  57. "${invoker.generator_plugin_suffix}.h",
  58. "${invoker.generator_plugin_suffix}.cc",
  59. ]
  60. } else {
  61. generator_plugin_suffixes = invoker.generator_plugin_suffixes
  62. }
  63. }
  64. out_dir = "$root_gen_dir/" + proto_out_dir
  65. rel_out_dir = rebase_path(out_dir, root_build_dir)
  66. # Prevent unused errors when generating descriptor only.
  67. if (generate_descriptor != "") {
  68. not_needed([ "rel_out_dir" ])
  69. }
  70. protos = rebase_path(proto_sources, proto_in_dir)
  71. protogens = []
  72. if (generate_descriptor != "") {
  73. protogens += [ "$out_dir/${generate_descriptor}" ]
  74. }
  75. foreach(proto, protos) {
  76. proto_dir = get_path_info(proto, "dir")
  77. proto_name = get_path_info(proto, "name")
  78. proto_path = proto_dir + "/" + proto_name
  79. # Prevent unused errors when generating descriptor only.
  80. if (generate_descriptor != "") {
  81. not_needed([ "proto_path" ])
  82. }
  83. if (generate_cc) {
  84. protogens += [
  85. "$out_dir/$proto_path.pb.h",
  86. "$out_dir/$proto_path.pb.cc",
  87. ]
  88. }
  89. if (generate_with_plugin) {
  90. foreach(suffix, generator_plugin_suffixes) {
  91. protogens += [ "$out_dir/${proto_path}${suffix}" ]
  92. }
  93. }
  94. }
  95. config_name = "${target_name}_config"
  96. if (generate_descriptor == "") {
  97. action_name = "${target_name}_gen"
  98. source_set_name = target_name
  99. } else {
  100. action_name = target_name
  101. }
  102. config(config_name) {
  103. include_dirs = [ out_dir ]
  104. }
  105. # The XXX_gen action that generates the .pb.{cc,h} files.
  106. action(action_name) {
  107. if (generate_descriptor == "") {
  108. visibility = [ ":$source_set_name" ]
  109. }
  110. sources = proto_sources
  111. outputs = get_path_info(protogens, "abspath")
  112. protoc_label = "//:protoc($host_toolchain)"
  113. protoc_path = get_label_info(protoc_label, "root_out_dir") + "/protoc" +
  114. _host_executable_suffix
  115. protoc_rebased_path = "./" + rebase_path(protoc_path, root_build_dir)
  116. script = "//gni/protoc.py"
  117. args = [
  118. # Path should be rebased because |root_build_dir| for current toolchain
  119. # may be different from |root_out_dir| of protoc built on host toolchain.
  120. protoc_rebased_path,
  121. "--proto_path",
  122. rebase_path(proto_in_dir, root_build_dir),
  123. ]
  124. foreach(path, import_dirs) {
  125. args += [
  126. "--proto_path",
  127. rebase_path(path, root_build_dir),
  128. ]
  129. }
  130. if (generate_cc) {
  131. cc_generator_options_ = ""
  132. if (defined(invoker.cc_generator_options)) {
  133. cc_generator_options_ = invoker.cc_generator_options
  134. }
  135. args += [
  136. "--cpp_out",
  137. cc_generator_options_ + rel_out_dir,
  138. ]
  139. }
  140. if (generate_descriptor != "") {
  141. depfile = "$out_dir/$generate_descriptor.d"
  142. args += [
  143. "--include_imports",
  144. "--descriptor_set_out",
  145. rebase_path("$out_dir/$generate_descriptor", root_build_dir),
  146. "--dependency_out",
  147. rebase_path(depfile, root_build_dir),
  148. ]
  149. }
  150. if (generate_with_plugin) {
  151. plugin_path_rebased = rebase_path(plugin_path, root_build_dir)
  152. plugin_out_args = ""
  153. if (defined(invoker.generator_plugin_options)) {
  154. plugin_out_args += invoker.generator_plugin_options
  155. }
  156. plugin_out_args += ":$rel_out_dir"
  157. args += [
  158. "--plugin=protoc-gen-plugin=$plugin_path_rebased",
  159. "--plugin_out=$plugin_out_args",
  160. ]
  161. }
  162. args += rebase_path(proto_sources, root_build_dir)
  163. inputs = [ protoc_path ]
  164. deps = [ protoc_label ]
  165. # TODO(hjd): Avoid adding to deps here this.
  166. # When we generate BUILD files we need find the transitive proto,
  167. # dependencies, so also add link_deps to actual deps so they show up
  168. # in gn desc.
  169. if (defined(invoker.link_deps)) {
  170. deps += invoker.link_deps
  171. }
  172. if (generate_with_plugin) {
  173. inputs += [ plugin_path ]
  174. if (defined(plugin_host_label)) {
  175. # Action depends on native generator plugin but for host toolchain only.
  176. deps += [ plugin_host_label ]
  177. }
  178. }
  179. if (defined(invoker.deps)) {
  180. deps += invoker.deps
  181. }
  182. } # action(action_name)
  183. # The source_set that builds the generated .pb.cc files.
  184. if (generate_descriptor == "") {
  185. source_set(source_set_name) {
  186. forward_variables_from(invoker,
  187. [
  188. "defines",
  189. "include_dirs",
  190. "public_configs",
  191. "testonly",
  192. "visibility",
  193. ])
  194. sources = get_target_outputs(":$action_name")
  195. if (defined(invoker.extra_configs)) {
  196. configs += invoker.extra_configs
  197. }
  198. if (!defined(invoker.public_configs)) {
  199. public_configs = []
  200. }
  201. public_configs += [
  202. "//:protobuf_gen_config",
  203. ":$config_name",
  204. ]
  205. # By default, propagate the config for |include_dirs| to dependent
  206. # targets, so that public imports can be resolved to corresponding header
  207. # files. In some cases, the embedder target handles include directory
  208. # propagation itself, e.g. via a common config.
  209. propagate_imports_configs = !defined(invoker.propagate_imports_configs) ||
  210. invoker.propagate_imports_configs
  211. if (propagate_imports_configs) {
  212. public_configs += [ ":$config_name" ]
  213. } else {
  214. configs += [ ":$config_name" ]
  215. }
  216. # Use protobuf_full only for tests.
  217. if (defined(invoker.use_protobuf_full) &&
  218. invoker.use_protobuf_full == true) {
  219. deps = [ "//:protobuf_full" ]
  220. } else if (generate_cc) {
  221. deps = [ "//:protobuf_lite" ]
  222. } else {
  223. deps = []
  224. }
  225. deps += [ ":$action_name" ]
  226. if (defined(invoker.deps)) {
  227. deps += invoker.deps
  228. }
  229. } # source_set(source_set_name)
  230. }
  231. } # template