remotely-built `java_binary`s can't run locally - bazel

I'm using Bazel 0.29.1 with remote execution to build java_binary targets. They are straightforward targets with a few sources and deps, e.g.
java_binary(
name = "foo",
main_class = "my.foo",
runtime_deps = [
"//my/foo",
"//third_party/jvm/org/apache/logging/log4j:log4j_core",
],
)
The remote execution config is using rbe_autoconfig from Bazel toolchains 0.29.8 and the default build container.
The binary builds fine with bazel --config=remote build //:foo. However, it fails when run with bazel --config=remote run //:foo:
/home/kgessner/.cache/bazel/_bazel_kgessner/[snip]/foo: line 359: /usr/lib/jvm/java-8-openjdk-amd64/bin/java: No such file or directory
The java_binary wrapper/launcher has the wrong java path: /usr/lib/jvm/java-8-openjdk-amd64/bin/java is the path to java in the build container, but not locally.
I can't find the right combination of java flags to make this work: build remotely but use the local JRE when it's run. What's the trick?

Sounds like a bug. Could you please file it on GitHub?

Related

Building uWSGI with bazel

I have a simple example package served with uwsgi, that I'm trying to switch from building with makefile rules to bazel.
The WORKSPACE file that, in addition to loading rules_python and other default stuff (registering toolchains) also gets uwsgi as follows
load("#bazel_tools//tools/build_defs/repo:git.bzl", "new_git_repository")
new_git_repository(
name = "uwsgi",
remote = "git#github.com:unbit/uwsgi.git",
commit = "ca8bc6acc98b2c062b5b00668acd851e210fcbca",
build_file_content = """
...
"""
)
What I can't quite get my head around is how to build uwsgi. Technically, you're building a C package. However, I'm building it using the provided python script (uwsgiconfig.py) and my configuration file (I'll call it myconf.ini that I manually copy into the uwsgi/buildconf/ directory then build the package using python uwsgiconfig.py --build myconfig
This is the stage I'm (hopefully) trying to accomplish with bazel. However, I'm not sure if I should be using a cc_binary or a py_binary rule for to build uwsgi.
Any assistance is greatly appreciated.

How to avoid deleting cached files after build in Bazel

I have a genrule in Bazel that is supposed to manipulate some files. I think I'm not accessing these files by the correct path, so I want to look at the directory structure that Bazel is creating so I can debug.
I added some echo statements to my genrule and I can see that Bazel is working in the directory /home/lyft/.cache/bazel/_bazel_lyft/8de0a1069de8d166c668173ca21c04ae/sandbox/linux-sandbox/1/execroot/. However, after Bazel finishes running, this directory is gone, so I can't look at the directory structure.
How can I prevent Bazel from deleting its temporary files so that I can debug what's happening?
Since this question is a top result for "keep sandbox files after build bazel" Google search and it wasn't obvious for me from the accepted answer, I feel the need to write this answer.
Short answer
Use --sandbox_debug. If this flag is passed, Bazel will not delete the files inside the sandbox folder after the build finishes.
Longer answer
Run bazel build with --sandbox_debug option:
$ bazel build mypackage:mytarget --sandbox_debug
Then you can inspect the contents of the sandbox folder for the project.
To get the location of the sandbox folder for current project, navigate to project and then run:
$ bazel info output_base
/home/johnsmith/.cache/bazel/_bazel_johnsmith/d949417420413f64a0b619cb69f1db69 # output will be something like this
Inside that directory there will be sandbox folder.
Possible caveat: (I'm NOT sure about this but) It's possible that some of the files are missing in sandbox folder, if you previously ran a build without --sandbox_debug flag and it partially succeeded. The reason is Bazel won't rerun parts of the build that already succeeded, and consequently the files corresponding to the successful build parts might not end up in the sandbox.
If you want to make sure all the sandbox files are there, clean the project first using either bazel clean or bazel clean --expunge.
You can use --spawn_strategy=standalone.
You can also use --sandbox_debug to see which directories are mounted to the sandbox.
You can also set the genrule's cmd to find . > $# to debug what's available to the genrule.
Important: declare all srcs/outs/tools that the genrule will read/write/use, and use $(location //label/of:target) to look up their path. Example:
genrule(
name = "x1",
srcs = ["//foo:input1.txt", "//bar:generated_file"],
outs = ["x1out.txt", "x1err.txt"],
tools = ["//util:bin1"],
cmd = "$(location //util:bin1) --input1=$(location //foo:input1.txt) --input2=$(location //bar:generated_file) --some_flag --other_flag >$(location x1out.txt) 2>$(location x1err.txt)",
)

Local cache for bazel remote repos

We are using codeship to run CI for a C++ project. Our CI build consists of a Docker image into which we install system dependencies, then a bazel build step that builds our tests.
Our bazel WORKSPACE file pulls in various external dependencies, such as gtest:
new_http_archive(
name = "gtest",
url = "https://github.com/google/googletest/archive/release-1.7.0.zip",
build_file = "thirdparty/gtest.BUILD",
strip_prefix = "googletest-release-1.7.0",
sha256 = "b58cb7547a28b2c718d1e38aee18a3659c9e3ff52440297e965f5edffe34b6d0",
)
During CI builds, a lot of time is spent downloading these files. Is it possible to set up Bazel to use a local cache for these archives?
I think Bazel already caches external repositories in the output_base (It should, if not it's a bug worth reporting). Is it an option for you to keep the cache hot in the docker container? E.g. by fetching the code and running bazel fetch //... or some more specific target? Note you can also specify where is bazel`s output_base by using bazel --output_base=/foo build //.... You might find this doc section relevant.
[EDIT: Our awesome Kristina comes to save the day]:
You can use --experimental_repository_cache=/path/to/some/dir
Does this help?

Get sourcecode into Jenkins WORKSPACE subdirectory

Is it possible to configure Jenkins to get source code into a subdirectory of a %WORKSPACE%? Right now the source gets pulled into %WORKSPACE% and for the build output I explicitly specify a directory outside of the %WORKSPACE%.
Ideally I would like to have something similar to this:
%WORKSPACE%\source for source code and %WORKSPACE%\artifacts for build outputs. Is it possible to have this configuration?
Create a 'run batch command' build step and use xcopy, this is presuming jenkins is running on a Windows machine, if it's a deployment directory then make it a post build step.
cd c:/
xcopy /Y "c:/program files 86/junkies/workspace/app" "c:/path to new directory"
This is just a guess at your directories, replace with correct ones, the /Y forces it to be overwritten every time it's copied.

Is there a way to use just build command instead of ant build while using ant scripts?

I am using Apache Ant scripts for building a web application. I have written some targets in the build.xml file and the script is running fine. I remember using just "build" command to run ant build instead of "ant build". Can anyone tell me how is that achieved? I was a bit curious on this.
There's no built in "build" command. You could create a simple script file called "build" in the same directory that launched the ant build.
Create a text file with this as the contents:
ant build
In windows save this as a file called build.bat then you can just type build from the command line to start your build.
On unix or linux, save the file as build, then make it executable (with chmod +x build). You'll need to type ./build to get it to run.
I don't think there's a lot of value doing this to replace the simple case of ant build, but if you have to regularly run a build that has multiple targets, or need to pass in certain system variables then it could come in useful.
Maybe your are remembering typing "ant" instead of "ant build" in the past. This is possible to setup. You just need to set default attribute on the root project element in your Ant script to the name of the target you want invoked when an explicit target isn't specified.
For instance...
<project name="myproj" default="build">
...
</project>

Resources