blob: 9871c0dff39d74f7c8b1ab4ef938145f0c6dda28 [file] [log] [blame]
James Kuszmaul8e62b022022-03-22 09:33:25 -07001#!/usr/bin/env python3
2#
3# Copyright 2021 Google Inc. All rights reserved.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import argparse
18import filecmp
19import glob
20import platform
21import shutil
22import subprocess
23import sys
24from pathlib import Path
25
26parser = argparse.ArgumentParser()
27parser.add_argument(
28 "--flatc",
29 help="path of the Flat C compiler relative to the root directory",
30)
31parser.add_argument("--cpp-0x", action="store_true", help="use --cpp-std c++ox")
32parser.add_argument(
33 "--skip-monster-extra",
34 action="store_true",
35 help="skip generating tests involving monster_extra.fbs",
36)
37parser.add_argument(
38 "--skip-gen-reflection",
39 action="store_true",
40 help="skip generating the reflection.fbs files",
41)
42args = parser.parse_args()
43
44# Get the path where this script is located so we can invoke the script from
45# any directory and have the paths work correctly.
46script_path = Path(__file__).parent.resolve()
47
48# Get the root path as an absolute path, so all derived paths are absolute.
49root_path = script_path.parent.absolute()
50
51# Get the location of the flatc executable, reading from the first command line
52# argument or defaulting to default names.
53flatc_exe = Path(
54 ("flatc" if not platform.system() == "Windows" else "flatc.exe")
55 if not args.flatc
56 else args.flatc
57)
58
59# Find and assert flatc compiler is present.
60if root_path in flatc_exe.parents:
61 flatc_exe = flatc_exe.relative_to(root_path)
62flatc_path = Path(root_path, flatc_exe)
63assert flatc_path.exists(), "Cannot find the flatc compiler " + str(flatc_path)
64
65# Specify the other paths that will be referenced
66tests_path = Path(root_path, "tests")
67samples_path = Path(root_path, "samples")
68reflection_path = Path(root_path, "reflection")
69
70# Execute the flatc compiler with the specified parameters
71def flatc(
72 options, schema, prefix=None, include=None, data=None, cwd=tests_path
73):
74 cmd = [str(flatc_path)] + options
75 if prefix:
76 cmd += ["-o"] + [prefix]
77 if include:
78 cmd += ["-I"] + [include]
79 cmd += [schema] if isinstance(schema, str) else schema
80 if data:
81 cmd += [data] if isinstance(data, str) else data
82 result = subprocess.run(cmd, cwd=str(cwd), check=True)
83
84
85# Generate the code for flatbuffers reflection schema
86def flatc_reflection(options, location, target):
87 full_options = ["--no-prefix"] + options
88 temp_dir = ".tmp"
89 flatc(
90 full_options,
91 prefix=temp_dir,
92 schema="reflection.fbs",
93 cwd=reflection_path,
94 )
95 new_reflection_path = Path(reflection_path, temp_dir, target)
96 original_reflection_path = Path(root_path, location, target)
97 if not filecmp.cmp(str(new_reflection_path), str(original_reflection_path)):
98 shutil.rmtree(str(original_reflection_path))
99 shutil.move(str(new_reflection_path), str(original_reflection_path))
100 shutil.rmtree(str(Path(reflection_path, temp_dir)))
101
102
103# Glob a pattern relative to file path
104def glob(path, pattern):
105 return [str(p) for p in path.glob(pattern)]
106
107
108# flatc options that are shared
109BASE_OPTS = ["--reflect-names", "--gen-mutable", "--gen-object-api"]
110NO_INCL_OPTS = BASE_OPTS + ["--no-includes"]
111
112# Language specific options
113CS_OPTS = ["--csharp", "--cs-gen-json-serializer"]
114CPP_OPTS = [
115 "--cpp",
116 "--gen-compare",
117 "--cpp-ptr-type",
118 "flatbuffers::unique_ptr",
119] + (["--cpp-std", "c++0x"] if args.cpp_0x else [])
120
121CPP_17_OPTS = NO_INCL_OPTS + [
122 "--cpp",
123 "--cpp-std",
124 "c++17",
125 "--cpp-static-reflection",
126 "--gen-object-api",
127]
128RUST_OPTS = BASE_OPTS + ["--rust", "--gen-all", "--gen-name-strings", "--rust-module-root-file"]
129RUST_SERIALIZE_OPTS = BASE_OPTS + [
130 "--rust",
131 "--gen-all",
132 "--gen-name-strings",
133 "--rust-serialize",
134 "--rust-module-root-file",
135]
136TS_OPTS = ["--ts", "--gen-name-strings"]
137LOBSTER_OPTS = ["--lobster"]
138SWIFT_OPTS = ["--swift", "--gen-json-emit", "--bfbs-filenames", str(tests_path)]
139JAVA_OPTS = ["--java"]
140KOTLIN_OPTS = ["--kotlin"]
141PHP_OPTS = ["--php"]
142DART_OPTS = ["--dart"]
143PYTHON_OPTS = ["--python"]
144BINARY_OPTS = ["-b", "--schema", "--bfbs-comments", "--bfbs-builtins"]
145
146# Basic Usage
147
148flatc(
149 NO_INCL_OPTS
150 + CPP_OPTS
151 + CS_OPTS
152 + TS_OPTS
153 + [
154 "--binary",
155 "--java",
156 "--kotlin",
157 "--dart",
158 "--go",
159 "--lobster",
160 "--php",
161 ],
162 schema="monster_test.fbs",
163 include="include_test",
164 data="monsterdata_test.json",
165)
166
167flatc(
168 ["--lua", "--bfbs-filenames", str(tests_path)],
169 schema="monster_test.fbs",
170 include="include_test",
171)
172
173flatc(
174 NO_INCL_OPTS + CPP_OPTS + ["--grpc"],
175 schema="monster_test.fbs",
176 include="include_test",
177 data="monsterdata_test.json",
178)
179
180flatc(
181 RUST_OPTS,
182 schema="monster_test.fbs",
183 include="include_test",
184 prefix="monster_test",
185 data="monsterdata_test.json",
186)
187
188flatc(
189 RUST_SERIALIZE_OPTS,
190 schema="monster_test.fbs",
191 include="include_test",
192 prefix="monster_test_serialize",
193 data="monsterdata_test.json",
194)
195
196flatc(
197 options=BASE_OPTS + ["--python"],
198 schema="monster_test.fbs",
199 include="include_test",
200 data="monsterdata_test.json",
201)
202
203flatc(
204 options=BASE_OPTS + ["--python", "--gen-onefile"],
205 schema="monster_test.fbs",
206 include="include_test",
207 data="monsterdata_test.json",
208)
209
210# For Rust we currently generate two independent schemas, with namespace_test2
211# duplicating the types in namespace_test1
212flatc(
213 RUST_OPTS,
214 prefix="namespace_test",
215 schema=[
216 "namespace_test/namespace_test1.fbs",
217 "namespace_test/namespace_test2.fbs",
218 ],
219)
220
221flatc(
222 BASE_OPTS
223 + CPP_OPTS
224 + CS_OPTS
225 + TS_OPTS
226 + JAVA_OPTS
227 + KOTLIN_OPTS
228 + PHP_OPTS,
229 prefix="union_vector",
230 schema="union_vector/union_vector.fbs",
231)
232
233flatc(
234 BASE_OPTS + TS_OPTS + ["--gen-name-strings", "--gen-mutable"],
235 include="include_test",
236 schema="monster_test.fbs",
237)
238
239flatc(
240 BASE_OPTS + TS_OPTS + ["-b"],
241 include="include_test",
242 schema="monster_test.fbs",
243 data="unicode_test.json",
244)
245
246flatc(
247 BASE_OPTS + TS_OPTS + ["--gen-name-strings"],
248 prefix="union_vector",
249 schema="union_vector/union_vector.fbs",
250)
251
252flatc(
253 RUST_OPTS,
254 prefix="include_test1",
255 include="include_test",
256 schema="include_test/include_test1.fbs",
257)
258
259flatc(
260 RUST_OPTS,
261 prefix="include_test2",
262 include="include_test",
263 schema="include_test/sub/include_test2.fbs",
264)
265
266flatc(
267 BINARY_OPTS + ["--bfbs-filenames", str(tests_path)],
268 include="include_test",
269 schema="monster_test.fbs",
270)
271
272flatc(
273 CPP_OPTS
274 + NO_INCL_OPTS
275 + [
276 "--bfbs-comments",
277 "--bfbs-builtins",
278 "--bfbs-gen-embed",
279 "--bfbs-filenames",
280 str(tests_path),
281 ],
282 include="include_test",
283 schema="monster_test.fbs",
284)
285
286flatc(
287 BINARY_OPTS + ["--bfbs-filenames", str(tests_path)],
288 include="include_test",
289 schema="arrays_test.fbs",
290)
291
292flatc(
293 ["--jsonschema", "--schema"],
294 include="include_test",
295 schema="monster_test.fbs",
296)
297
298if not args.skip_monster_extra:
299 flatc(
300 CPP_OPTS
301 + CS_OPTS
302 + NO_INCL_OPTS
303 + JAVA_OPTS
304 + KOTLIN_OPTS
305 + PYTHON_OPTS,
306 schema="monster_extra.fbs",
307 data="monsterdata_extra.json",
308 )
309
310 flatc(
311 DART_OPTS + ["--gen-object-api"],
312 schema="monster_extra.fbs",
313 )
314
315flatc(
316 CPP_OPTS
317 + CS_OPTS
318 + NO_INCL_OPTS
319 + JAVA_OPTS
320 + ["--jsonschema", "--scoped-enums"],
321 schema="arrays_test.fbs",
322)
323
324flatc(
325 RUST_OPTS,
326 prefix="arrays_test",
327 schema="arrays_test.fbs",
328)
329
330flatc(
331 BASE_OPTS + PYTHON_OPTS,
332 schema="arrays_test.fbs",
333)
334
335
336# Optional Scalars
337optional_scalars_schema = "optional_scalars.fbs"
338flatc(
339 ["--java", "--kotlin", "--lobster", "--ts"], schema=optional_scalars_schema
340)
341
342flatc(["--csharp", "--gen-object-api"], schema=optional_scalars_schema)
343
344flatc(RUST_OPTS, prefix="optional_scalars", schema=optional_scalars_schema)
345
346flatc(NO_INCL_OPTS + CPP_OPTS, schema=optional_scalars_schema)
347
348# Generate string/vector default code for tests
349flatc(RUST_OPTS, prefix="more_defaults", schema="more_defaults.fbs")
350
351# Generate the schema evolution tests
352flatc(
353 CPP_OPTS + ["--scoped-enums"],
354 prefix="evolution_test",
355 schema=glob(tests_path, "evolution_test/evolution_v*.fbs"),
356)
357
358# Generate the keywords tests
359flatc(BASE_OPTS + CS_OPTS, schema="keyword_test.fbs")
360flatc(RUST_OPTS, prefix="keyword_test", schema="keyword_test.fbs")
361flatc(
362 BASE_OPTS + CS_OPTS + ["--cs-global-alias", "--gen-onefile"],
363 prefix="nested_namespace_test",
364 schema=glob(tests_path, "nested_namespace_test/nested_namespace_test*.fbs"),
365)
366
367# Swift Tests
368swift_prefix = "FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests"
369flatc(
370 SWIFT_OPTS + NO_INCL_OPTS + ["--grpc"],
371 schema="monster_test.fbs",
372 include="include_test",
373 prefix=swift_prefix,
374)
375flatc(
376 SWIFT_OPTS + BASE_OPTS,
377 schema="union_vector/union_vector.fbs",
378 prefix=swift_prefix,
379)
380flatc(SWIFT_OPTS, schema="optional_scalars.fbs", prefix=swift_prefix)
381flatc(
382 SWIFT_OPTS + ["--gen-object-api"],
383 schema="more_defaults.fbs",
384 prefix=swift_prefix,
385)
386flatc(
387 SWIFT_OPTS + BASE_OPTS,
388 schema="MutatingBool.fbs",
389 prefix=swift_prefix,
390)
391
392# --filename-suffix and --filename-ext tests
393flatc(
394 CPP_OPTS
395 + NO_INCL_OPTS
396 + ["--filename-suffix", "_suffix", "--filename-ext", "hpp"],
397 include="include_test",
398 schema="monster_test.fbs",
399)
400orig_monster_file = Path(tests_path, "monster_test_generated.h")
401new_monster_file = Path(tests_path, "monster_test_suffix.hpp")
402assert (
403 new_monster_file.exists()
404), "filename suffix option did not produce a file"
405assert filecmp.cmp(
406 str(orig_monster_file), str(new_monster_file)
407), "filename suffix option did not produce identical results"
408new_monster_file.unlink()
409
410# Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher.
411cpp_17_prefix = "cpp17/generated_cpp17"
412flatc(
413 CPP_17_OPTS,
414 schema="monster_test.fbs",
415 include="include_test",
416 prefix=cpp_17_prefix,
417)
418flatc(
419 CPP_17_OPTS,
420 schema="optional_scalars.fbs",
421 prefix=cpp_17_prefix,
422)
423flatc(
424 CPP_17_OPTS,
425 schema="union_vector/union_vector.fbs",
426 prefix=cpp_17_prefix,
427)
428
429# Sample files
430samples_schema = "monster.fbs"
431flatc(
432 BASE_OPTS + CPP_OPTS + LOBSTER_OPTS, schema=samples_schema, cwd=samples_path
433)
434flatc(
435 RUST_OPTS, prefix="rust_generated", schema=samples_schema, cwd=samples_path
436)
437flatc(
438 BINARY_OPTS + ["--bfbs-filenames", str(samples_path)],
439 schema=samples_schema,
440 cwd=samples_path,
441)
442
443# Reflection
444
445# Skip generating the reflection if told too, as we run this script after
446# building flatc which uses the reflection_generated.h itself.
447if not args.skip_gen_reflection:
448 # C++ Reflection
449 flatc_reflection(["-c", "--cpp-std", "c++0x"], "include/flatbuffers",
450 "reflection_generated.h")
451
452# Python Reflection
453flatc_reflection(["-p"], "python/flatbuffers", "reflection")