/CC @ekuefler
Repository_ctx exposes this attribute already, by providing SkylarkOS class:
/** A Skylark structure to deliver information about the system we are running on. */
@Immutable
@SkylarkModule(
  name = "repository_os",
  category = SkylarkModuleCategory.NONE,
  doc = "Various data about the current platform Bazel is running on."
)
final class SkylarkOS {
In some cases regular (non repository) rule also requires access to this information. Say to GWT compilation rule, classpath has to be constructed:
https://github.com/GerritCodeReview/gerrit/blob/master/tools/bzl/gwt.bzl#L149
cmd = "external/local_jdk/bin/java %s -Dgwt.normalizeTimestamps=true -cp %s %s -war %s -deploy %s " % (
    " ".join(ctx.attr.jvm_args),
    ":".join(paths),
    GWT_COMPILER,
    output_dir,
    deploy_dir,
  )
But, with hard coded class path delimiter:
    ":".join(paths),
we would end up with non-portable command, that would fail on that another operating system (that expects the delimiter to be ;) with error, like main class for GWT compiler isn't found or some such.
I notice that the Scala rules seem to have the same issue: https://github.com/bazelbuild/rules_scala/blob/6e1561e077e2f902d53cc934d4f6f2056efa0400/scala/scala.bzl#L137
Indeed. Looks like nobody had ever tried to build Scala with Bazel on that other operating system.
Though isn't it an even more significant issue that many Skylark rules (including both Scala and GWT) use Linux commands like cd, cp, mkdir, etc? Unless Bazel's doing some sort of fancy emulation I can't quite see how it would be possible for Skylark rules to support windows without having a lot of dedicated work to do so for each rule.
It's all there and is called MSYS. There is even chocolatey Bazel package that bundles all prerequisites for you:
Anyway, if you install all that, and clone the latest Gerrit Code Review, and try to build GWT module:
  $ bazel build gerrit-gwtui:ui_optdbg
it's failing to detect GWT compiler because of wrong delimiter char in class path construction.
@damienmg @dslomov @aehlig
What is needed/missing to implement that feature? This prevents Gerrit Code Review (and other projects) to write platform independent Skylark rules.
what is this request for? AFAICT ';' vs ':' is only relevant for Windows. Do we have a need to create a windows build of gerrit?
Yes. It's a long-standing issue to support Windows. Gerrit supported this platform but that support was lost after Buck migration. We were hoping to get it back with move to Bazel.
+1 on being able to tell OS in a skylark rule.
We might need to do things like choose between .sh and .bat depending on the OS. The native Java rules need to do this so skylark rules should be able to as well.
/CC @meteorcloudy @damienmg
So, I found a simple workaround for my original issue. It's already now exposed in Skylark the platform specific path separator: ctx.configuration.host_path_separator.
But now I'm hitting a completely different issue: the constructed classpath (and thus the command line) to invoke GWT compiler is too long:
 cmd = "external/local_jdk/bin/java %s -Dgwt.normalizeTimestamps=true -classpath %s %s -war %s -deploy %s " % (
    " ".join(ctx.attr.jvm_args),
    ctx.configuration.host_path_separator.join(paths),
    GWT_COMPILER,
    output_dir,
    deploy_dir,
  )
And the command produced doesn't work on MSYS: [1]. I'm running it with:
 ctx.actions.run_shell(
    inputs = list(deps) + ctx.files._jdk + ctx.files._zip + gwt_user_agent_modules,
    outputs = [output_zip],
    mnemonic = "GwtBinary",
    progress_message = "GWT compiling " + output_zip.short_path,
    command = cmd,
  )
I think one workaround is to construct a classpath.jar with artificial MANIFEST.MF (Class-Path: this.jar that.jar other.jar), similarly to something that was done in #2242, but all this in my custom gwt.bzl Skylark rule?
Another hack would be to copy (or link) all files in some directory and then use wildcard as the classpath: a l谩: java -cp libs/*.
I'm removing the "Windows" label because this is feature request is independent of platforms.
As I understand it, retrieving the execution platform isn't the real issue.
The real issue is to write platform-independent skylark rules.
Looking at it like that we have at least two options:
Expose a ctx.os field. I think this approach won't work. It'd require Bazel to know at analysis-time what execution platform it'll send the action to. In a potentially mixed remote execution system (with multiple execution platforms) this is impractical to know before execution-time.
Support something like an execution-time select() on platform constraints: allow the skylark rule author to write platform-specific actions, and let Bazel choose the right one at execution-time. I think this is the right solution.
AFAIK Bazel supports neither of these today. Nor does it yet have a notion of execution platform(s) (where actions run) as opposed to host platforms (where Bazel itself runs). @katre's and his team's work fall into this domain, he may know more about this.
One more thing: the way I envision it, the rule could create entirely different action graph fragments for different platforms, producing different artifacts, while the rest of the rule logic (i.e. computing providers) could be the same or mostly the same.
The full and complete answer is to use toolchains and platforms.
By defining the appropriate toolchains for Linux, Windows, whatever other system GWT can be compiled on, you can properly handle the platform-specific parts.
There may be a need for some more basic toolchain type built in to Bazel, which defines things like path separators, and executable extensions. It's tricky to figure out exactly what would need to be in there, however, so I don't want to start implementing too early.
Currently, select() and config_setting() do understand platforms and constraints, but only on the target platform, not the execution platform. We could consider implementing config_settings for execution platform constraints, which would then allow other ways to configure builds, but this will quickly run into problems when people try to use your rules on new systems. Toolchains are designed so that other people can add toolchains for new platforms and the rules just work. Select cannot handle that, so any attempt to build your project on a new platform would require re-writing the select statements.
@katre : thanks for the detailed answer!
@davido: a workaround I came up with is to smuggle the platform information into the rule via an attribute whose value you fill using select(). Then in the rule implementation you can instantiate Windows- or Linux-specific actions based on the attribute's value.
@laszlocsomor: thanks for this suggestion. Is that any better, that just use ctx.configuration.host_path_separator as mentioned in my previous comment?
@davido : i don't think it's better.
Related feature request: https://github.com/bazelbuild/bazel/issues/6017
Most helpful comment
+1 on being able to tell OS in a skylark rule.
We might need to do things like choose between
.shand.batdepending on the OS. The native Java rules need to do this so skylark rules should be able to as well.