Skip to content

Commit 6d192cd

Browse files
committed
Swift: make C++ code generation language agnostic
1 parent feb4e60 commit 6d192cd

File tree

12 files changed

+77
-55
lines changed

12 files changed

+77
-55
lines changed

swift/BUILD.bazel

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,13 @@ load("//misc/bazel:pkg_runfiles.bzl", "pkg_runfiles")
55

66
filegroup(
77
name = "schema",
8-
srcs = ["schema.py"] + glob(["*.dbscheme"]),
8+
srcs = ["schema.py"],
9+
visibility = ["//swift:__subpackages__"],
10+
)
11+
12+
filegroup(
13+
name = "schema_includes",
14+
srcs = glob(["*.dbscheme"]),
915
visibility = ["//swift:__subpackages__"],
1016
)
1117

swift/codegen/codegen.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,19 @@ def _parse_args() -> argparse.Namespace:
6060
p.add_argument("--generated-registry",
6161
help="registry file containing information about checked-in generated code"),
6262
]
63+
p.add_argument("--script-name",
64+
help="script name to put in header comments of generated files. By default, the path of this "
65+
"script relative to the root directory")
66+
p.add_argument("--trap-library",
67+
help="path to the trap library from an include directory, required if generating C++ trap bindings"),
6368
p.add_argument("--ql-format", action="store_true", default=True,
6469
help="use codeql to autoformat QL files (which is the default)")
6570
p.add_argument("--no-ql-format", action="store_false", dest="ql_format", help="do not format QL files")
6671
p.add_argument("--codeql-binary", default="codeql", help="command to use for QL formatting (default %(default)s)")
6772
p.add_argument("--force", "-f", action="store_true",
68-
help="generate all files without skipping unchanged files and overwriting modified ones"),
73+
help="generate all files without skipping unchanged files and overwriting modified ones")
74+
p.add_argument("--use-current-directory", action="store_true",
75+
help="do not consider paths as relative to --root-dir or the configuration directory")
6976
opts = p.parse_args()
7077
if opts.configuration_file is not None:
7178
with open(opts.configuration_file) as config:
@@ -75,16 +82,15 @@ def _parse_args() -> argparse.Namespace:
7582
setattr(opts, flag, getattr(defaults, flag))
7683
if opts.root_dir is None:
7784
opts.root_dir = opts.configuration_file.parent
78-
if opts.root_dir is None:
79-
p.error("Either --configuration-file or --root-dir must be provided, or a codegen.conf file must be in a "
80-
"containing directory")
8185
if not opts.generate:
8286
p.error("Nothing to do, specify --generate")
83-
# absolutize all paths relative to --root-dir
87+
# absolutize all paths
8488
for arg in path_arguments:
8589
path = getattr(opts, arg.dest)
8690
if path is not None:
87-
setattr(opts, arg.dest, opts.root_dir / path)
91+
setattr(opts, arg.dest, _abspath(path) if opts.use_current_directory else (opts.root_dir / path))
92+
if not opts.script_name:
93+
opts.script_name = paths.exe_file.relative_to(opts.root_dir)
8894
return opts
8995

9096

@@ -102,7 +108,7 @@ def run():
102108
log_level = logging.INFO
103109
logging.basicConfig(format="{levelname} {message}", style='{', level=log_level)
104110
for target in opts.generate:
105-
generate(target, opts, render.Renderer(opts.root_dir))
111+
generate(target, opts, render.Renderer(opts.script_name, opts.root_dir))
106112

107113

108114
if __name__ == "__main__":

swift/codegen/generators/cppgen.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,5 @@ def generate(opts, renderer):
9595
out = opts.cpp_output
9696
for dir, classes in processor.get_classes().items():
9797
renderer.render(cpp.ClassList(classes, opts.schema,
98-
include_parent=bool(dir)), out / dir / "TrapClasses")
98+
include_parent=bool(dir),
99+
trap_library=opts.trap_library), out / dir / "TrapClasses")

swift/codegen/generators/dbschemegen.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,8 @@ def generate(opts, renderer):
125125

126126
data = schemaloader.load_file(input)
127127

128-
dbscheme = Scheme(src=input.relative_to(opts.root_dir),
129-
includes=get_includes(data, include_dir=input.parent, root_dir=opts.root_dir),
128+
dbscheme = Scheme(src=input.name,
129+
includes=get_includes(data, include_dir=input.parent, root_dir=input.parent),
130130
declarations=get_declarations(data))
131131

132132
renderer.render(dbscheme, out)

swift/codegen/generators/trapgen.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ def generate(opts, renderer):
7272
assert opts.cpp_output
7373
tag_graph = {}
7474
out = opts.cpp_output
75+
trap_library = opts.trap_library
7576

7677
traps = {pathlib.Path(): []}
7778
for e in dbschemeloader.iterload(opts.dbscheme):
@@ -84,7 +85,8 @@ def generate(opts, renderer):
8485

8586
for dir, entries in traps.items():
8687
dir = dir or pathlib.Path()
87-
renderer.render(cpp.TrapList(entries, opts.dbscheme), out / dir / "TrapEntries")
88+
relative_gen_dir = pathlib.Path(*[".." for _ in dir.parents])
89+
renderer.render(cpp.TrapList(entries, opts.dbscheme, trap_library, relative_gen_dir), out / dir / "TrapEntries")
8890

8991
tags = []
9092
for tag in toposort_flatten(tag_graph):

swift/codegen/lib/cpp.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import pathlib
12
import re
23
from dataclasses import dataclass, field
34
from typing import List, ClassVar
@@ -110,6 +111,8 @@ class TrapList:
110111
extensions = ["h", "cpp"]
111112
traps: List[Trap]
112113
source: str
114+
trap_library_dir: pathlib.Path
115+
gen_dir: pathlib.Path
113116

114117

115118
@dataclass
@@ -156,4 +159,5 @@ class ClassList:
156159

157160
classes: List[Class]
158161
source: str
162+
trap_library: str
159163
include_parent: bool = False

swift/codegen/lib/render.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,10 @@ class Error(Exception):
2525
class Renderer:
2626
""" Template renderer using mustache templates in the `templates` directory """
2727

28-
def __init__(self, root_dir: pathlib.Path):
28+
def __init__(self, generator: pathlib.Path, root_dir: pathlib.Path):
2929
self._r = pystache.Renderer(search_dirs=str(paths.templates_dir), escape=lambda u: u)
3030
self._root_dir = root_dir
31-
try:
32-
self._generator = self._get_path(paths.exe_file)
33-
except ValueError:
34-
self._generator = paths.exe_file.name
31+
self._generator = generator
3532

3633
def _get_path(self, file: pathlib.Path):
3734
return file.relative_to(self._root_dir)
@@ -63,7 +60,7 @@ def _do_write(self, mnemonic: str, contents: str, output: pathlib.Path):
6360

6461
def manage(self, generated: typing.Iterable[pathlib.Path], stubs: typing.Iterable[pathlib.Path],
6562
registry: pathlib.Path, force: bool = False) -> "RenderManager":
66-
return RenderManager(self._root_dir, generated, stubs, registry, force)
63+
return RenderManager(self._generator, self._root_dir, generated, stubs, registry, force)
6764

6865

6966
class RenderManager(Renderer):
@@ -88,10 +85,10 @@ class Hashes:
8885
pre: str
8986
post: typing.Optional[str] = None
9087

91-
def __init__(self, root_dir: pathlib.Path, generated: typing.Iterable[pathlib.Path],
88+
def __init__(self, generator: pathlib.Path, root_dir: pathlib.Path, generated: typing.Iterable[pathlib.Path],
9289
stubs: typing.Iterable[pathlib.Path],
9390
registry: pathlib.Path, force: bool = False):
94-
super().__init__(root_dir)
91+
super().__init__(generator, root_dir)
9592
self._registry_path = registry
9693
self._force = force
9794
self._hashes = {}

swift/codegen/templates/cpp_classes_h.mustache

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#include <optional>
77
#include <vector>
88

9-
#include "swift/extractor/trap/TrapLabel.h"
10-
#include "swift/extractor/trap/TrapTagTraits.h"
9+
#include "{{trap_library}}/TrapLabel.h"
10+
#include "{{trap_library}}/TrapTagTraits.h"
1111
#include "./TrapEntries.h"
1212
{{#include_parent}}
1313
#include "../TrapClasses.h"

swift/codegen/templates/trap_traps_h.mustache

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
#include <iostream>
66
#include <string>
77

8-
#include "swift/extractor/trap/TrapLabel.h"
9-
#include "swift/extractor/trap/TrapTagTraits.h"
10-
#include "swift/extractor/trap/generated/TrapTags.h"
8+
#include "{{trap_library_dir}}/TrapLabel.h"
9+
#include "{{trap_library_dir}}/TrapTagTraits.h"
10+
#include "{{gen_dir}}/TrapTags.h"
1111

1212
namespace codeql {
1313
{{#traps}}

swift/codegen/test/test_dbschemegen.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def func(classes, null=None):
3030

3131
def test_empty(generate):
3232
assert generate([]) == dbscheme.Scheme(
33-
src=schema_file,
33+
src=schema_file.name,
3434
includes=[],
3535
declarations=[],
3636
)
@@ -43,10 +43,10 @@ def test_includes(input, opts, generate):
4343
write(opts.schema.parent / i, i + " data")
4444

4545
assert generate([]) == dbscheme.Scheme(
46-
src=schema_file,
46+
src=schema_file.name,
4747
includes=[
4848
dbscheme.SchemeInclude(
49-
src=schema_dir / i,
49+
src=pathlib.Path(i),
5050
data=i + " data",
5151
) for i in includes
5252
],
@@ -58,7 +58,7 @@ def test_empty_final_class(generate, dir_param):
5858
assert generate([
5959
schema.Class("Object", group=dir_param.input),
6060
]) == dbscheme.Scheme(
61-
src=schema_file,
61+
src=schema_file.name,
6262
includes=[],
6363
declarations=[
6464
dbscheme.Table(
@@ -78,7 +78,7 @@ def test_final_class_with_single_scalar_field(generate, dir_param):
7878
schema.SingleProperty("foo", "bar"),
7979
]),
8080
]) == dbscheme.Scheme(
81-
src=schema_file,
81+
src=schema_file.name,
8282
includes=[],
8383
declarations=[
8484
dbscheme.Table(
@@ -98,7 +98,7 @@ def test_final_class_with_single_class_field(generate, dir_param):
9898
schema.SingleProperty("foo", "Bar"),
9999
]),
100100
]) == dbscheme.Scheme(
101-
src=schema_file,
101+
src=schema_file.name,
102102
includes=[],
103103
declarations=[
104104
dbscheme.Table(
@@ -118,7 +118,7 @@ def test_final_class_with_optional_field(generate, dir_param):
118118
schema.OptionalProperty("foo", "bar"),
119119
]),
120120
]) == dbscheme.Scheme(
121-
src=schema_file,
121+
src=schema_file.name,
122122
includes=[],
123123
declarations=[
124124
dbscheme.Table(
@@ -146,7 +146,7 @@ def test_final_class_with_repeated_field(generate, property_cls, dir_param):
146146
property_cls("foo", "bar"),
147147
]),
148148
]) == dbscheme.Scheme(
149-
src=schema_file,
149+
src=schema_file.name,
150150
includes=[],
151151
declarations=[
152152
dbscheme.Table(
@@ -174,7 +174,7 @@ def test_final_class_with_predicate_field(generate, dir_param):
174174
schema.PredicateProperty("foo"),
175175
]),
176176
]) == dbscheme.Scheme(
177-
src=schema_file,
177+
src=schema_file.name,
178178
includes=[],
179179
declarations=[
180180
dbscheme.Table(
@@ -205,7 +205,7 @@ def test_final_class_with_more_fields(generate, dir_param):
205205
schema.PredicateProperty("six"),
206206
]),
207207
]) == dbscheme.Scheme(
208-
src=schema_file,
208+
src=schema_file.name,
209209
includes=[],
210210
declarations=[
211211
dbscheme.Table(
@@ -259,7 +259,7 @@ def test_empty_class_with_derived(generate):
259259
schema.Class(name="Left", bases=["Base"]),
260260
schema.Class(name="Right", bases=["Base"]),
261261
]) == dbscheme.Scheme(
262-
src=schema_file,
262+
src=schema_file.name,
263263
includes=[],
264264
declarations=[
265265
dbscheme.Union(
@@ -290,7 +290,7 @@ def test_class_with_derived_and_single_property(generate, dir_param):
290290
schema.Class(name="Left", bases=["Base"]),
291291
schema.Class(name="Right", bases=["Base"]),
292292
]) == dbscheme.Scheme(
293-
src=schema_file,
293+
src=schema_file.name,
294294
includes=[],
295295
declarations=[
296296
dbscheme.Union(
@@ -330,7 +330,7 @@ def test_class_with_derived_and_optional_property(generate, dir_param):
330330
schema.Class(name="Left", bases=["Base"]),
331331
schema.Class(name="Right", bases=["Base"]),
332332
]) == dbscheme.Scheme(
333-
src=schema_file,
333+
src=schema_file.name,
334334
includes=[],
335335
declarations=[
336336
dbscheme.Union(
@@ -370,7 +370,7 @@ def test_class_with_derived_and_repeated_property(generate, dir_param):
370370
schema.Class(name="Left", bases=["Base"]),
371371
schema.Class(name="Right", bases=["Base"]),
372372
]) == dbscheme.Scheme(
373-
src=schema_file,
373+
src=schema_file.name,
374374
includes=[],
375375
declarations=[
376376
dbscheme.Union(
@@ -432,7 +432,7 @@ def test_null_class(generate):
432432
bases=["Base"],
433433
),
434434
], null="Null") == dbscheme.Scheme(
435-
src=schema_file,
435+
src=schema_file.name,
436436
includes=[],
437437
declarations=[
438438
dbscheme.Union(
@@ -514,7 +514,7 @@ def test_ipa_classes_ignored(generate):
514514
schema.Class(name="B", ipa=schema.IpaInfo(from_class="A")),
515515
schema.Class(name="C", ipa=schema.IpaInfo(on_arguments={"x": "A"})),
516516
]) == dbscheme.Scheme(
517-
src=schema_file,
517+
src=schema_file.name,
518518
includes=[],
519519
declarations=[],
520520
)
@@ -526,7 +526,7 @@ def test_ipa_derived_classes_ignored(generate):
526526
schema.Class(name="B", bases=["A"], ipa=schema.IpaInfo()),
527527
schema.Class(name="C", bases=["A"]),
528528
]) == dbscheme.Scheme(
529-
src=schema_file,
529+
src=schema_file.name,
530530
includes=[],
531531
declarations=[
532532
dbscheme.Union("@a", ["@c"]),

0 commit comments

Comments
 (0)