--
You received this message because you are subscribed to the Google Groups "bazel-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-dev/9bd2d56e-1eab-4274-837d-72555b9355acn%40googlegroups.com.
Specific comments:I think I mentioned to you last week, the special targets @bazel_tools//platforms:target_platform and @bazel_tools//platforms:host_platform are deprecated and scheduled to be removed (support for them only still exists for internal-to-Google reasons, otherwise they'd be gone). See https://github.com/bazelbuild/bazel/pull/9109 and related issues, and https://github.com/bazelbuild/proposals/blob/master/designs/2018-10-22-autoconfigured-host-platform.md for the design proposal.Currently in Bazel, the default value of the `--host_platform` flag is @local_config_platform//:host, and the value of the `--platforms` flag is whatever was chosen as the host platform. The logic is present in PlatformOptions.computeTargetPlatform() and PlatformOptions.computeHostPlatform() (see https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/analysis/PlatformOptions.java). It's complicated by the support for disabling "--incompatible_auto_configure_host_platform", but that's all legacy for Bazel. Support only still exists for Google-internal reasons.
In your proposal, you state:```Rationalia for those two requirements are:
- Use embedded JDK for compilation in order to have hermetic compiles.
- Use locally installed JDK in order to execute Java code without Bazel installed.```I thought we weren't supporting using the embedded JDK for builds, just to execute Bazel?
Why can't we require users of Java rules to install a local JDK (and auto-configure that properly for them, including both toolchain types),
or to use a hermetic remote JDK (and configure that properly in the WORKSPACE)? That seems the cleanest approach and should allow us to properly handle local and remote builds.
Fundamentally, Bazel shouldn't be trying to distinguish between "builds for the target platform" and "builds for an execution platform that is identical to the target platform": they should be handled the same way because they are the same builds.
On Tue, Sep 29, 2020 at 9:50 AM John Cater <jca...@google.com> wrote:The actual proposal is now live at https://github.com/bazelbuild/proposals/blob/master/designs/2020-09-29-new-default-target-constraint.mdSpecific comments to follow.On Tue, Sep 29, 2020 at 7:16 AM 'Ivo List' via bazel-dev <baze...@googlegroups.com> wrote:Hi everyone,--I am working on toolchain resolution for Java rules. One of the obstacles is that target and host platforms are identical which necessarily results in resolving the same toolchains (where java uses two different JDKs). Solution to this is to add a specific constraint to auto-generated target platform.More on PR: https://github.com/bazelbuild/proposals/pull/196Regards,Ivo List
You received this message because you are subscribed to the Google Groups "bazel-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-dev+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-dev/9bd2d56e-1eab-4274-837d-72555b9355acn%40googlegroups.com.
I'm not so fond about this proposal anymore.I found a couple of use-cases that are weird:
- building using java14
what happens is that I need to define both local and host platform to select JDK14 for compilation (the weird part is that I should only prescribe target platform, but if I do so JDK11 gets used, without compiler for JDK14)- bootstrapping with only local JDK:
local JDK is used for compilation (weird part is that I need to use located_on_target_and_host constraint in host platform constraint)The problem seems to be that we should match host execution JDK with target Java toolchain.This can be done by adding a third toolchain type - which is complex and can still use a wrong pair of JDK and toolchain.Another option is to add an attribute to java_toolchain rule, whose value points to the most appropriate java_runtime.This would ensure that for compilation for either target or host, a consistent pair of JDK and toolchains are used. It would decouple JVM used to execute on the execution platform from JDK used to compile for the target.Examples:
- default toolchain11 points to @remote_jdk11//:jdk
- toolchain14 points to @remote_jdk14//:jdk
- boostrap_toolchain can point to @local_jdk//:jdk
Cross-product doesn't really happen, because for each toolchain you have one (or perhaps two JDKs).What do you think?
Sorry for the delays, I've been trying to wrap my head around the issues you've raised here. I am still struggling to understand the root issue. Is it that the Java rules have historically used the locally-installed JDK for local builds, and a remote JDK for remote builds, and we want to maintain that?
The first question I have is, who wants to maintain that behavior? And the second is, can users of Bazel's Java rules be asked to configure this? We currently have the `register_execution_platform` function available in WORKSPACE. Bazel users who utilize both Java rules and remote execution should be able to declare a new execution platform describing their remote execution, and a new hermetic Java toolchain that works on that platform, with the needed constraints to ensure they are selected in tandem. Meanwhile, users of Java rules who do not use remote execution can either use their local JDK for all builds, or configure a hermetic JDK for local builds as well.
Historic behavior aside, my understanding is that the current default is to use a downloaded JDK to run Java compilation (i.e. the host JDK) and a local JVM to run whatever is built. The embedded JDK is only used for running Bazel. This is so that:
- We know what version of javac we are running (this is important because Error Prone uses non-public APIs and Error Prone integration is very popular) and it always works without having to separately download one before you run Bazel
- The built Java binaries run on the local machine
- We can upgrade the JDK used to run Bazel without affecting anyone and cut it down to the minimum
This is in line with Ivo's desire to work out of the box for as many people as possible: Java compilation works (because we download a known-good machinery) and the binaries work because they use a local JVM.The part I don't understand is why we need to "match host execution JDK with target Java toolchain". Does "target Java toolchain" mean the Java runtime version you want the built code to run on?
On Fri, Oct 2, 2020 at 2:09 PM Lukács T. Berki <lbe...@google.com> wrote:Historic behavior aside, my understanding is that the current default is to use a downloaded JDK to run Java compilation (i.e. the host JDK) and a local JVM to run whatever is built. The embedded JDK is only used for running Bazel. This is so that:
- We know what version of javac we are running (this is important because Error Prone uses non-public APIs and Error Prone integration is very popular) and it always works without having to separately download one before you run Bazel
- The built Java binaries run on the local machine
- We can upgrade the JDK used to run Bazel without affecting anyone and cut it down to the minimum
This is in line with Ivo's desire to work out of the box for as many people as possible: Java compilation works (because we download a known-good machinery) and the binaries work because they use a local JVM.The part I don't understand is why we need to "match host execution JDK with target Java toolchain". Does "target Java toolchain" mean the Java runtime version you want the built code to run on?Putting it more simply: matching JavaBuilder with JDK. This seems to be the "correct" way to do it, because JavaBuilder as you said uses non-public API.One use-case that proves this is, currently you can compile for Java14 target while using Java11 for tools on the host only with vanilla_toolchian. You have to set --javabase and --host_javabase to remote JDK14. And this then forces you to use vanilla_toolchain on the host (while you could be using remote JDK11 with proper JavaBuilder). This in a way breaks hermetic compiles.
On Fri, Oct 2, 2020 at 2:43 PM Ivo List <il...@google.com> wrote:On Fri, Oct 2, 2020 at 2:09 PM Lukács T. Berki <lbe...@google.com> wrote:Historic behavior aside, my understanding is that the current default is to use a downloaded JDK to run Java compilation (i.e. the host JDK) and a local JVM to run whatever is built. The embedded JDK is only used for running Bazel. This is so that:
- We know what version of javac we are running (this is important because Error Prone uses non-public APIs and Error Prone integration is very popular) and it always works without having to separately download one before you run Bazel
- The built Java binaries run on the local machine
- We can upgrade the JDK used to run Bazel without affecting anyone and cut it down to the minimum
This is in line with Ivo's desire to work out of the box for as many people as possible: Java compilation works (because we download a known-good machinery) and the binaries work because they use a local JVM.The part I don't understand is why we need to "match host execution JDK with target Java toolchain". Does "target Java toolchain" mean the Java runtime version you want the built code to run on?Putting it more simply: matching JavaBuilder with JDK. This seems to be the "correct" way to do it, because JavaBuilder as you said uses non-public API.One use-case that proves this is, currently you can compile for Java14 target while using Java11 for tools on the host only with vanilla_toolchian. You have to set --javabase and --host_javabase to remote JDK14. And this then forces you to use vanilla_toolchain on the host (while you could be using remote JDK11 with proper JavaBuilder). This in a way breaks hermetic compiles.To recap our VC: if you set --javabase <JVM 14> --host_javabase <JVM 14> you currently get a JavaBuilder that assumes that it runs on JVM 11, which doesn't work. The workaround is to use the --java_toolchain <vanilla builder> so that you get the javac from the JDK 14 and not the one packaged with the default JavaBuilder (which you must use since we don't have one yet for JDK 14). Is this correct?
On Mon, Oct 5, 2020 at 8:56 AM Lukács T. Berki <lbe...@google.com> wrote:Hey Ivo,After a weekend and acquiring a bit (but just a bit) clearer head, here are what I think the fundamental limitations are:
- java_toolchain rules with an embedded javac version X (i.e. JavaBuilder versions) can use any JVM version >= X (Java bytecode should be forward compatible)
- java_toolchain rules that embed knowledge about that particular javac version but which don't embed a javac and which rely on the one supplied by JDK (i.e. the vanilla versions) should probably use only that JDK version X because they generally
Is this correct?
Correct.But this is more of a P2, kind of a problem: support different versions of Java.Let's first just focus to support javac version X, out of the box. The P1 problem is compiling it with "embedded javac version X" +remote_jdk11 JVM and executing with local_jdk JVM.
The most naive way to model these is with exec constraints: we'd make an exec constraint that says "I have Java version X" a java_toolchain embedding javac X would say that it runs on that version or above, whereas a java_toolchain relying on the javac supplied by the JDK would say that it needs that particular version.This gives rise to two kinds of coupling:
- If you want to use javac version X to build your Java code, you put constraints on the Java version that everything else uses on the target platform according to the above rules
- If you want to target a particular Java language version, you are forced to use a java_toolchain that sets that target_version and thus the constraints arising from (1) if you don't have multiple java_toolchains that have the same javac version but different target_version
(2) seems solvable by making target_version not a property of the java_toolchain rule but a configuration flag or something; then java_toolchain would have a property that says "this is the maximum language level I support".If (1) proves to be a problem, we can go with the "attach a java_runtime to a java_toolchain rule" idea.WDYT? This all doesn't cover any migration we may need to do (I didn't think about it yet), but it looks like a reasonable end state to me.
I don't see other ways to solve P1 above, except:- drop/change the requirement - for example using remote_jdk11 JVM to compile and execute by default and provide another predefined platform that uses local_jdk
- add a constraint on one of the default platforms
- attach a java_runtime to a java_toolchain rule
On Mon, Oct 5, 2020 at 12:56 PM Ivo List <il...@google.com> wrote:On Mon, Oct 5, 2020 at 8:56 AM Lukács T. Berki <lbe...@google.com> wrote:Hey Ivo,After a weekend and acquiring a bit (but just a bit) clearer head, here are what I think the fundamental limitations are:
- java_toolchain rules with an embedded javac version X (i.e. JavaBuilder versions) can use any JVM version >= X (Java bytecode should be forward compatible)
- java_toolchain rules that embed knowledge about that particular javac version but which don't embed a javac and which rely on the one supplied by JDK (i.e. the vanilla versions) should probably use only that JDK version X because they generally
Is this correct?Correct.But this is more of a P2, kind of a problem: support different versions of Java.Let's first just focus to support javac version X, out of the box. The P1 problem is compiling it with "embedded javac version X" +remote_jdk11 JVM and executing with local_jdk JVM.The most naive way to model these is with exec constraints: we'd make an exec constraint that says "I have Java version X" a java_toolchain embedding javac X would say that it runs on that version or above, whereas a java_toolchain relying on the javac supplied by the JDK would say that it needs that particular version.This gives rise to two kinds of coupling:
- If you want to use javac version X to build your Java code, you put constraints on the Java version that everything else uses on the target platform according to the above rules
- If you want to target a particular Java language version, you are forced to use a java_toolchain that sets that target_version and thus the constraints arising from (1) if you don't have multiple java_toolchains that have the same javac version but different target_version
(2) seems solvable by making target_version not a property of the java_toolchain rule but a configuration flag or something; then java_toolchain would have a property that says "this is the maximum language level I support".If (1) proves to be a problem, we can go with the "attach a java_runtime to a java_toolchain rule" idea.WDYT? This all doesn't cover any migration we may need to do (I didn't think about it yet), but it looks like a reasonable end state to me.I don't see other ways to solve P1 above, except:- drop/change the requirement - for example using remote_jdk11 JVM to compile and execute by default and provide another predefined platform that uses local_jdkLet's not do this.- add a constraint on one of the default platformsI thought that the "this platform is the same as the one Bazel runs on" constraint is a reasonable one. John, what's the argument against it?
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-dev/CAOu%2B0LWTosWjaW7BaBhyNP5Hupdc%3Ds90CwZfkq-MbD%2Bpb_HrNg%40mail.gmail.com.
I kind of have second thoughts on this solution. The good thing about it, it is simple and easy to implement.Leaving this aside it could introduce some technical dept and with it issues in the future. One such possible issue is when supporting multiple versions of Java. If we hack around constraints to select the right combination, on every next release of Java or our toolchain, somebody will have to hack again. After those "hacks" are implemented it might become hard to remove this constraint from the default platform.
- attach a java_runtime to a java_toolchain ruleAnd this would also mean not registering that java_runtime toolchain in the java_tools repositories, since then you wouldn't be able to guarantee that Bazel doesn't choose that one as the one for the target platform (fwiw, this "additional toolchain accidentally gets selected" issue is a good argument for the "this toolchain is available locally" constraint)
No, we would still register java_runtime toolchain, which would be then used only for execution. Java rules would use java_runtime from java_toolchain for compilation and java_runtime for execution. Nice thing is, that there wouldn't be any host/exec transition in Java rules anymore. In target configuration this would mean local_jdk for execution and remote one for compilation.There is one change (just realised about it while writing) - also in host/exec configuration targets would be executed using local jdk (right now remotejdk is used in host/exec for execution). I don't think this is very problematic (android is an example that heavily depends on this). If it is problematic then we're back at adding a constraint to autoconfigured platforms.About accidental selection of toolchains: toolchains get selected by the order of their appearance, so if local_jdk is on the first place in WORKSPACE suffix, this should be fine. We can also use it in our advantage - i.e. if there is no local jdk, failover to remote jdk.
In addition to the philosophical problem with using a constraint to distinguish the target and host platforms, there's an implementation problem: there is no separate target platform. Currently (in Bazel), the default host platform is `@local_config_platform//:host`, and the default target platform is "whatever --host_platform happens to be set to".
If we add a new default target platform (so we can distinguish it from the default host platform), we lose that second property, which means that anyone currently using `--host_platform` will see behavior changes (and probably will select the wrong JVM, if I am understanding the current proposals correctly). Due to the issues with execution strategy and execution platform selection, my understanding is that many users of remote execution currently set `--host_platform`, especially if they are starting builds on a Mac laptop but executing them on linux remote workers.
I kind of have second thoughts on this solution. The good thing about it, it is simple and easy to implement.Leaving this aside it could introduce some technical dept and with it issues in the future. One such possible issue is when supporting multiple versions of Java. If we hack around constraints to select the right combination, on every next release of Java or our toolchain, somebody will have to hack again. After those "hacks" are implemented it might become hard to remove this constraint from the default platform.
- attach a java_runtime to a java_toolchain ruleAnd this would also mean not registering that java_runtime toolchain in the java_tools repositories, since then you wouldn't be able to guarantee that Bazel doesn't choose that one as the one for the target platform (fwiw, this "additional toolchain accidentally gets selected" issue is a good argument for the "this toolchain is available locally" constraint)
No, we would still register java_runtime toolchain, which would be then used only for execution. Java rules would use java_runtime from java_toolchain for compilation and java_runtime for execution. Nice thing is, that there wouldn't be any host/exec transition in Java rules anymore. In target configuration this would mean local_jdk for execution and remote one for compilation.
There is one change (just realised about it while writing) - also in host/exec configuration targets would be executed using local jdk (right now remotejdk is used in host/exec for execution).
I don't think this is very problematic (android is an example that heavily depends on this). If it is problematic then we're back at adding a constraint to autoconfigured platforms.
About accidental selection of toolchains: toolchains get selected by the order of their appearance, so if local_jdk is on the first place in WORKSPACE suffix, this should be fine. We can also use it in our advantage - i.e. if there is no local jdk, failover to remote jdk.
On Mon, Oct 5, 2020 at 2:27 PM John Cater <jca...@google.com> wrote:In addition to the philosophical problem with using a constraint to distinguish the target and host platforms, there's an implementation problem: there is no separate target platform. Currently (in Bazel), the default host platform is `@local_config_platform//:host`, and the default target platform is "whatever --host_platform happens to be set to".Is this by design or did we just end up doing this "accidentally?"
If we add a new default target platform (so we can distinguish it from the default host platform), we lose that second property, which means that anyone currently using `--host_platform` will see behavior changes (and probably will select the wrong JVM, if I am understanding the current proposals correctly). Due to the issues with execution strategy and execution platform selection, my understanding is that many users of remote execution currently set `--host_platform`, especially if they are starting builds on a Mac laptop but executing them on linux remote workers....and then they build binaries for Linux?
Hey Ivo,After a weekend and acquiring a bit (but just a bit) clearer head, here are what I think the fundamental limitations are:
- java_toolchain rules with an embedded javac version X (i.e. JavaBuilder versions) can use any JVM version >= X (Java bytecode should be forward compatible)
- java_toolchain rules that embed knowledge about that particular javac version but which don't embed a javac and which rely on the one supplied by JDK (i.e. the vanilla versions) should probably use only that JDK version X because they generally
Is this correct?
The most naive way to model these is with exec constraints: we'd make an exec constraint that says "I have Java version X" a java_toolchain embedding javac X would say that it runs on that version or above, whereas a java_toolchain relying on the javac supplied by the JDK would say that it needs that particular version.This gives rise to two kinds of coupling:
- If you want to use javac version X to build your Java code, you put constraints on the Java version that everything else uses on the target platform according to the above rules
- If you want to target a particular Java language version, you are forced to use a java_toolchain that sets that target_version and thus the constraints arising from (1) if you don't have multiple java_toolchains that have the same javac version but different target_version
(2) seems solvable by making target_version not a property of the java_toolchain rule but a configuration flag or something; then java_toolchain would have a property that says "this is the maximum language level I support".If (1) proves to be a problem, we can go with the "attach a java_runtime to a java_toolchain rule" idea.
WDYT? This all doesn't cover any migration we may need to do (I didn't think about it yet), but it looks like a reasonable end state to me.
- attach a java_runtime to a java_toolchain rule
And this would also mean not registering that java_runtime toolchain in the java_tools repositories, since then you wouldn't be able to guarantee that Bazel doesn't choose that one as the one for the target platform (fwiw, this "additional toolchain accidentally gets selected" issue is a good argument for the "this toolchain is available locally" constraint)
On Mon, Oct 5, 2020 at 8:30 AM Lukács T. Berki <lbe...@google.com> wrote:On Mon, Oct 5, 2020 at 2:27 PM John Cater <jca...@google.com> wrote:In addition to the philosophical problem with using a constraint to distinguish the target and host platforms, there's an implementation problem: there is no separate target platform. Currently (in Bazel), the default host platform is `@local_config_platform//:host`, and the default target platform is "whatever --host_platform happens to be set to".Is this by design or did we just end up doing this "accidentally?"This is by design. The original thought was "bazel should default to building for the host platform", so we evolved that to "Bazel should default to building for what the user claims is the the host platform."
If we add a new default target platform (so we can distinguish it from the default host platform), we lose that second property, which means that anyone currently using `--host_platform` will see behavior changes (and probably will select the wrong JVM, if I am understanding the current proposals correctly). Due to the issues with execution strategy and execution platform selection, my understanding is that many users of remote execution currently set `--host_platform`, especially if they are starting builds on a Mac laptop but executing them on linux remote workers....and then they build binaries for Linux?If they haven't set "--platforms" to a more specific value, yes.
On Mon, Oct 5, 2020 at 8:30 AM Lukács T. Berki <lbe...@google.com> wrote:On Mon, Oct 5, 2020 at 2:27 PM John Cater <jca...@google.com> wrote:In addition to the philosophical problem with using a constraint to distinguish the target and host platforms, there's an implementation problem: there is no separate target platform. Currently (in Bazel), the default host platform is `@local_config_platform//:host`, and the default target platform is "whatever --host_platform happens to be set to".Is this by design or did we just end up doing this "accidentally?"This is by design. The original thought was "bazel should default to building for the host platform", so we evolved that to "Bazel should default to building for what the user claims is the the host platform."
If we add a new default target platform (so we can distinguish it from the default host platform), we lose that second property, which means that anyone currently using `--host_platform` will see behavior changes (and probably will select the wrong JVM, if I am understanding the current proposals correctly). Due to the issues with execution strategy and execution platform selection, my understanding is that many users of remote execution currently set `--host_platform`, especially if they are starting builds on a Mac laptop but executing them on linux remote workers....and then they build binaries for Linux?If they haven't set "--platforms" to a more specific value, yes.
- attach a java_runtime to a java_toolchain ruleAnd this would also mean not registering that java_runtime toolchain in the java_tools repositories, since then you wouldn't be able to guarantee that Bazel doesn't choose that one as the one for the target platform (fwiw, this "additional toolchain accidentally gets selected" issue is a good argument for the "this toolchain is available locally" constraint)No, we would still register java_runtime toolchain, which would be then used only for execution. Java rules would use java_runtime from java_toolchain for compilation and java_runtime for execution. Nice thing is, that there wouldn't be any host/exec transition in Java rules anymore. In target configuration this would mean local_jdk for execution and remote one for compilation.There is one change (just realised about it while writing) - also in host/exec configuration targets would be executed using local jdk (right now remotejdk is used in host/exec for execution).I suppose what you are saying here is the same as what John is saying, that the current default is that the host and the target platforms are the same?
I don't think this is very problematic (android is an example that heavily depends on this). If it is problematic then we're back at adding a constraint to autoconfigured platforms.How is Android special?
About accidental selection of toolchains: toolchains get selected by the order of their appearance, so if local_jdk is on the first place in WORKSPACE suffix, this should be fine. We can also use it in our advantage - i.e. if there is no local jdk, failover to remote jdk.Relying on the order the toolchains are registered in looks like a bit of a hack, doesn' it?
@Ulf: that's a nice principle, but what do you think about the difference between "any JDK fulfilling these constraints that Bazel can provide" and "the JDK that is known to be installed in this environment without Bazel taking extra steps?" If you don't make this difference, there is no guarantee that instead of the locally installed JDK, Bazel will choose one as the target JDK that happens to fulfill the same constraints and then the binary you built will not be executable since the wrapper script references the wrong thing.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-dev/CAOu%2B0LU9jibAa4dwDx_USE5q9MXVoQiJrq8UmfTpAjMph49gAw%40mail.gmail.com.
On Mon, Oct 5, 2020 at 2:35 PM 'Lukács T. Berki' via bazel-dev <baze...@googlegroups.com> wrote:@Ulf: that's a nice principle, but what do you think about the difference between "any JDK fulfilling these constraints that Bazel can provide" and "the JDK that is known to be installed in this environment without Bazel taking extra steps?" If you don't make this difference, there is no guarantee that instead of the locally installed JDK, Bazel will choose one as the target JDK that happens to fulfill the same constraints and then the binary you built will not be executable since the wrapper script references the wrong thing.I'm afraid I don't follow your argument. If the two JDKs are equivalent, they should have the same constraints. If not, then not.