Commit 9eb8fd64 authored by Giovanni Ortuño Urquidi's avatar Giovanni Ortuño Urquidi Committed by Commit Bot

mojo-ts: Support dependencies between mojom targets

We do this by changing three things:

1. Set `composite` to `true`. From Typescript docs:
```
The composite option enforces certain constraints which make it possible
for build tools to quickly determine if a project has been built yet.
```
This results in the TypeScript compiler generating two new files for
each mojom target:
  - Declaration files (.d.ts) which in the Mojo case describes the
    exported Mojo interface.
  - tsBuildInfo files (.tsbuildinfo) which store incremental
    compilation information as a part of composite projects which
    enables faster building of larger TypeScript codebases.

2. Adding `references` to tsconfigs, to tell the compile that a target
   depends on other targets.

3. Adding `/// <reference>` to non-es-modules files, to tell the
   compiler which files that file references. Somewhat surprisingly
   adding `references` to the tsconfig was not enough.

This results in:

1. Each mojom target getting compiled only once, independent of how many
   other targets depend on it.
2. The compiler complaining if we forget to add a mojom target to
   `references` and if we forget to add `/// <reference>`s for files
   in non-es-modules files.
3. When compiling a mojom target, the compiler only attempts to compile
   the specific target i.e. it doesn't try to compile its
   dependencies. It's up to ninja to trigger the compilation of
   dependencies. If a dependent target hasn't been compiled yet,
   the compiler will throw an error. This ensures that we don't
   accidentally forget dependencies in our generated bindings.

The upside of this, is that compilation order is controlled by gn
and ninja. The downside is that we need to run an instance of the
compiler for each target and we don't get to take advantage of the
--build flag, which changes the compiler to act more like an
orchestrator than a simple compiler.

Bug: 1002798
Change-Id: I831aaaa9a0f159d6e90b9ec698ba5cc1f7653c4d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2274387Reviewed-by: default avatarKen Rockot <rockot@google.com>
Commit-Queue: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#784318}
parent ed0c24ef
......@@ -4,6 +4,29 @@
import("//mojo/public/tools/bindings/mojom.gni")
# Target to test that one target can depend on another.
mojom("other_test_interfaces1") {
testonly = true
sources = [ "export_other1.test-mojom" ]
use_typescript_sources = true
}
# Targets that test when a target depends on a target that depends on a third
# target i.e. "test_interfaces" depends on "other_interfaces3", which in turn
# depends on "other_interfaces2".
mojom("other_test_interfaces2") {
testonly = true
sources = [ "export_other2.test-mojom" ]
use_typescript_sources = true
}
mojom("other_test_interfaces3") {
testonly = true
sources = [ "export_other3.test-mojom" ]
public_deps = [ ":other_test_interfaces2" ]
use_typescript_sources = true
}
# Partial copy of //mojo/public/interfaces/bindings/tests:test_interfaces. Used
# to incrementally develop Typescript bindings.
mojom("test_interfaces") {
......@@ -20,6 +43,10 @@ mojom("test_interfaces") {
"other_dir/other_dir.test-mojom",
"structs.test-mojom",
]
public_deps = [
":other_test_interfaces1",
":other_test_interfaces3",
]
use_typescript_sources = true
}
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module mojo.tstest.exported_other;
const uint8 kOne = 1;
struct ExportedStructOne {
bool value;
};
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module mojo.tstest.exported_other;
const uint8 kTwo = 2;
struct ExportedStructTwo {
bool value;
};
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
module mojo.tstest.exported_other;
import "mojo/public/js/ts/bindings/tests/export_other2.test-mojom";
const uint8 kAlsoTwo = mojo.tstest.exported_other.kTwo;
struct ExportedStructThree {
ExportedStructTwo value;
};
......@@ -8,15 +8,22 @@ import "mojo/public/js/ts/bindings/tests/export1.test-mojom";
import "mojo/public/js/ts/bindings/tests/export2.test-mojom";
import "mojo/public/js/ts/bindings/tests/export4.test-mojom";
import "mojo/public/js/ts/bindings/tests/other_dir/other_dir.test-mojom";
import "mojo/public/js/ts/bindings/tests/export_other1.test-mojom";
import "mojo/public/js/ts/bindings/tests/export_other3.test-mojom";
const uint8 kImportedOne = mojo.tstest.exported.kOne;
const uint8 kImportedTwo = mojo.tstest.exported.kTwo;
const uint8 kImportedThree = mojo.tstest.exported.kAlsoThree;
const uint8 kImportedOtherDir = mojo.tstest.exported.kOtherDir;
const uint8 kImportedOtherOne = mojo.tstest.exported_other.kOne;
const uint8 kImportedOtherTwo = mojo.tstest.exported_other.kAlsoTwo;
struct StructWithImportedStructs {
mojo.tstest.exported.ExportedStructOne val1;
mojo.tstest.exported.ExportedStructTwo val2;
mojo.tstest.exported.ExportedStructFour val4;
mojo.tstest.exported.ExportedStructOtherDir val_other_dir;
mojo.tstest.exported_other.ExportedStructOne val_other1;
mojo.tstest.exported_other.ExportedStructThree val_other3;
};
......@@ -19,7 +19,7 @@ def main(argv):
args = parser.parse_args(argv)
result = node.RunNode([node_modules.PathToTypescript()] +
['--project %s' % args.tsconfig_path])
['--project', args.tsconfig_path])
if len(result) != 0:
raise RuntimeError('Failed to compile Typescript: \n%s' % result)
......
......@@ -2,15 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{%- if use_es_modules %}
{%- for import in module.imports %}
{%- if use_es_modules %}
{#
# We add a ".js" file extension because otherwise the compiled JS would import
# "-lite.m" which doesn't work on browsers unless served with a
# "text/javascript" MIME type.
#}
import * as {{import.unique_alias}} from '{{import.path|relative_path}}-lite.m.js';
{%- endfor %}
{% else %}
/// <reference path="{{import.path|relative_path}}-lite.ts" />
{% endif %}
{%- endfor %}
{% include "module_definition.tmpl" %}
......@@ -1811,6 +1811,7 @@ template("mojom") {
":$parser_target_name",
"//mojo/public/tools/bindings:precompile_templates",
]
outputs = ts_outputs
args = common_generator_args
response_file_contents = source_filelist
......@@ -1835,6 +1836,7 @@ template("mojom") {
tsconfig = {
}
tsconfig.compilerOptions = {
composite = true
target = "es6"
module = "es6"
lib = [
......@@ -1850,6 +1852,17 @@ template("mojom") {
target_gen_dir,
root_gen_dir) ]
}
tsconfig.references = []
# Get tsconfigs for deps.
foreach(d, all_deps) {
dep_target_gen_dir = rebase_path(get_label_info(d, "target_gen_dir"))
dep_name = get_label_info(d, "name")
reference = {
}
reference.path = "$dep_target_gen_dir/$dep_name-${dependency_type.name}-tsconfig.json"
tsconfig.references += [ reference ]
}
write_file(tsconfig_filename, tsconfig, "json")
# Compile previously generated Typescript to Javascript.
......@@ -1862,6 +1875,12 @@ template("mojom") {
sources = ts_outputs
outputs = js_outputs
public_deps = [ ":$generator_ts_target_name" ]
foreach(d, all_deps) {
full_name = get_label_info(d, "label_no_toolchain")
public_deps +=
[ "${full_name}_${dependency_type.name}__js__generator" ]
}
absolute_tsconfig_path =
rebase_path(tsconfig_filename, "", target_gen_dir)
args = [ "--tsconfig_path=$absolute_tsconfig_path" ]
......
......@@ -7,6 +7,9 @@
<script src="/gen/mojo/public/js/ts/bindings/tests/export3.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/export4.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/other_dir/other_dir.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/export_other1.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/export_other2.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/export_other3.test-mojom-lite.js"></script>
<script src="/gen/mojo/public/js/ts/bindings/tests/import.test-mojom-lite.js"></script>
<script>
'use strict';
......@@ -15,5 +18,7 @@ test(() => {
assert_equals(mojo.tstest.imported.IMPORTED_TWO, 2);
assert_equals(mojo.tstest.imported.IMPORTED_THREE, 3);
assert_equals(mojo.tstest.imported.IMPORTED_OTHER_DIR, 1);
assert_equals(mojo.tstest.imported.IMPORTED_OTHER_ONE, 1);
assert_equals(mojo.tstest.imported.IMPORTED_OTHER_TWO, 2);
}, 'Checks that values of imported constants is correct');
</script>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment