1#
2#  Copyright 2021 Google, Inc.
3#
4#  Licensed under the Apache License, Version 2.0 (the "License");
5#  you may not use this file except in compliance with the License.
6#  You may obtain a copy of the License at:
7#
8#  http://www.apache.org/licenses/LICENSE-2.0
9#
10#  Unless required by applicable law or agreed to in writing, software
11#  distributed under the License is distributed on an "AS IS" BASIS,
12#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13#  See the License for the specific language governing permissions and
14#  limitations under the License.
15#
16
17# Generate pybind11 source files + headers
18#
19# Parameters:
20#   include: Base include path (i.e. bt/gd)
21#   source_root: Root of source relative to current BUILD.gn
22#   sources: PDL files to use for generation.
23#   shards [optional]: Shard generated source into N files.
24#                      Default = 0. Max = 10.
25template("packetgen_py") {
26  action_name = "${target_name}_gen"
27
28  all_dependent_config_name = "_${target_name}_all_dependent_config"
29  config(all_dependent_config_name) {
30    include_dirs = [ "${root_gen_dir}" ]
31  }
32
33  action(action_name) {
34    forward_variables_from(invoker, [ "sources", "include", "shards", "source_root" ])
35    assert(defined(sources), "sources must be set")
36    assert(defined(include), "include must be set")
37    assert(defined(source_root), "source root must be set")
38
39    outdir = rebase_path(root_gen_dir)
40    source_root = rebase_path(source_root)
41
42    # Set shards cmd
43    shards_cmd = ""
44    outputs = []
45    source_args = []
46    if (defined(shards)) {
47      shards_list = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
48      foreach (source, sources) {
49        rel_source = rebase_path(source, ".")
50        source_args += [ rebase_path(source, source_root) ]
51        shards_cmd = "--num_shards=${shards}"
52
53        # TODO - GN reference doesn't explain how to programatically create
54        # a range (i.e. range(shards)) so we use a fixed list and foreach loop to
55        # work around it.
56        assert(shards <= 10, "Maximum supported shards is 10.")
57        index = 0
58        outputs += [ string_replace("${outdir}/${rel_source}_python3.cc", ".pdl", "") ]
59        foreach(num, shards_list) {
60          if (index < shards) {
61              outputs += [ string_replace("${outdir}/${rel_source}_python3_shard_${num}.cc", ".pdl", "") ]
62          }
63
64          index = index + 1
65        }
66      }
67    }
68
69    script = "//common-mk/file_generator_wrapper.py"
70    binfile = "${root_out_dir}/bluetooth_packetgen"
71    args = [
72      binfile,
73      "--include=${include}",
74      "--out=${outdir}",
75      "--source_root=${source_root}",
76      shards_cmd,
77    ] + source_args
78  }
79
80  # TODO: Make building with python-dev work.
81  # source_set(target_name) {
82  #   sources = get_target_outputs(":${action_name}")
83  #   deps = [":${action_name}"]
84  #   all_dependent_configs = [":${all_dependent_config_name}"]
85  #   if (defined(invoker.all_dependent_configs)) {
86  #     all_dependent_configs += invoker.all_dependent_configs
87  #   }
88  #   if (defined(invoker.configs)) {
89  #     configs += invoker.configs
90  #   }
91  # }
92}
93
94# Generate single c++ headers for each pdl
95#
96# Parameters:
97#   include: Base include path (i.e. bt/gd)
98#   source_root: Root of source relative to current BUILD.gn
99#   sources: PDL files to use for generation.
100template("packetgen_headers") {
101  all_dependent_config_name = "_${target_name}_all_dependent_config"
102  config(all_dependent_config_name) {
103    include_dirs = [ "${root_gen_dir}" ]
104  }
105
106  action(target_name) {
107    forward_variables_from(invoker, [ "include", "sources", "source_root" ])
108    assert(defined(sources), "sources must be set")
109    assert(defined(include), "include must be set")
110    assert(defined(source_root), "source root must be set")
111
112    outdir = rebase_path(root_gen_dir)
113    source_root = rebase_path(source_root)
114
115    script = "//common-mk/file_generator_wrapper.py"
116    binfile = "${root_out_dir}/bluetooth_packetgen"
117    args = [
118      binfile,
119      "--include=${include}",
120      "--out=${outdir}",
121      "--source_root=${source_root}",
122    ]
123
124    outputs = []
125    foreach (source, sources) {
126      rel_source = rebase_path(source, ".")
127      args += [ rebase_path(source, source_root) ]
128      outputs += [ string_replace("${outdir}/${rel_source}.h", ".pdl", "") ]
129    }
130
131    all_dependent_configs = [ ":${all_dependent_config_name}" ]
132    if (defined(invoker.all_dependent_configs)) {
133      all_dependent_configs += invoker.all_dependent_configs
134    }
135
136    if (defined(invoker.configs)) {
137      configs += invoker.configs
138    }
139  }
140}
141
142# Generate single Rust files for each pdl
143#
144# Parameters:
145#   include: Base include path (i.e. bt/gd)
146#   source_root: Root of source relative to current BUILD.gn
147#   sources: PDL files to use for generation.
148template("packetgen_rust") {
149  action_name = "${target_name}_gen"
150  all_dependent_config_name = "_${target_name}_all_dependent_config"
151  config(all_dependent_config_name) {
152    include_dirs = [ "${root_gen_dir}" ]
153  }
154
155  action(action_name) {
156    forward_variables_from(invoker, [ "include", "sources", "source_root" ])
157    assert(defined(sources), "sources must be set")
158    assert(defined(include), "include must be set")
159    assert(defined(source_root), "source root must be set")
160
161    outdir = rebase_path(root_gen_dir)
162    source_root = rebase_path(source_root)
163
164    script = "//common-mk/file_generator_wrapper.py"
165    binfile = "${root_out_dir}/bluetooth_packetgen"
166    args = [
167      binfile,
168      "--include=${include}",
169      "--out=${outdir}",
170      "--source_root=${source_root}",
171      "--rust",
172    ]
173
174    outputs = []
175    foreach (source, sources) {
176      rel_source = rebase_path(source, ".")
177      args += [ rebase_path(source, source_root) ]
178      outputs += [ string_replace("${outdir}/${rel_source}.rs", ".pdl", "") ]
179    }
180  }
181
182  # TODO: Rust source_set is not supported by gn.
183  # source_set(target_name) {
184  #   sources = get_target_outputs(":${action_name}")
185  #   deps = [ ":${action_name}" ]
186  #   all_dependent_configs = [":${all_dependent_config_name}"]
187  #   if (defined(invoker.all_dependent_configs)) {
188  #     all_dependent_configs += invoker.all_dependent_configs
189  #   }
190  #   if (defined(invoker.configs)) {
191  #     configs += invoker.configs
192  #   }
193  # }
194}
195