| # Copyright 2021 The Chromium Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import("../../../scripts/build/typescript/typescript.gni") |
| import("./bundle.gni") |
| import("./copy.gni") |
| import("./node.gni") |
| import("./vars.gni") |
| |
| # This defines an entrypoint for DevTools, which uses Rollup |
| # in release mode, but creates an unbundled JavaScript file |
| # in debug mode. This entrypoint should only be used if: |
| # 1. it defines a file that is statically imported. E.g. in |
| # the form of "../entrypoint/entrypoint.js". |
| # 2. it defines a file that is dynamically imported by the |
| # runtime. This uses the same notation, but uses a dynamic |
| # import in `core/root/Runtime.js`. |
| template("devtools_entrypoint") { |
| assert(defined(invoker.entrypoint), |
| "You must define the 'entrypoint' for a bundle target") |
| |
| _entrypoint_target_name = "devtools_entrypoint-" + target_name |
| |
| _entrypoint_output_file_name = get_path_info(invoker.entrypoint, "name") |
| _entrypoint_gen_file_location = |
| "$target_gen_dir/$_entrypoint_output_file_name.js" |
| |
| _devtools_entrypoint_deps = [] |
| |
| # If we don't bundle, the entrypoint is kept as-is. This means we only |
| # need to compile with TypeScript/esbuild, which means it will fetch all |
| # of its files as separate network requests. |
| if (!devtools_bundle) { |
| _ts_library_target_name = _entrypoint_target_name + "-typescript" |
| |
| ts_library(_ts_library_target_name) { |
| forward_variables_from(invoker, ["deps", "es_target", "es_libs", "inputs"]) |
| |
| sources = [ invoker.entrypoint ] |
| } |
| |
| _devtools_entrypoint_deps += [ ":$_ts_library_target_name" ] |
| } else { |
| # Otherwise, we are running Rollup and thus bundle all |
| # files in the (sub-)folder(s) into 1 file. |
| # |
| # To make sure that the build system can handle the Rollup |
| # bundle, we have to use several tasks. That's because we |
| # can't have 2 tasks generate a file to the same location. |
| # |
| # First, we need to compile the entrypoint with TypeScript |
| # as usual. However, we can't put the output into the |
| # location of the entrypoint, as that's where we are going |
| # to put the Rollup bundle output. Therefore, we need to |
| # create a separate file called the "entrypoint.prebundle.ts" |
| # file. |
| # |
| # We compile the "prebundle.ts" with TypeScript, to create |
| # the "prebundle.js" file. We pass in the "prebundle.js" |
| # into Rollup, which then outputs into the normal |
| # "entrypoint.js" location. |
| # |
| # Since TypeScript does not support renaming of files during |
| # compilation, we first have a "copy" task that copies (and |
| # essentially renames) the file to the output directory. |
| # |
| # Additionally, we need to fix the tsconfig renaming, to patch |
| # up the generated tsconfig.json as part of the second ts_library |
| # step. |
| # |
| # Since all of these tasks depend on each other, we have to |
| # make sure that the GN dependency graph correctly corresponds |
| # to that. Therefore, the graph looks like so: |
| # |
| # copy -> ts_library -> fix-tsconfig -> bundle |
| # |
| _entrypoint_output_file_name = get_path_info(invoker.entrypoint, "name") |
| _output_file_name = |
| "$target_gen_dir/$_entrypoint_output_file_name.prebundle" |
| _copy_output_file_name = "$_output_file_name.ts" |
| _prebundle_output_file_name = "$_output_file_name.js" |
| |
| _copy_target_name = _entrypoint_target_name + "-copy" |
| _bundle_target_name = _entrypoint_target_name + "-bundle" |
| _prebundle_target_name = _entrypoint_target_name + "-tsconfig" |
| |
| node_action(_copy_target_name) { |
| script = "scripts/build/ninja/copy-file.js" |
| |
| inputs = [ invoker.entrypoint ] |
| |
| outputs = [ _copy_output_file_name ] |
| |
| _copy_src = rebase_path(".", root_build_dir) + "/" + invoker.entrypoint |
| _copy_dest = rebase_path(_copy_output_file_name, root_build_dir) |
| |
| args = [ |
| _copy_src, |
| _copy_dest, |
| ] |
| |
| public_deps = invoker.deps |
| } |
| |
| ts_library(_prebundle_target_name) { |
| forward_variables_from(invoker, ["deps", "es_target", "es_libs", "inputs"]) |
| |
| sources = [ _copy_output_file_name ] |
| |
| rootdir = target_gen_dir |
| |
| public_deps = [ ":$_copy_target_name" ] |
| |
| } |
| |
| bundle(_bundle_target_name) { |
| entrypoint = _prebundle_output_file_name |
| |
| output_file_location = _entrypoint_gen_file_location |
| |
| # Since bundles both the entrypoint and the files it imports, |
| # we have to make sure that, when you change a file it imports, we |
| # retrigger Rollup. Since the `invoker.deps` is a reference to the |
| # `ts_library` that compiles all of the files it imports, we have to |
| # explicitly add it here. If you don't, then the file change will |
| # retrigger the copy action above, but "the output of the copy action" |
| # is the same. So Ninja will detect that no output has changed for |
| # "_typescript_target_name" and bail out. This would then *also* skip |
| # the Rollup action. |
| public_deps = [ ":$_prebundle_target_name" ] + invoker.deps |
| } |
| |
| if (!devtools_skip_typecheck) { |
| _generated_declaration_target_name = |
| _entrypoint_target_name + "-generate-declaration" |
| |
| # TypeScript requires a `module.d.ts` that describes |
| # the public API of the `module.js` entrypoint. To do so, we copy |
| # the generated `prebundle.d.ts` over, as the public API for a |
| # rolled up bundle remains the same. |
| node_action(_generated_declaration_target_name) { |
| script = "scripts/build/ninja/generate-declaration.js" |
| |
| args = [ |
| rebase_path(target_gen_dir, root_build_dir), |
| invoker.entrypoint, |
| ] |
| |
| public_deps = [ |
| ":$_bundle_target_name", |
| ":$_prebundle_target_name", |
| ] |
| |
| outputs = [ "$target_gen_dir/$_entrypoint_output_file_name.d.ts" ] |
| } |
| |
| _devtools_entrypoint_deps += [ ":$_generated_declaration_target_name" ] |
| } else { |
| _devtools_entrypoint_deps += [ |
| ":$_bundle_target_name", |
| ":$_prebundle_target_name", |
| ] |
| } |
| } |
| |
| # Because we change the filename before rolling up the bundle, |
| # tsc can get upset when it uses the original `target_name` to |
| # reference a different `ts_library`. The `ts_library` action |
| # above generates a `tsconfig.json` which does not include the |
| # `target_name`, but instead uses `_ts_library_target_name`. |
| # |
| # For example, if the `target_name` is "module", the `ts_library` |
| # action above generates a |
| # `devtools_entrypoint-module-typescript-tsconfig.json`. However, |
| # if a different `ts_library` depends on this `devtools_entrypoint`, |
| # it depends on it as "../module:module". Therefore, the expected |
| # location of the `tsconfig.json` is instead `module-tsconfig.json`. |
| # |
| # Therefore, we need to generate a separate tsconfig.json which |
| # artificially mimics what `ts_library` would have generated. |
| _generated_tsconfig_location = |
| target_gen_dir + "/" + invoker.target_name + "-tsconfig.json" |
| _target_outputs = [ _entrypoint_gen_file_location ] |
| |
| node_action(target_name) { |
| script = "scripts/build/ninja/generate-tsconfig.js" |
| |
| args = [ |
| rebase_path(_generated_tsconfig_location, root_build_dir), |
| rebase_path(invoker.entrypoint, root_build_dir), |
| ] + invoker.deps |
| |
| public_deps = _devtools_entrypoint_deps |
| |
| outputs = [ _generated_tsconfig_location ] |
| |
| data = _target_outputs |
| |
| metadata = { |
| grd_files = _target_outputs |
| } |
| |
| if (defined(invoker.visibility)) { |
| visibility = invoker.visibility |
| } else { |
| visibility = [ ":*" ] |
| } |
| } |
| } |
| |
| set_defaults("devtools_entrypoint") { |
| inputs = [] |
| } |