#!/bin/bash # Copyright 2014 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This script bootstraps building a Bazel binary without Bazel then # use this compiled Bazel to bootstrap Bazel itself. It can also # be provided with a previous version of Bazel to bootstrap Bazel # itself. # The resulting binary can be found at output/bazel. set -o errexit cd $[dirname $0] # Set the default verbose mode in buildenv.sh so that we do not display command # output unless there is a failure. We do this conditionally to offer the user # a chance of overriding this in case they want to do so. : $(VERBOSE:=no) source scripts/bootstrap/buildenv.sh proc usage { test -n $(1:-compile) && echo "Invalid command(s): $1" > !2 echo "syntax: $0 [command[,command]* [BAZEL_BIN [BAZEL_SUM]]]" > !2 echo " General purpose commands:" > !2 echo " compile = compile the bazel binary (default)" > !2 echo " Commands for developers:" > !2 echo " all = compile,determinism,test" > !2 echo " determinism = test for stability of Bazel builds" > !2 echo " srcs = test that //:srcs contains all the sources" > !2 echo " test = run the full test suite of Bazel" > !2 exit 1 } proc parse_options { var keywords = '"(compile|all|determinism|bootstrap|srcs|test)'" setglobal COMMANDS = $(1:-compile) [[ "${COMMANDS}" =~ ^$keywords(,$keywords)*$ ]] || usage @Argv setglobal DO_COMPILE = '' setglobal DO_CHECKSUM = '' setglobal DO_FULL_CHECKSUM = '1' setglobal DO_TESTS = '' setglobal DO_SRCS_TEST = '' [[ "${COMMANDS}" =~ (compile|all) ]] && setglobal DO_COMPILE = '1' [[ "${COMMANDS}" =~ (bootstrap|determinism|all) ]] && setglobal DO_CHECKSUM = '1' [[ "${COMMANDS}" =~ (bootstrap) ]] && setglobal DO_FULL_CHECKSUM = '' [[ "${COMMANDS}" =~ (srcs|all) ]] && setglobal DO_SRCS_TEST = '1' [[ "${COMMANDS}" =~ (test|all) ]] && setglobal DO_TESTS = '1' setglobal BAZEL_BIN = $(2:-"bazel-bin/src/bazel") setglobal BAZEL_SUM = $(3:-"x") } parse_options $(@) mkdir -p output : $(BAZEL:=${2-}) # # Create an initial binary so we can host ourself # if test ! -x $(BAZEL) { display "$INFO You can skip this first step by providing a path to the bazel binary as second argument:" display "$INFO $0 $(COMMANDS) /path/to/bazel" new_step 'Building Bazel from scratch' source scripts/bootstrap/compile.sh # The DO_COMPILE flow will actually create the bazel binary and set BAZEL. setglobal DO_COMPILE = '1' } # # Bootstrap bazel using the previous bazel binary = release binary # if test $(EMBED_LABEL-x) = "x" { # Add a default label when unspecified setglobal git_sha1 = $[git_sha1] setglobal EMBED_LABEL = ""$[get_last_version] (@$(git_sha1:-non-git))"" } if [[ $PLATFORM == "darwin" ]] && \ xcodebuild -showsdks !2 > /dev/null | grep -q '\-sdk iphonesimulator' { setglobal EXTRA_BAZEL_ARGS = ""$(EXTRA_BAZEL_ARGS-) --define IPHONE_SDK=1"" } source scripts/bootstrap/bootstrap.sh if test $DO_COMPILE { new_step 'Building Bazel with Bazel' display "." log "Building output/bazel" bazel_build "src:bazel$(EXE_EXT)" \ || fail "Could not build Bazel" setglobal bazel_bin_path = ""$[get_bazel_bin_path]/src/bazel$(EXE_EXT)"" test -e $bazel_bin_path \ || fail "Could not find freshly built Bazel binary at '$bazel_bin_path'" cp -f $bazel_bin_path "output/bazel$(EXE_EXT)" \ || fail "Could not copy '$bazel_bin_path' to 'output/bazel$(EXE_EXT)'" chmod 0755 "output/bazel$(EXE_EXT)" setglobal BAZEL = ""$[pwd]/output/bazel$(EXE_EXT)"" } # # Output is deterministic between two bootstrapped bazel binary using the actual tools and the # released binary. # if test $DO_CHECKSUM { new_step "Determinism test" if test ! -f $(BAZEL_SUM:-x) { setglobal BAZEL_SUM = 'bazel-out/bazel_checksum' log "First build" bootstrap_test $(BAZEL) $(BAZEL_SUM) } else { setglobal BOOTSTRAP = $(BAZEL) } if test $(BAZEL_SUM) != "$(OUTPUT_DIR)/bazel_checksum" { cp $(BAZEL_SUM) $(OUTPUT_DIR)/bazel_checksum } if test $DO_FULL_CHECKSUM { log "Second build" bootstrap_test $(BOOTSTRAP) bazel-out/bazel_checksum log "Comparing output" shell {diff -U 0 $(OUTPUT_DIR)/bazel_checksum bazel-out/bazel_checksum > !2} \ || fail "Differences detected in outputs!" } } # # Test that //:srcs contains all the sources # if test $DO_SRCS_TEST { new_step "Checking that //:srcs contains all the sources" log "Querying //:srcs" $(BAZEL) query 'kind("source file", deps(//:srcs))' !2 >/dev/null \ | grep -v '^@' \ | sed -e 's|^//||' | sed 's|^:||' | sed 's|:|/|' \ | sort -u >"$(OUTPUT_DIR)/srcs-query" log "Finding all files" # SRCS_EXCLUDES can be overriden to adds some more exceptions for the find # commands (for CI systems). setglobal SRCS_EXCLUDES = $(SRCS_EXCLUDES-XXXXXXXXXXXXXX1268778dfsdf4) # See file BUILD for the list of grep -v exceptions. # tools/defaults package is hidden by Bazel so cannot be put in the srcs. find . -type f | sed 's|./||' \ | grep -v '^bazel-' | grep -v '^WORKSPACE.user.bzl' \ | grep -v '^\.' | grep -v '^out/' | grep -v '^output/' \ | grep -Ev $(SRCS_EXCLUDES) \ | grep -v '^tools/defaults/BUILD' \ | sort -u >"$(OUTPUT_DIR)/srcs-find" log "Diffing" setglobal res = $[diff -U 0 "$(OUTPUT_DIR)/srcs-find" "$(OUTPUT_DIR)/srcs-query" | sed 's|^-||' | grep -Ev '^(@@|\+\+|--)' || true] if test -n $(res) { fail "//:srcs filegroup do not contains all the sources, missing: $(res)" } } # # Tests # if test $DO_TESTS { new_step "Running tests" display "." setglobal ndk_target = $[get_bind_target //external:android_ndk_for_testing] setglobal sdk_target = $[get_bind_target //external:android_sdk_for_testing] if test $ndk_target = "//:dummy" -o $sdk_target = "//:dummy" { display "$WARNING Android SDK or NDK are not set in the WORKSPACE file. Android tests will not be run." } test -n $JAVAC_VERSION || get_java_version if [[ ! "${BAZEL_TEST_FILTERS-}" =~ "-jdk8" ]] { if test "8" -gt $(JAVAC_VERSION#*.) || test $(JAVA_VERSION) = "1.7" { display "$WARNING Your version of Java is lower than 1.8!" display "$WARNING Deactivating Java 8 tests, please use a JDK 8 to fully" display "$WARNING test Bazel." if test -n $(BAZEL_TEST_FILTERS-) { setglobal BAZEL_TEST_FILTERS = ""$(BAZEL_TEST_FILTERS),-jdk8"" } else { setglobal BAZEL_TEST_FILTERS = '"-jdk8'" } } } $BAZEL --bazelrc=$(BAZELRC) --nomaster_bazelrc \ $(BAZEL_DIR_STARTUP_OPTIONS) \ test \ --test_tag_filters="$(BAZEL_TEST_FILTERS-)" \ --build_tests_only \ --nolegacy_bazel_java_test \ --define JAVA_VERSION=$(JAVA_VERSION) \ $(EXTRA_BAZEL_ARGS) \ -k --test_output=errors //src/... //third_party/ijar/... //scripts/... \ || fail "Tests failed" } clear_log display "Build successful! Binary is here: $(BAZEL)"