Replies: 12 comments
-
It's an interesting question. I think some of it also comes from a bit of familiarity with the tool. When thinking of build targets, the targets that sbt produces currently actually do make sense in the context of sbt. It's funny this sort of relates to a conversation that we had at the Center today about custom configurations, which can also produce targets! If I was to greatly simplify what I think a target means, it'd be something (at least in the Scala world) that has a unique classpath. So in the case of a cross build Scala 3 / Scala 2.13 and JVM and ScalaJS project, the 8 actually make sense as each of those will have a unique classpath for both
I don't fully get this part I guess. When I think of the target I think of any test in that target that can be ran with that same classpath. Can you maybe expand on this a bit?
That's totally fine. A single target can have multiple main classes, but they'd again be ran/created with the same classpath since they're in the same target.
You can, we do this with Metals by passing in the |
Beta Was this translation helpful? Give feedback.
-
@ckipp01 so I think that projects seem to be the missing abstraction layer. See #472.
When I think of a target I think of a single class (in the JVM world).
Under #472 each main class would be a separate target withing a single project.
And I don't like it, because I think that's happening at a wrong level of abstraction. Again, IMO build servers should be forced to present each main class as a separate runnable target. Otherwise build clients will need to handle this special scala-specific data kind just to be able to run different binaries! |
Beta Was this translation helpful? Give feedback.
-
I don't really think so. Take the multiple main class example. If you follow this approach you'd start creating "targets" that are completely artificial in sbt world for example and not logically really mappable to anything an sbt user would be familiar with. I think we should be careful to create new abstractions that maybe make sense for one specific tool, but would be completely artificial for others.
Wouldn't this cause a ton of duplication? For example if you have class A and class B wouldn't a ton of the request/response just be needless duplication?
Again, I don't really think so, but I'm open to be convinced otherwise. Do maybe others have some thoughts? |
Beta Was this translation helpful? Give feedback.
-
Some servers will not even have to support running, this is not a core thing of a build server, while compilation (building) is. And presenting each main class and also test class as a separate target will cause loads of redundant data to pollute the protocol. Additionally, would we base the logic of the BSP server here on the testing framework? That seems dangerous and way too coupled.
Target is not really a very unique word, so this might represent something different for everyone. There is usually a target directory for example, which will contain all classes including many main classes defined in a module. If you feel like for Rust this new approach makes more sense then you can follow it, but for sure we will not be changing anything in the current BSP implementations, since it doesn't really add or solve anything for us. |
Beta Was this translation helpful? Give feedback.
-
I agree with @ckipp01 and @tgodzik that the build target is the right level of abstraction at the build tool level. I think that what you call But you made a point saying that we need to handle a special scala-specific data kind to be able to run different main classes. So maybe what we are missing is the notion of In short, the build would contain many |
Beta Was this translation helpful? Give feedback.
-
I meant a single runnable class
That seems to be a very bold statement. This discussion pertains to a new major version of the protocol anyway. |
Beta Was this translation helpful? Give feedback.
-
In Bazel, for example, you can. But I agree that the notion of a "build target" has become somewhat blurred. In Bazel apparently what you (scala-tooling people) call a "build target" and what you called a "run target" in #472 mean the same thing.
I agree.
That's precisely what I wanted to achieve by introducing a notion of a project :) |
Beta Was this translation helpful? Give feedback.
-
That's exactly how it works in bazel-bsp, because in Bazel you have to define each main class/ test class as a separate Bazel (and hence BSP) target. But I agree that introducing another level of granularity (which for sbt would be a smaller unit than a build target and for Bazel would be something bigger than what currently is considered a build/run target) can be helpful there. For example, in Bazel we could treat each folder/BUILD.bazel file as a build target. And each Bazel target defined inside a build file would become a run target. Cc @tpasternak @jastice @abrams27 we need to discuss it further.
It's up to the server. In bazel-bsp we're working on supporting some of the major java testing frameworks atm. For example, we are able to parse JUnit5 output and present to the client each test separately using task notifications.
It depends. In our (JetBrains') upcoming plugin for Bazel we want to make running and testing over BSP a first class citizen. |
Beta Was this translation helpful? Give feedback.
-
Sometimes I have a feeling that all currently existing abstractions make sense only for sbt ;) I mean, it's hard to deny that BSP started as a Scala/JVM specific project and now we're trying to grow it further, which obviously causes us pain. Cargo and Bazel are way more similar to each other (despite being completely unrelated) than any of them to sbt. But at the same time I must admit that I have little knowledge about the inner workings of sbt, I'm telling only by the assumptions that are being made during creation of a BSP server for each of them. |
Beta Was this translation helpful? Give feedback.
-
To be fair, you should also count Maven, Gradle and Mill into your picture of what a "build target" represents. And except for Mill (which already handle tests as separate modules), they all need to make compromises to project their concept of a "module" or "sub-project" to a "build target". If bazel has smaller build units than sbt, nothing stops it from mapping those smaller unit to distinct BSP "build targets". Once you accept, that you are going to model the same code base differently, based on the used build tool, you probably also accept, that BSP can't please all build tools to the same degree. The question is, are the current abstractions and unifications choosen by BSP good enough? What exactly is not working for bazel or cargo? I mean, just because BSP has multiple build targets for main and test, I'm still not aware of a single sbt project that refactored it's build structure because of that. In the end, we want the IDE to understand how to build, run or test something. Unless BSP proves to be the bottleneck for some usability, it's already good enough if that goal is reached. The IDE is allowed to represent details differently, e.g. whether the option to run various main classes comes from a single build target and its run environment with multiple main classes or from multiple build targets that only know of a single main class should not matter. |
Beta Was this translation helpful? Give feedback.
-
why'd we do that? the current abstraction works for bazel perfectly; on top of that bazel targets can be completely detached from their location in the project structure (potentially we can have all the targets defined in the root BUILD file) also
the only bottleneck im aware is bsp + cargo |
Beta Was this translation helpful? Give feedback.
-
well, afair it's almost always true, but not always - for example https://github.com/bazelbuild/rules_scala/blob/master/docs/scala_test_suite.md or just test rules with test discovery mechanizm |
Beta Was this translation helpful? Give feedback.
-
Bazel targets map naturally to BSP targets. But for example in the sbt world it is much more complicated:
What if you have multiple main classes/binary artifacts/runnable targets inside a single sbt project? Shouldn't you be able to run each one separately? In cargo (Rust's default build tool, my students are implementing BSP support for it: https://github.com/cargo-bsp/cargo-bsp) there's a notion of target configurations (namely: "features") too, but we decided that - instead of each configuration of a project being a separate target - we map cargo targets to BSP targets 1-1 (and keep the configuration as a state/context of the server). So it aligns more closely with Bazel than with sbt.
I think we should specify more clearly what a target is, so that users have better intuition about it. The Bazel/cargo definition of a binary target would be: "a binary target is the smallest unit within a project that can be run individually and produced stdout/stderr". What is a single test target would depend on the testing framework and language, but we could specify that "when a test target is run, it must produce a clear indication whether it succeeded or failed. The granularity and type (unit/integration/e2e) of the test depends on the testing framework. A test target can map for example to a single unit test or all unit tests in a given file (for example, in the Java class),"
Beta Was this translation helpful? Give feedback.
All reactions