Skip to content

Commit bc04925

Browse files
author
hscham
committed
libchrome: downgrade mojom types at arc build time
This is to prepare for synchronizing .mojom files with those in chromium/src which are in new syntax. Add the mojom downgrading python script from crrev.com/c/2082513. In soong/bindings_generator.go, define new ModuleFactory executing it and register as new Module generate_mojom_downgraded_files. The change will be cherry-picked to ARC branches to use in Android.bp: downgraded .mojom files are generated from the original .mojom files using the new module, then they would (replace the original .mojom files to) be used as input to generate bindings. Files in old syntax will be output as is. Note that previously, when generating the bindings, it is assumed that the input .mojom files are located under the module's local source directory, which is then given as value of argument depth to mojo/public/tools/bindings/mojom_bindings_generator.py. The mojom_bindings_generator.py computes the relative path (hence output path) accordingly. Since this is no longer true, the source root would now be computed per input .mojom file. Bug: 149070836, chromium:1035484 Test: local build; compare downgraded mojom files and generated bindings Change-Id: I86a6c67c5ae7056f3c9f617a1c5a9c954c10aa0d
1 parent 649dae6 commit bc04925

File tree

2 files changed

+203
-6
lines changed

2 files changed

+203
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#!/usr/bin/env python
2+
# Copyright 2020 The Chromium Authors. All rights reserved.
3+
# Use of this source code is governed by a BSD-style license that can be
4+
# found in the LICENSE file.
5+
"""Downgrades *.mojom files to the old mojo types for remotes and receivers."""
6+
7+
import argparse
8+
import fnmatch
9+
import os
10+
import re
11+
import shutil
12+
import sys
13+
import tempfile
14+
15+
# List of patterns and replacements to match and use against the contents of a
16+
# mojo file. Each replacement string will be used with Python string's format()
17+
# function, so the '{}' substring is used to mark where the mojo type should go.
18+
_MOJO_REPLACEMENTS = {
19+
r'pending_remote': r'{}',
20+
r'pending_receiver': r'{}&',
21+
r'pending_associated_remote': r'associated {}',
22+
r'pending_associated_receiver': r'associated {}&',
23+
}
24+
25+
# Pre-compiled regular expression that matches against any of the replacements.
26+
_REGEXP_PATTERN = re.compile(
27+
r'|'.join(
28+
['{}\s*<\s*(.*?)\s*>'.format(k) for k in _MOJO_REPLACEMENTS.keys()]),
29+
flags=re.DOTALL)
30+
31+
32+
def ReplaceFunction(match_object):
33+
"""Returns the right replacement for the string matched against the regexp."""
34+
for index, (match, repl) in enumerate(_MOJO_REPLACEMENTS.items(), 1):
35+
if match_object.group(0).startswith(match):
36+
return repl.format(match_object.group(index))
37+
38+
39+
def DowngradeFile(path, output_dir=None):
40+
"""Downgrades the mojom file specified by |path| to the old mojo types.
41+
42+
Optionally pass |output_dir| to place the result under a separate output
43+
directory, preserving the relative path to the file included in |path|.
44+
"""
45+
# Use a temporary file to dump the new contents after replacing the patterns.
46+
with open(path) as src_mojo_file:
47+
with tempfile.NamedTemporaryFile(mode='w', delete=False) as tmp_mojo_file:
48+
tmp_contents = _REGEXP_PATTERN.sub(ReplaceFunction, src_mojo_file.read())
49+
tmp_mojo_file.write(tmp_contents)
50+
51+
# Files should be placed in the desired output directory
52+
if output_dir:
53+
output_filepath = os.path.join(output_dir, os.path.basename(path))
54+
if not os.path.exists(output_dir):
55+
os.makedirs(output_dir)
56+
else:
57+
output_filepath = path
58+
59+
# Write the new contents preserving the original file's attributes.
60+
shutil.copystat(path, tmp_mojo_file.name)
61+
shutil.move(tmp_mojo_file.name, output_filepath)
62+
63+
# Make sure to "touch" the new file so that access, modify and change times
64+
# are always newer than the source file's, otherwise Modify time will be kept
65+
# as per the call to shutil.copystat(), causing unnecessary generations of the
66+
# output file in subsequent builds due to ninja considering it dirty.
67+
os.utime(output_filepath, None)
68+
69+
70+
def DowngradeDirectory(path, output_dir=None):
71+
"""Downgrades mojom files inside directory |path| to the old mojo types.
72+
73+
Optionally pass |output_dir| to place the result under a separate output
74+
directory, preserving the relative path to the file included in |path|.
75+
"""
76+
# We don't have recursive glob.glob() nor pathlib.Path.rglob() in Python 2.7
77+
mojom_filepaths = []
78+
for dir_path, _, filenames in os.walk(path):
79+
for filename in fnmatch.filter(filenames, "*mojom"):
80+
mojom_filepaths.append(os.path.join(dir_path, filename))
81+
82+
for path in mojom_filepaths:
83+
absolute_dirpath = os.path.dirname(os.path.abspath(path))
84+
if output_dir:
85+
dest_dirpath = output_dir + absolute_dirpath
86+
else:
87+
dest_dirpath = absolute_dirpath
88+
DowngradeFile(path, dest_dirpath)
89+
90+
91+
def DowngradePath(src_path, output_dir=None):
92+
"""Downgrades the mojom files pointed by |src_path| to the old mojo types.
93+
94+
Optionally pass |output_dir| to place the result under a separate output
95+
directory, preserving the relative path to the file included in |path|.
96+
"""
97+
if os.path.isdir(src_path):
98+
DowngradeDirectory(src_path, output_dir)
99+
elif os.path.isfile(src_path):
100+
DowngradeFile(src_path, output_dir)
101+
else:
102+
print(">>> {} not pointing to a valid file or directory".format(src_path))
103+
sys.exit(1)
104+
105+
106+
def main():
107+
parser = argparse.ArgumentParser(
108+
description="Downgrade *.mojom files to use the old mojo types.")
109+
parser.add_argument(
110+
"srcpath", help="path to the file or directory to apply the conversion")
111+
parser.add_argument(
112+
"--outdir", help="the directory to place the converted file(s) under")
113+
args = parser.parse_args()
114+
115+
DowngradePath(args.srcpath, args.outdir)
116+
117+
118+
if __name__ == "__main__":
119+
sys.exit(main())

soong/bindings_generator.go

+84-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
)
1313

1414
func init() {
15+
android.RegisterModuleType("generate_mojom_downgraded_files", mojomDowngradedFilesFactory)
1516
android.RegisterModuleType("generate_mojom_pickles", mojomPicklesFactory)
1617
android.RegisterModuleType("generate_mojom_headers", mojomHeadersFactory)
1718
android.RegisterModuleType("generate_mojom_srcs", mojomSrcsFactory)
@@ -22,8 +23,19 @@ var (
2223
pctx = android.NewPackageContext("android/soong/external/libchrome")
2324

2425
mojomBindingsGenerator = pctx.HostBinToolVariable("mojomBindingsGenerator", "mojom_bindings_generator")
26+
mojomTypesDowngrader = pctx.HostBinToolVariable("mojomTypesDowngrader", "mojom_types_downgrader")
2527
mergeZips = pctx.HostBinToolVariable("mergeZips", "merge_zips")
2628

29+
downgradeMojomTypesRule = pctx.StaticRule("downgradeMojomTypesRule", blueprint.RuleParams{
30+
Command: `${mojomTypesDowngrader}
31+
${in}
32+
--outdir ${outDir}`,
33+
CommandDeps: []string{
34+
"${mojomTypesDowngrader}",
35+
},
36+
Description: "Downgrade mojom files $in => $out",
37+
}, "outDir")
38+
2739
generateMojomPicklesRule = pctx.StaticRule("generateMojomPicklesRule", blueprint.RuleParams{
2840
Command: `${mojomBindingsGenerator}
2941
--use_bundled_pylibs parse
@@ -65,6 +77,72 @@ var (
6577
})
6678
)
6779

80+
type mojomDowngradedFilesProperties struct {
81+
// list of input files
82+
Srcs []string
83+
}
84+
85+
type mojomDowngradedFiles struct {
86+
android.ModuleBase
87+
88+
properties mojomDowngradedFilesProperties
89+
90+
generatedSrcs android.Paths
91+
outDir android.Path
92+
}
93+
94+
var _ genrule.SourceFileGenerator = (*mojomDowngradedFiles)(nil)
95+
96+
func (m *mojomDowngradedFiles) DepsMutator(ctx android.BottomUpMutatorContext) {
97+
android.ExtractSourcesDeps(ctx, m.properties.Srcs)
98+
}
99+
100+
func (m *mojomDowngradedFiles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
101+
m.outDir = android.PathForModuleGen(ctx, "")
102+
103+
for _, in := range ctx.ExpandSources(m.properties.Srcs, nil) {
104+
if !strings.HasSuffix(in.Rel(), ".mojom") {
105+
ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
106+
continue
107+
}
108+
109+
out := android.PathForModuleGen(ctx, in.Rel())
110+
m.generatedSrcs = append(m.generatedSrcs, out)
111+
112+
ctx.ModuleBuild(pctx, android.ModuleBuildParams{
113+
Rule: downgradeMojomTypesRule,
114+
Input: in,
115+
Output: out,
116+
Args: map[string]string{
117+
"outDir": path.Dir(out.String()),
118+
},
119+
})
120+
}
121+
}
122+
123+
func (m *mojomDowngradedFiles) GeneratedHeaderDirs() android.Paths {
124+
return nil
125+
}
126+
127+
func (m *mojomDowngradedFiles) GeneratedDeps() android.Paths {
128+
return append(android.Paths{}, m.generatedSrcs...)
129+
}
130+
131+
func (m *mojomDowngradedFiles) GeneratedSourceFiles() android.Paths {
132+
return append(android.Paths{}, m.generatedSrcs...)
133+
}
134+
135+
func (m *mojomDowngradedFiles) Srcs() android.Paths {
136+
return append(android.Paths{}, m.generatedSrcs...)
137+
}
138+
139+
func mojomDowngradedFilesFactory() android.Module {
140+
m := &mojomDowngradedFiles{}
141+
m.AddProperties(&m.properties)
142+
android.InitAndroidModule(m)
143+
return m
144+
}
145+
68146
type mojomPicklesProperties struct {
69147
// list of input files
70148
Srcs []string
@@ -88,13 +166,14 @@ func (m *mojomPickles) DepsMutator(ctx android.BottomUpMutatorContext) {
88166
func (m *mojomPickles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
89167
m.outDir = android.PathForModuleGen(ctx, "")
90168

91-
packagePath := android.PathForModuleSrc(ctx, "")
92-
93169
for _, in := range ctx.ExpandSources(m.properties.Srcs, nil) {
94170
if !strings.HasSuffix(in.Rel(), ".mojom") {
95171
ctx.PropertyErrorf("srcs", "Source is not a .mojom file: %s", in.Rel())
96172
continue
97173
}
174+
175+
srcRoot := strings.TrimSuffix(in.String(), in.Rel())
176+
98177
relStem := strings.TrimSuffix(in.Rel(), ".mojom")
99178

100179
out := android.PathForModuleGen(ctx, relStem+".p")
@@ -105,9 +184,8 @@ func (m *mojomPickles) GenerateAndroidBuildActions(ctx android.ModuleContext) {
105184
Input: in,
106185
Output: out,
107186
Args: map[string]string{
108-
"package": packagePath.Rel(),
187+
"package": srcRoot,
109188
"outDir": m.outDir.String(),
110-
"flags": fmt.Sprintf("-I=%s:%s", packagePath, packagePath),
111189
},
112190
})
113191
}
@@ -237,7 +315,6 @@ func (p *mojomGenerationProperties) generateBuildActions(
237315
mojomGenerator string,
238316
descriptions []mojomSrcsRuleDescription,
239317
) android.Paths {
240-
packageName := android.PathForModuleSrc(ctx, "").Rel()
241318
outDir := android.PathForModuleGen(ctx, "")
242319
implicitDeps := p.implicitDeps(ctx)
243320
templateDir := p.templateDir(ctx)
@@ -249,6 +326,7 @@ func (p *mojomGenerationProperties) generateBuildActions(
249326
continue
250327
}
251328
relStem := strings.TrimSuffix(in.Rel(), ".mojom")
329+
srcRoot := strings.TrimSuffix(in.String(), in.Rel())
252330

253331
for _, description := range descriptions {
254332
outs := android.WritablePaths{}
@@ -264,7 +342,7 @@ func (p *mojomGenerationProperties) generateBuildActions(
264342
Outputs: outs,
265343
Args: map[string]string{
266344
"mojomGenerator": mojomGenerator,
267-
"package": packageName,
345+
"package": srcRoot,
268346
"flags": fmt.Sprintf("%s %s", p.flags(ctx), description.extraFlags),
269347
"outDir": outDir.String(),
270348
"templateDir": templateDir,

0 commit comments

Comments
 (0)