Home | History | Annotate | Download | only in build
      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 # bundle_name [required if bundle or bundle_registrations]:
     35 #     A string to prepend to generated bundle class names, so that multiple
     36 #     bundle rules can be used without conflicting.  Only used with one of
     37 #     the cpp-bundle generators.
     38 #
     39 # impl_dir [required if bundle_registration = true, otherwise unused]
     40 #   The path containing C++ implementations of API functions. This path is
     41 #   used as the root path when looking for {schema}/{schema}_api.h headers
     42 #   when generating API registration bundles. Such headers, if found, are
     43 #   automatically included by the generated code.
     44 #
     45 # uncompiled_sources [optional, only used when bundle = true or
     46 #     bundle_registration = true]
     47 #   A list of schema files which should not be compiled, but which should still
     48 #   be processed for API bundle generation.
     49 #
     50 # configs [optional]
     51 #   Extra configs to apply to the compile step.
     52 #
     53 # deps [optional]
     54 #   If any deps are specified they will be inherited by the static library
     55 #   target.
     56 #
     57 # generate_static_library [optional, defaults to false]
     58 #   Produces a static library instead of a source_set.
     59 #
     60 # The generated library target also inherits the visibility and output_name
     61 # of its invoker.
     62 
     63 template("json_schema_api") {
     64   assert(defined(invoker.sources),
     65          "\"sources\" must be defined for the $target_name template.")
     66   assert(defined(invoker.root_namespace),
     67          "\"root_namespace\" must be defined for the $target_name template.")
     68 
     69   schemas = defined(invoker.schemas) && invoker.schemas
     70   bundle = defined(invoker.bundle) && invoker.bundle
     71   bundle_registration =
     72       defined(invoker.bundle_registration) && invoker.bundle_registration
     73 
     74   schema_include_rules = ""
     75   if (defined(invoker.schema_include_rules)) {
     76     schema_include_rules = invoker.schema_include_rules
     77   }
     78 
     79   # Keep a copy of the target_name here since it will be trampled
     80   # in nested targets.
     81   target_visibility = [ ":$target_name" ]
     82 
     83   generated_config_name = target_name + "_generated_config"
     84   config(generated_config_name) {
     85     include_dirs = [ root_gen_dir ]
     86     visibility = target_visibility
     87   }
     88 
     89   root_namespace = invoker.root_namespace
     90 
     91   compiler_root = "//tools/json_schema_compiler"
     92   compiler_script = "$compiler_root/compiler.py"
     93   compiler_sources = [
     94     "$compiler_root/cc_generator.py",
     95     "$compiler_root/code.py",
     96     "$compiler_root/compiler.py",
     97     "$compiler_root/cpp_bundle_generator.py",
     98     "$compiler_root/cpp_generator.py",
     99     "$compiler_root/cpp_type_generator.py",
    100     "$compiler_root/cpp_util.py",
    101     "$compiler_root/h_generator.py",
    102     "$compiler_root/idl_schema.py",
    103     "$compiler_root/model.py",
    104     "$compiler_root/util_cc_helper.py",
    105   ]
    106 
    107   if (schemas) {
    108     schema_generator_name = target_name + "_schema_generator"
    109     action_foreach(schema_generator_name) {
    110       script = compiler_script
    111       sources = invoker.sources
    112       inputs = compiler_sources
    113       outputs = [
    114         "$target_gen_dir/{{source_name_part}}.cc",
    115         "$target_gen_dir/{{source_name_part}}.h",
    116       ]
    117       args = [
    118         "{{source}}",
    119         "--root=" + rebase_path("//", root_build_dir),
    120         "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
    121         "--namespace=$root_namespace",
    122         "--generator=cpp",
    123         "--include-rules=$schema_include_rules",
    124       ]
    125 
    126       if (defined(invoker.visibility)) {
    127         # If visibility is restricted, add our own target to it.
    128         visibility = invoker.visibility + target_visibility
    129       }
    130     }
    131   }
    132 
    133   if (bundle) {
    134     assert(defined(invoker.bundle_name),
    135            "\"bundle_name\" must be defined for bundles")
    136 
    137     uncompiled_sources = []
    138     if (defined(invoker.uncompiled_sources)) {
    139       uncompiled_sources = invoker.uncompiled_sources
    140     }
    141 
    142     bundle_generator_schema_name = target_name + "_bundle_generator_schema"
    143     action(bundle_generator_schema_name) {
    144       script = compiler_script
    145       inputs = compiler_sources + invoker.sources + uncompiled_sources
    146       outputs = [
    147         "$target_gen_dir/generated_schemas.cc",
    148         "$target_gen_dir/generated_schemas.h",
    149       ]
    150       args = [
    151                "--root=" + rebase_path("//", root_build_dir),
    152                "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
    153                "--namespace=$root_namespace",
    154                "--bundle-name=" + invoker.bundle_name,
    155                "--generator=cpp-bundle-schema",
    156                "--include-rules=$schema_include_rules",
    157              ] + rebase_path(invoker.sources, root_build_dir) +
    158              rebase_path(uncompiled_sources, root_build_dir)
    159     }
    160   }
    161 
    162   if (bundle_registration) {
    163     assert(defined(invoker.bundle_name),
    164            "\"bundle_name\" must be defined for bundle registrations")
    165 
    166     uncompiled_sources = []
    167     if (defined(invoker.uncompiled_sources)) {
    168       uncompiled_sources = invoker.uncompiled_sources
    169     }
    170 
    171     assert(defined(invoker.impl_dir),
    172            "\"impl_dir\" must be defined for the $target_name template.")
    173 
    174     # Child directory inside the generated file tree.
    175     gen_child_dir = rebase_path(invoker.impl_dir, "//")
    176 
    177     bundle_generator_registration_name =
    178         target_name + "_bundle_generator_registration"
    179     action(bundle_generator_registration_name) {
    180       script = compiler_script
    181       inputs = compiler_sources + invoker.sources + uncompiled_sources
    182       outputs = [
    183         "$root_gen_dir/$gen_child_dir/generated_api_registration.cc",
    184         "$root_gen_dir/$gen_child_dir/generated_api_registration.h",
    185       ]
    186       args = [
    187                "--root=" + rebase_path("//", root_build_dir),
    188                "--destdir=" + rebase_path(root_gen_dir, root_build_dir),
    189                "--namespace=$root_namespace",
    190                "--bundle-name=" + invoker.bundle_name,
    191                "--generator=cpp-bundle-registration",
    192                "--impl-dir=$gen_child_dir",
    193                "--include-rules=$schema_include_rules",
    194              ] + rebase_path(invoker.sources, root_build_dir) +
    195              rebase_path(uncompiled_sources, root_build_dir)
    196     }
    197   }
    198 
    199   # Compute the contents of the library/source set.
    200   lib_sources = invoker.sources
    201   lib_deps = []
    202   lib_public_deps = []
    203   lib_extra_configs = []
    204   if (defined(invoker.configs)) {
    205     lib_extra_configs += invoker.configs
    206   }
    207 
    208   if (schemas) {
    209     lib_sources += get_target_outputs(":$schema_generator_name")
    210     lib_public_deps += [ ":$schema_generator_name" ]
    211     lib_deps += [ "//tools/json_schema_compiler:generated_api_util" ]
    212     lib_extra_configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
    213   }
    214 
    215   if (bundle) {
    216     lib_sources += get_target_outputs(":$bundle_generator_schema_name")
    217     lib_deps += [ ":$bundle_generator_schema_name" ]
    218   }
    219 
    220   if (bundle_registration) {
    221     lib_sources += get_target_outputs(":$bundle_generator_registration_name")
    222     lib_deps += [ ":$bundle_generator_registration_name" ]
    223   }
    224 
    225   if (defined(invoker.deps)) {
    226     lib_deps += invoker.deps
    227   }
    228 
    229   # Generate either a static library or a source set.
    230   if (defined(invoker.generate_static_library) &&
    231       invoker.generate_static_library) {
    232     static_library(target_name) {
    233       sources = lib_sources
    234       deps = lib_deps
    235       public_deps = lib_public_deps
    236       configs += lib_extra_configs
    237       public_configs = [ ":$generated_config_name" ]
    238 
    239       if (defined(invoker.visibility)) {
    240         visibility = invoker.visibility
    241       }
    242       if (defined(invoker.output_name)) {
    243         output_name = invoker.output_name
    244       }
    245     }
    246   } else {
    247     source_set(target_name) {
    248       sources = lib_sources
    249       deps = lib_deps
    250       public_deps = lib_public_deps
    251       configs += lib_extra_configs
    252       public_configs = [ ":$generated_config_name" ]
    253 
    254       if (defined(invoker.visibility)) {
    255         visibility = invoker.visibility
    256       }
    257       if (defined(invoker.output_name)) {
    258         output_name = invoker.output_name
    259       }
    260     }
    261   }
    262 }
    263