1# Copyright 2014 The Chromium 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
5# Defines a static library corresponding to the output of schema compiler tools
6# over a set of extensions API schemas (IDL or JSON format.) The library target
7# has implicit hard dependencies on all schema files listed by the invoker and
8# is itself a hard dependency.
9#
10# Invocations of this template may use the following variables:
11#
12# sources [required] A list of schema files to be compiled.
13#
14# root_namespace [required]
15#     A Python string substituion pattern used to generate the C++
16#     namespace for each API. Use %(namespace)s to replace with the API
17#     namespace, like "toplevel::%(namespace)s_api".
18#
19# schema_include_rules [optional]
20#     A list of paths to include when searching for referenced objects,
21#     with the namespace separated by a :.
22#     Example:
23#       [ '/foo/bar:Foo::Bar::%(namespace)s' ]
24#
25# schemas [optional, default = false]
26#   Boolean indicating if the schema files should be generated.
27#
28# bundle [optional, default = false]
29#   Boolean indicating if the schema bundle files should be generated.
30#
31# bundle_registration [optional, default = false]
32#   Boolean indicating if the API registration bundle files should be generated.
33#
34# impl_dir [required if bundle_registration = true, otherwise unused]
35#   The path containing C++ implementations of API functions. This path is
36#   used as the root path when looking for {schema}/{schema}_api.h headers
37#   when generating API registration bundles. Such headers, if found, are
38#   automatically included by the generated code.
39#
40# uncompiled_sources [optional, only used when bundle = true or
41#     bundle_registration = true]
42#   A list of schema files which should not be compiled, but which should still
43#   be processed for API bundle generation.
44#
45# deps [optional]
46#   If any deps are specified they will be inherited by the static library
47#   target.
48#
49# The static library target also inherits the visibility and output_name
50# of its invoker.
51
52template("generated_extensions_api") {
53  assert(defined(invoker.sources),
54         "\"sources\" must be defined for the $target_name template.")
55  assert(defined(invoker.root_namespace),
56         "\"root_namespace\" must be defined for the $target_name template.")
57
58  schemas = defined(invoker.schemas) && invoker.schemas
59  bundle = defined(invoker.bundle) && invoker.bundle
60  bundle_registration = defined(invoker.bundle_registration) &&
61      invoker.bundle_registration
62
63  schema_include_rules = ""
64  if (defined(invoker.schema_include_rules)) {
65    schema_include_rules = invoker.schema_include_rules
66  }
67
68  # Keep a copy of the target_name here since it will be trampled
69  # in nested targets.
70  target_visibility = [ ":$target_name" ]
71
72  generated_config_name = target_name + "_generated_config"
73  config(generated_config_name) {
74    include_dirs = [ target_gen_dir ]
75    visibility = target_visibility
76  }
77
78  sources = invoker.sources
79  root_namespace = invoker.root_namespace
80
81  compiler_root = "//tools/json_schema_compiler"
82  compiler_script = "$compiler_root/compiler.py"
83  compiler_sources = [
84    "$compiler_root/cc_generator.py",
85    "$compiler_root/code.py",
86    "$compiler_root/compiler.py",
87    "$compiler_root/cpp_generator.py",
88    "$compiler_root/cpp_type_generator.py",
89    "$compiler_root/cpp_util.py",
90    "$compiler_root/h_generator.py",
91    "$compiler_root/idl_schema.py",
92    "$compiler_root/model.py",
93    "$compiler_root/util_cc_helper.py",
94  ]
95
96  if (schemas) {
97    schema_generator_name = target_name + "_schema_generator"
98    action_foreach(schema_generator_name) {
99      script = compiler_script
100      inputs = compiler_sources
101      outputs = [
102        "$target_gen_dir/{{source_name_part}}.cc",
103        "$target_gen_dir/{{source_name_part}}.h",
104      ]
105      args = [
106        "{{source}}",
107        "--root=" + rebase_path("//", root_build_dir),
108        "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
109        "--namespace=$root_namespace",
110        "--generator=cpp",
111        "--include-rules=$schema_include_rules" ]
112
113      if (defined(invoker.visibility)) {
114        # If visibility is restricted, add our own target to it.
115        visibility = [ invoker.visibility, target_visibility ]
116      }
117    }
118  }
119
120  if (bundle) {
121    uncompiled_sources = []
122    if (defined(invoker.uncompiled_sources)) {
123     uncompiled_sources = invoker.uncompiled_sources
124    }
125
126    bundle_generator_schema_name = target_name + "_bundle_generator_schema"
127    action(bundle_generator_schema_name) {
128      script = compiler_script
129      inputs = compiler_sources + sources + uncompiled_sources
130      outputs = [
131        "$target_gen_dir/generated_schemas.cc",
132        "$target_gen_dir/generated_schemas.h",
133      ]
134      args = [
135        "--root=" + rebase_path("//", root_build_dir),
136        "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
137        "--namespace=$root_namespace",
138        "--generator=cpp-bundle-schema",
139        "--include-rules=$schema_include_rules" ]
140        + rebase_path(sources, root_build_dir)
141        + rebase_path(uncompiled_sources, root_build_dir)
142    }
143  }
144
145  if (bundle_registration) {
146    uncompiled_sources = []
147    if (defined(invoker.uncompiled_sources)) {
148     uncompiled_sources = invoker.uncompiled_sources
149    }
150
151    assert(defined(invoker.impl_dir),
152           "\"impl_dir\" must be defined for the $target_name template.")
153    impl_dir = invoker.impl_dir
154
155    bundle_generator_registration_name = target_name +
156        "_bundle_generator_registration"
157    action(bundle_generator_registration_name) {
158      script = compiler_script
159      inputs = compiler_sources + sources + uncompiled_sources
160      outputs = [
161        "$root_gen_dir/$impl_dir/generated_api_registration.cc",
162        "$root_gen_dir/$impl_dir/generated_api_registration.h",
163      ]
164      args = [
165        "--root=" + rebase_path("//", root_build_dir),
166        "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
167        "--namespace=$root_namespace",
168        "--generator=cpp-bundle-registration",
169        "--impl-dir=" + rebase_path(impl_dir, "//"),
170        "--include-rules=$schema_include_rules" ]
171        + rebase_path(sources, root_build_dir)
172        + rebase_path(uncompiled_sources, root_build_dir)
173    }
174  }
175
176  source_set(target_name) {
177    sources = []
178    deps = []
179    public_deps = []
180
181    if (schemas) {
182      sources += get_target_outputs(":$schema_generator_name")
183      public_deps += [ ":$schema_generator_name" ]
184      deps += [ "//tools/json_schema_compiler:generated_api_util" ]
185    }
186
187    if (bundle) {
188      sources += get_target_outputs(":$bundle_generator_schema_name")
189      deps += [ ":$bundle_generator_schema_name" ]
190    }
191
192    if (bundle_registration) {
193      sources += get_target_outputs(":$bundle_generator_registration_name")
194      deps += [ ":$bundle_generator_registration_name" ]
195    }
196
197    if (defined(invoker.deps)) {
198      deps += invoker.deps
199    }
200    public_configs = [ ":$generated_config_name" ]
201
202    if (defined(invoker.visibility)) {
203      visibility = invoker.visibility
204    }
205    if (defined(invoker.output_name)) {
206      output_name = invoker.output_name
207    }
208  }
209}
210