Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify output flavor with starlark configuration #2162

Open
ashi009 opened this issue Sep 1, 2020 · 5 comments
Open

Simplify output flavor with starlark configuration #2162

ashi009 opened this issue Sep 1, 2020 · 5 comments
Labels
need: discussion On the agenda for team meeting to determine next steps package:typescript

Comments

@ashi009
Copy link
Contributor

ashi009 commented Sep 1, 2020

🚀 feature request

Relevant Rules

ts_library and potentially other rules

Description

Currently, all the javascript rules use providers to differentiate outputs for different modes, eg. AMD, ESM. Consumers will then pick the right output based on their needs by using a provider or add a proxy filegroup to pick the right output_group.

However, this approach requires that the output files of different flavors be unique, and there is no simple way to create a target that consumes a dependency tree of specific flavor outputs. Consumers must know the right way to pick the output flavor they want.

Describe the solution you'd like

Use build settings API to transparently determine the output of a dependency ts_library. ts_library always produces the output with the same name, and the content may vary based on the build settings.

ts_library(
  # implicitly depends on the build settings for typescript, and it will 
  # produce only one set of outputs as `DefaultInfo` based on the
  # build settings, and bazel will create different output dirs for
  # different build configs -- consumers only see the output tree
  # matching their config.
  name = "lib",
)

devserver(
  # implicitly set the build settings for the deps with a transition:
  # [
  #   { “@npm//@bazel/typescript:mode”: "dev" },
  #   { “@npm//@bazel/typescript:target”: "es5" },
  #   { “@npm//@bazel/typescript:module”: "amd" },
  # ]
  deps = [":lib"],
)

rollup_bundle(
  # implicitly set the build settings for the deps with a transition:
  # [
  #   { “@npm//@bazel/typescript:mode”: "prod" },
  #   { “@npm//@bazel/typescript:target”: "esnext" },
  #   { “@npm//@bazel/typescript:module”: "esmodule" },
  # ]
  deps = [":lib"],
)

This could also enable possibilities like build nodejs/browser targets with the same dependency graph (eg. #2073).

See bazel doc and example from rules_go.

Describe alternatives you've considered

@DavidANeil
Copy link
Contributor

This feels similar to the recent work to move some tsconfig into a starlark dict/rule, but using transitions instead.

Do you feel like transitions provide a certain advantage, or was it just top-of-mind?

@ashi009
Copy link
Contributor Author

ashi009 commented Sep 3, 2020

There should be lots of advantages over the current implementation.

  • The current implementation generates a huge action graph for all flavors at once, and bazel has to analyze those actions all together, though some of them will never be used. With build settings, only one flavor will be analyzed at a time unless there is a transition to require a different flavor.
  • The implementation should be significantly simpler, as the rule only need to deal with a single flavor at once (generate a single tsconfig as well), and the dependent rules will only see that flavor. So we don't need to work around those source locating difficulties and we don't need to understand all those providers to implement a rule. Everything should be as simple as DefaulInfo.
  • With build settings we can build any flavor we want, not limited to the predefined list of flavors. Eg. ESnext build.
  • Support target based select in build files.
  • Build settings also provide a common ground for people to extend the frontend build system. For instance, add browserslist support as a build setting and css rules can take the hint from that config (this needs further discussion, but I think the idea should be the same).

@alexeagle
Copy link
Collaborator

How is this different from ts_project? It already generates only one action, has a tremendously simpler implementation, and you can use the out_dir attribute to get different output flavors to different distinct paths in the output tree.

@alexeagle alexeagle added need: discussion On the agenda for team meeting to determine next steps package:typescript labels Sep 3, 2020
@ashi009
Copy link
Contributor Author

ashi009 commented Sep 3, 2020

Well, I'd say completely different.

ts_project requires the user to write many tsconfig files for different outputs, which means, the consuming rule won't be able to choose the output they expect without modifying the provider rule -- thinking about the long-standing xx_proto_library issue in g3.

Also, if multiple outputs were required, users must add those actions as rules in build files -- which is tedious, error-prone, and doing things bazel is capable of doing (pretty much the definition of toil).

Most importantly, ts_project is not something one would use in a bazel idiomatic environment. The simplicity ts_project implies is due to its limited capability. I wish that the build settings API could reduce ts_library's necessary complexity, yet delivering the same or even better functionalities.

We can discuss more on slack -- if you have time.

@ashi009
Copy link
Contributor Author

ashi009 commented Sep 3, 2020

To clarify, the "output dir" is the top-level bazel output directory right under the bazel-out:

bazel-out/
  local_linux-fastbuild/        <== this will be different for different settings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need: discussion On the agenda for team meeting to determine next steps package:typescript
Projects
None yet
Development

No branches or pull requests

3 participants