It would be great if there were a wrapper script (let's call it "bazelw") that downloads a specific version (which could be the latest version) of bazel, and executes the given command with the downloaded copy of bazel. I'm thinking of something similar to the gradle wrapper ("gradlew"):
https://docs.gradle.org/current/userguide/gradle_wrapper.html
This would make it more palatable to use Bazel in opensource projects, as it would reduce the number of steps required for users to setup their machine. It would also make the build even more reliable by ensuring that a specific version (encoded in the wrapper) is used, rather than whatever version of bazel happens to installed on the user's machine (which may be incompatible with the BUILD/WORKSPACE).
Is this not more a thing you would like to do with docker?
Docker is ideal for remote builds (like a continuous integration machine), but it is a very heavy-weight solution for ordinary developers. It's also not compatible with all environments (e.g. for developers working on Cloud 9 or other hosted environments that are, themselves, running in Docker and, therefore, incapable of running Docker). So I think there is still a reason to desire something like this.
I swear we had a bug open before to create a gradlew-similar wrapper script for Bazel, but now I can't find it. I think this is a good idea.
The duplicate bug is #373 which is wrongly triaged, let keep this bug which is more complete and close #373
FYI, I've started to sketch out just such a wrapper script:
https://github.com/michaelsafyan/bazel-wrapper
(Feel free to crib from that for going forward).
FYI, there is also dazel: https://github.com/nadirizr/dazel
This is _still_ really important, 2 years later. There needs to be a standard way to version bazel itself, like this proposes.
It won't be sufficient to just download a specific version of Bazel. You will also want to get the rule sets at the versions the Bazel version was tested against. We are thinking about better versioning across core Bazel and the rules, but there may not be anything new for a quarter or so.
@philwo made a wrapper here: https://github.com/philwo/bazelisk
While we wait for an officially support solution, this isn't too difficult to implement on your own:
#!/bin/bash
# This script is a wrapper for Bazel that controls version pinning for the
# Bazel client binary. This allows us to pin the required Bazel version
# for each commit.
#
# It works by downloading the pinned version of the Bazel binary to the
# host (if it isn't already cached) and transparently exec'ing it with
# the provided Bazel args. To the end user it should appear no different
# than calling Bazel directly
BAZEL_VERSION="0.23.2"
BAZEL_FILENAME="bazel-${BAZEL_VERSION}-linux-x86_64"
BAZEL_LOCAL_DIR="${HOME}/.cache/bazel-versions"
BAZEL_LOCAL_LOCK="${BAZEL_LOCAL_DIR}/.lock"
BAZEL_LOCAL_BINARY="${BAZEL_LOCAL_DIR}/${BAZEL_FILENAME}"
BAZEL_BINARY_URL="https://github.com/bazelbuild/bazel/releases/download/${BAZEL_VERSION}/${BAZEL_FILENAME}"
# Check if pinned bazel version is cached
if ! [ -x "${BAZEL_LOCAL_BINARY}" ]; then
mkdir -p "${BAZEL_LOCAL_DIR}"
(
flock 200
if ! [ -x "${BAZEL_LOCAL_BINARY}" ]; then
>&2 echo "Downloading Bazel version ${BAZEL_VERSION}"
curl -s -L "${BAZEL_BINARY_URL}" --output ${BAZEL_LOCAL_BINARY}
chmod +x "${BAZEL_LOCAL_BINARY}"
fi
) 200>"${BAZEL_LOCAL_LOCK}"
fi
exec "${BAZEL_LOCAL_BINARY}" "$@"
We check this into our git repo with a filename of bazel
and have devs/ci add it to their PATH
. It makes upgrading bazel versions way less of a headache. If you want to be a good neighbor, replace the URL with a path to your own blob store (ex GCS).
$ bazel version
Downloading Bazel version 0.23.2
Build label: 0.23.2
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Mon Mar 11 16:47:03 2019 (1552322823)
Build timestamp: 1552322823
Build timestamp as int: 1552322823
@ebracho Bazelisk is the "official" solution - it will move into the bazelbuild org, soon. Any reason you didn't consider using it? (Just want to make sure that it's as usable as possible for all of you. :))
(Co-worker of @ebracho here)
We don't want to rely on github, so we actually reupload bazel binaries into our object store and pull it from there, as our CI system is fairly transient, and we don't want builds to fail just cause of network/github issues. If bazelisk was able to be told a specific url, or ideally even a command to run to pull it, that would probably be a viable solution for us.
@philwo To add to that, until now I didn't realize that Bazelisk had a python version we could check into our own repo (as opposed to provisioning every environment with an external dependency), which was the main deciding factor. I'm glad to hear that Bazelisk is being adopted as the official solution though! Our script is concise but fairly limited (e.g. no macOS/windows support).
bazelisk
is now in the bazelbuild GitHub org, and is the official wrapper to version your Bazel binaries.
Most helpful comment
This is _still_ really important, 2 years later. There needs to be a standard way to version bazel itself, like this proposes.