blob: cc09784c1d851dd428c8cd6b5b77d553a192b284 [file] [log] [blame]
#!/usr/bin/env bash
# Copyright 2016 The TensorFlow 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.
# ==============================================================================
#
# Usage:
# ci_parameterized_build.sh
#
# The script obeys the following required environment variables:
# TF_BUILD_CONTAINER_TYPE: (CPU | GPU | ANDROID | ANDROID_FULL)
# TF_BUILD_PYTHON_VERSION: (PYTHON2 | PYTHON3 | PYTHON3.5)
# TF_BUILD_IS_PIP: (NO_PIP | PIP | BOTH)
#
# The below environment variable is required, but will be deprecated together
# with TF_BUILD_MAVX and both will be replaced by TF_BUILD_OPTIONS.
# TF_BUILD_IS_OPT: (NO_OPT | OPT)
#
# Note:
# 1) Certain combinations of parameter values are regarded
# as invalid and will cause the script to exit with code 0. For example:
# NO_OPT & PIP (PIP builds should always use OPT)
# ANDROID & PIP (Android and PIP builds are mutually exclusive)
#
# 2) TF_BUILD_PYTHON_VERSION is set to PYTHON3, the build will use the version
# pointed to by "which python3" on the system, which is typically python3.4. To
# build for python3.5, set the environment variable to PYTHON3.5
#
#
# Additionally, the script follows the directions of optional environment
# variables:
# TF_BUILD_DRY_RUN: If it is set to any non-empty value that is not "0",
# the script will just generate and print the final
# command, but not actually run it.
# TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS:
# String appended to the content of CI_DOCKER_EXTRA_PARAMS
# TF_BUILD_APPEND_ARGUMENTS:
# Additional command line arguments for the bazel,
# pip.sh or android.sh command
# TF_BUILD_MAVX: (Soon to be deprecated, use TF_BUILD_OPTIONS instead)
# (unset | MAVX | MAVX2)
# If set to MAVX or MAVX2, will cause bazel to use the
# additional flag --copt=-mavx or --copt=-mavx2, to
# perform AVX or AVX2 builds, respectively. This requires
# AVX- or AVX2-compatible CPUs.
# TF_BUILD_BAZEL_TARGET:
# Used to override the default bazel build target:
# //tensorflow/... -//tensorflow/compiler
# TF_BUILD_BAZEL_CLEAN:
# Will perform "bazel clean", if and only if this variable
# is set to any non-empty and non-0 value
# TF_BAZEL_BUILD_ONLY:
# If it is set to any non-empty value that is not "0", Bazel
# will only build specified targets
# TF_GPU_COUNT:
# Run this many parallel tests for serial builds.
# For now, only can be edited for PIP builds.
# TODO(gunan): Find a way to pass this environment variable
# to the script bazel runs (using --run_under).
# TF_BUILD_TEST_TUTORIALS:
# If set to any non-empty and non-0 value, will perform
# tutorials tests (Applicable only if TF_BUILD_IS_PIP is
# PIP or BOTH).
# See builds/test_tutorials.sh
# TF_BUILD_INTEGRATION_TESTS:
# If set this will perform integration tests. See
# builds/integration_tests.sh.
# TF_BUILD_RUN_BENCHMARKS:
# If set to any non-empty and non-0 value, will perform
# the benchmark tests (see *_logged_benchmark targets in
# tools/test/BUILD)
# TF_BUILD_OPTIONS:
# (FASTBUILD | OPT | OPTDBG | MAVX | MAVX2_FMA | MAVX_DBG |
# MAVX2_FMA_DBG)
# Use the specified configurations when building.
# When set, overrides TF_BUILD_IS_OPT and TF_BUILD_MAVX
# options, as this will replace the two.
# TF_SKIP_CONTRIB_TESTS:
# If set to any non-empty or non-0 value, will skip running
# contrib tests.
# TF_NIGHTLY:
# If this run is being used to build the tf_nightly pip
# packages.
# TF_CUDA_CLANG:
# If set to 1, builds and runs cuda_clang configuration.
# Only available inside GPU containers.
#
# This script can be used by Jenkins parameterized / matrix builds.
# Helper function: Convert to lower case
to_lower () {
echo "$1" | tr '[:upper:]' '[:lower:]'
}
# Helper function: Strip leading and trailing whitespaces
str_strip () {
echo -e "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
}
# Helper function: Exit on failure
die () {
echo $@
exit 1
}
##########################################################
# Default configuration
CI_BUILD_DIR="tensorflow/tools/ci_build"
# Command to call when Docker is available
DOCKER_MAIN_CMD="${CI_BUILD_DIR}/ci_build.sh"
# Command to call when Docker is unavailable
NO_DOCKER_MAIN_CMD="${CI_BUILD_DIR}/builds/configured"
# Additional option flags to apply when Docker is unavailable (e.g., on Mac)
NO_DOCKER_OPT_FLAG="--genrule_strategy=standalone"
DO_DOCKER=1
# Helpful flags:
# --test_summary=detailed: Tell us more about which targets are being built
# --keep_going: Don't stop at the first failure; tell us all the failures
# --build_tests_only: Don't build targets depended on by tests if the test is
# disabled. Also saves some compilation time. Otherwise,
# tries to build everything.
BAZEL_TEST_FLAGS="--test_summary=detailed --build_tests_only --keep_going"
BAZEL_BUILD_FLAGS="--keep_going"
BAZEL_CMD="bazel test ${BAZEL_TEST_FLAGS}"
BAZEL_BUILD_ONLY_CMD="bazel build ${BAZEL_BUILD_FLAGS}"
BAZEL_CLEAN_CMD="bazel clean"
PIP_CMD="${CI_BUILD_DIR}/builds/pip.sh"
PIP_TEST_TUTORIALS_FLAG="--test_tutorials"
PIP_INTEGRATION_TESTS_FLAG="--integration_tests"
ANDROID_CMD="${CI_BUILD_DIR}/builds/android.sh"
ANDROID_FULL_CMD="${CI_BUILD_DIR}/builds/android_full.sh"
TF_GPU_COUNT=${TF_GPU_COUNT:-8}
PARALLEL_GPU_TEST_CMD='//tensorflow/tools/ci_build/gpu_build:parallel_gpu_execute'
BENCHMARK_CMD="${CI_BUILD_DIR}/builds/benchmark.sh"
EXTRA_PARAMS=""
BAZEL_TARGET="//tensorflow/... -//tensorflow/compiler/..."
if [[ -n "$TF_SKIP_CONTRIB_TESTS" ]]; then
BAZEL_TARGET="${BAZEL_TARGET} -//tensorflow/contrib/..."
fi
TUT_TEST_DATA_DIR="/tmp/tf_tutorial_test_data"
##########################################################
echo "Parameterized build starts at: $(date)"
echo ""
START_TIME=$(date +'%s')
# Convert all the required environment variables to lower case
TF_BUILD_CONTAINER_TYPE=$(to_lower ${TF_BUILD_CONTAINER_TYPE})
TF_BUILD_PYTHON_VERSION=$(to_lower ${TF_BUILD_PYTHON_VERSION})
TF_BUILD_IS_OPT=$(to_lower ${TF_BUILD_IS_OPT})
TF_BUILD_IS_PIP=$(to_lower ${TF_BUILD_IS_PIP})
if [[ ! -z "${TF_BUILD_MAVX}" ]]; then
TF_BUILD_MAVX=$(to_lower ${TF_BUILD_MAVX})
fi
# Print parameter values
echo "Required build parameters:"
echo " TF_BUILD_CONTAINER_TYPE=${TF_BUILD_CONTAINER_TYPE}"
echo " TF_BUILD_PYTHON_VERSION=${TF_BUILD_PYTHON_VERSION}"
echo " TF_BUILD_IS_OPT=${TF_BUILD_IS_OPT}"
echo " TF_BUILD_IS_PIP=${TF_BUILD_IS_PIP}"
echo "Optional build parameters:"
echo " TF_BUILD_DRY_RUN=${TF_BUILD_DRY_RUN}"
echo " TF_BUILD_MAVX=${TF_BUILD_MAVX}"
echo " TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="\
"${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}"
echo " TF_BUILD_APPEND_ARGUMENTS=${TF_BUILD_APPEND_ARGUMENTS}"
echo " TF_BUILD_BAZEL_TARGET=${TF_BUILD_BAZEL_TARGET}"
echo " TF_BUILD_BAZEL_CLEAN=${TF_BUILD_BAZEL_CLEAN}"
echo " TF_BUILD_TEST_TUTORIALS=${TF_BUILD_TEST_TUTORIALS}"
echo " TF_BUILD_INTEGRATION_TESTS=${TF_BUILD_INTEGRATION_TESTS}"
echo " TF_BUILD_RUN_BENCHMARKS=${TF_BUILD_RUN_BENCHMARKS}"
echo " TF_BUILD_OPTIONS=${TF_BUILD_OPTIONS}"
# Function that tries to determine CUDA capability, if deviceQuery binary
# is available on path
function get_cuda_capability_version() {
if [[ ! -z $(which deviceQuery) ]]; then
# The first listed device is used
deviceQuery | grep "CUDA Capability .* version" | \
head -1 | awk '{print $NF}'
fi
}
# Container type, e.g., CPU, GPU
CTYPE=${TF_BUILD_CONTAINER_TYPE}
# Determine if the machine is a Mac
OPT_FLAG="--test_output=errors"
if [[ "$(uname -s)" == "Darwin" ]]; then
DO_DOCKER=0
echo "It appears this machine is a Mac. "\
"We will perform this build without Docker."
echo "Also, the additional option flags will be applied to the build:"
echo " ${NO_DOCKER_OPT_FLAG}"
MAIN_CMD="${NO_DOCKER_MAIN_CMD} ${CTYPE}"
OPT_FLAG="${OPT_FLAG} ${NO_DOCKER_OPT_FLAG}"
fi
# In DO_DOCKER mode, appends environment variable to docker's run invocation.
# Otherwise, exports the corresponding variable.
function set_script_variable() {
local VAR="$1"
local VALUE="$2"
if [[ $DO_DOCKER == "1" ]]; then
TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS} -e $VAR=$VALUE"
else
export $VAR="$VALUE"
fi
}
# Process container type
if [[ ${CTYPE} == cpu* ]] || [[ ${CTYPE} == "debian.jessie.cpu" ]]; then
:
elif [[ ${CTYPE} == gpu* ]]; then
set_script_variable TF_NEED_CUDA 1
if [[ $TF_CUDA_CLANG == "1" ]]; then
OPT_FLAG="${OPT_FLAG} --config=cuda_clang"
set_script_variable TF_CUDA_CLANG 1
# For cuda_clang we download `clang` while building.
set_script_variable TF_DOWNLOAD_CLANG 1
else
OPT_FLAG="${OPT_FLAG} --config=cuda"
fi
# Attempt to determine CUDA capability version automatically and use it if
# CUDA capability version is not specified by the environment variables.
CUDA_CAPA_VER=$(get_cuda_capability_version)
if [[ ! -z ${CUDA_CAPA_VER} ]]; then
AUTO_CUDA_CAPA_VER=0
if [[ ${DO_DOCKER} == "1" ]] && \
[[ "${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}" != \
*"TF_CUDA_COMPUTE_CAPABILITIES="* ]]; then
AUTO_CUDA_CAPA_VER=1
TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS=\
"${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS} -e "\
"TF_CUDA_COMPUTE_CAPABILITIES=${CUDA_CAPA_VER}"
echo "Docker GPU build: TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="\
"\"${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}\""
elif [[ ${DO_DOCKER} == "0" ]] && \
[[ -z "${TF_CUDA_COMPUTE_CAPABILITIES}" ]]; then
AUTO_CUDA_CAPA_VER=1
TF_CUDA_COMPUTE_CAPABILITIES="${CUDA_CAPA_VER}"
echo "Non-Docker GPU build: TF_CUDA_COMPUTE_CAPABILITIES="\
"\"${TF_CUDA_COMPUTE_CAPABILITIES}\""
fi
if [[ ${AUTO_CUDA_CAPA_VER} == "1" ]]; then
echo "TF_CUDA_COMPUTE_CAPABILITIES is not set:"
echo "Using CUDA capability version from deviceQuery: ${CUDA_CAPA_VER}"
echo ""
fi
fi
elif [[ ${CTYPE} == "android" ]] || [[ ${CTYPE} == "android_full" ]]; then
:
else
die "Unrecognized value in TF_BUILD_CONTAINER_TYPE: "\
"\"${TF_BUILD_CONTAINER_TYPE}\""
fi
# Determine if this is a benchmarks job
RUN_BENCHMARKS=0
if [[ ! -z "${TF_BUILD_RUN_BENCHMARKS}" ]] &&
[[ "${TF_BUILD_RUN_BENCHMARKS}" != "0" ]]; then
RUN_BENCHMARKS=1
fi
# Process Bazel "-c opt" flag
if [[ -z "${TF_BUILD_OPTIONS}" ]]; then
if [[ ${TF_BUILD_IS_OPT} == "no_opt" ]]; then
# PIP builds are done only with the -c opt flag
if [[ ${TF_BUILD_IS_PIP} == "pip" ]]; then
echo "Skipping parameter combination: ${TF_BUILD_IS_OPT} & "\
"${TF_BUILD_IS_PIP}"
exit 0
fi
elif [[ ${TF_BUILD_IS_OPT} == "opt" ]]; then
OPT_FLAG="${OPT_FLAG} -c opt"
else
die "Unrecognized value in TF_BUILD_IS_OPT: \"${TF_BUILD_IS_OPT}\""
fi
# Process MAVX option
if [[ ! -z "${TF_BUILD_MAVX}" ]]; then
if [[ "${TF_BUILD_MAVX}" == "mavx" ]]; then
OPT_FLAG="${OPT_FLAG} --copt=-mavx"
elif [[ "${TF_BUILD_MAVX}" == "mavx2" ]]; then
OPT_FLAG="${OPT_FLAG} --copt=-mavx2"
else
die "Unsupported value in TF_BUILD_MAVX: ${TF_BUILD_MAVX}"
fi
fi
else
case $TF_BUILD_OPTIONS in
FASTBUILD)
echo "Running FASTBUILD mode (noopt, nodbg)."
;;
OPT)
OPT_FLAG="${OPT_FLAG} -c opt"
;;
OPTDBG)
OPT_FLAG="${OPT_FLAG} -c opt --copt=-g"
;;
MAVX)
OPT_FLAG="${OPT_FLAG} -c opt --copt=-mavx"
;;
MAVX_DBG)
OPT_FLAG="${OPT_FLAG} -c opt --copt=-g --copt=-mavx"
;;
MAVX2_FMA)
OPT_FLAG="${OPT_FLAG} -c opt --copt=-mavx2 --copt=-mfma"
;;
MAVX2_FMA_DBG)
OPT_FLAG="${OPT_FLAG} -c opt --copt=-g --copt=-mavx2 --copt=-mfma"
;;
esac
fi
# Strip whitespaces from OPT_FLAG
OPT_FLAG=$(str_strip "${OPT_FLAG}")
# 1) Filter out benchmark tests if this is not a benchmarks job;
# 2) Filter out tests with the "nomac" tag if the build is on Mac OS X.
EXTRA_ARGS=${DEFAULT_BAZEL_CONFIGS}
IS_MAC=0
if [[ "$(uname)" == "Darwin" ]]; then
IS_MAC=1
fi
if [[ "${TF_BUILD_APPEND_ARGUMENTS}" == *"--test_tag_filters="* ]]; then
ITEMS=(${TF_BUILD_APPEND_ARGUMENTS})
for ITEM in "${ITEMS[@]}"; do
if [[ ${ITEM} == *"--test_tag_filters="* ]]; then
NEW_ITEM="${ITEM}"
if [[ ${NEW_ITEM} != *"benchmark-test"* ]]; then
NEW_ITEM="${NEW_ITEM},-benchmark-test"
fi
if [[ ${IS_MAC} == "1" ]] && [[ ${NEW_ITEM} != *"nomac"* ]]; then
NEW_ITEM="${NEW_ITEM},-nomac"
fi
EXTRA_ARGS="${EXTRA_ARGS} ${NEW_ITEM}"
else
EXTRA_ARGS="${EXTRA_ARGS} ${ITEM}"
fi
done
else
EXTRA_ARGS="${EXTRA_ARGS} ${TF_BUILD_APPEND_ARGUMENTS} --test_tag_filters=-no_oss,-oss_serial,-benchmark-test"
if [[ ${IS_MAC} == "1" ]]; then
EXTRA_ARGS="${EXTRA_ARGS},-nomac"
fi
EXTRA_ARGS="${EXTRA_ARGS} --build_tag_filters=-no_oss,-oss_serial,-benchmark-test"
if [[ ${IS_MAC} == "1" ]]; then
EXTRA_ARGS="${EXTRA_ARGS},-nomac"
fi
fi
# For any "tool" dependencies in genrules, Bazel will build them for host
# instead of the target configuration. We can save some build time by setting
# this flag, and it only affects a few tests.
EXTRA_ARGS="${EXTRA_ARGS} --distinct_host_configuration=false"
if [[ ! -z "${TF_BAZEL_BUILD_ONLY}" ]] &&
[[ "${TF_BAZEL_BUILD_ONLY}" != "0" ]];then
BAZEL_CMD=${BAZEL_BUILD_ONLY_CMD}
fi
# Process PIP install-test option
if [[ ${TF_BUILD_IS_PIP} == "no_pip" ]] ||
[[ ${TF_BUILD_IS_PIP} == "both" ]]; then
# Process optional bazel target override
if [[ ! -z "${TF_BUILD_BAZEL_TARGET}" ]]; then
BAZEL_TARGET=${TF_BUILD_BAZEL_TARGET}
fi
if [[ ${CTYPE} == cpu* ]] || \
[[ ${CTYPE} == "debian.jessie.cpu" ]]; then
# CPU only command, fully parallel.
NO_PIP_MAIN_CMD="${MAIN_CMD} ${BAZEL_CMD} ${OPT_FLAG} ${EXTRA_ARGS} -- "\
"${BAZEL_TARGET}"
elif [[ ${CTYPE} == gpu* ]]; then
# GPU only command, run as many jobs as the GPU count only.
NO_PIP_MAIN_CMD="${BAZEL_CMD} ${OPT_FLAG} "\
"--local_test_jobs=${TF_GPU_COUNT} "\
"--run_under=${PARALLEL_GPU_TEST_CMD} ${EXTRA_ARGS} -- ${BAZEL_TARGET}"
elif [[ ${CTYPE} == "android" ]]; then
# Run android specific script for android build.
NO_PIP_MAIN_CMD="${ANDROID_CMD} ${OPT_FLAG} "
elif [[ ${CTYPE} == "android_full" ]]; then
# Run android specific script for full android build.
NO_PIP_MAIN_CMD="${ANDROID_FULL_CMD} ${OPT_FLAG} "
fi
fi
if [[ ${TF_BUILD_IS_PIP} == "pip" ]] ||
[[ ${TF_BUILD_IS_PIP} == "both" ]]; then
# Android builds conflict with PIP builds
if [[ ${CTYPE} == "android" ]]; then
echo "Skipping parameter combination: ${TF_BUILD_IS_PIP} & "\
"${TF_BUILD_CONTAINER_TYPE}"
exit 0
fi
PIP_MAIN_CMD="${MAIN_CMD} ${PIP_CMD} ${CTYPE} ${EXTRA_ARGS} ${OPT_FLAG}"
# Add flag for integration tests
if [[ ! -z "${TF_BUILD_INTEGRATION_TESTS}" ]] &&
[[ "${TF_BUILD_INTEGRATION_TESTS}" != "0" ]]; then
PIP_MAIN_CMD="${PIP_MAIN_CMD} ${PIP_INTEGRATION_TESTS_FLAG}"
fi
# Add command for tutorial test
if [[ ! -z "${TF_BUILD_TEST_TUTORIALS}" ]] &&
[[ "${TF_BUILD_TEST_TUTORIALS}" != "0" ]]; then
PIP_MAIN_CMD="${PIP_MAIN_CMD} ${PIP_TEST_TUTORIALS_FLAG}"
# Prepare data directory for tutorial tests
mkdir -p "${TUT_TEST_DATA_DIR}" ||
die "FAILED to create data directory for tutorial tests: "\
"${TUT_TEST_DATA_DIR}"
if [[ "${DO_DOCKER}" == "1" ]]; then
EXTRA_PARAMS="${EXTRA_PARAMS} -v ${TUT_TEST_DATA_DIR}:${TUT_TEST_DATA_DIR}"
fi
fi
fi
if [[ ${RUN_BENCHMARKS} == "1" ]]; then
MAIN_CMD="${BENCHMARK_CMD} ${OPT_FLAG}"
elif [[ ${TF_BUILD_IS_PIP} == "no_pip" ]]; then
MAIN_CMD="${NO_PIP_MAIN_CMD}"
elif [[ ${TF_BUILD_IS_PIP} == "pip" ]]; then
MAIN_CMD="${PIP_MAIN_CMD}"
elif [[ ${TF_BUILD_IS_PIP} == "both" ]]; then
MAIN_CMD="${NO_PIP_MAIN_CMD} && ${PIP_MAIN_CMD}"
else
die "Unrecognized value in TF_BUILD_IS_PIP: \"${TF_BUILD_IS_PIP}\""
fi
# Check if this is a tf_nightly build
if [[ "${TF_NIGHTLY}" == "1" ]]; then
EXTRA_PARAMS="${EXTRA_PARAMS} -e TF_NIGHTLY=1"
fi
# Process Python version
if [[ ${TF_BUILD_PYTHON_VERSION} == "python2" ]]; then
:
elif [[ ${TF_BUILD_PYTHON_VERSION} == "python3" || \
${TF_BUILD_PYTHON_VERSION} == "python3.4" || \
${TF_BUILD_PYTHON_VERSION} == "python3.5" || \
${TF_BUILD_PYTHON_VERSION} == "python3.6" ]]; then
# Supply proper environment variable to select Python 3
if [[ "${DO_DOCKER}" == "1" ]]; then
EXTRA_PARAMS="${EXTRA_PARAMS} -e CI_BUILD_PYTHON=${TF_BUILD_PYTHON_VERSION}"
else
# Determine the path to python3
PYTHON3_PATH=$(which "${TF_BUILD_PYTHON_VERSION}" | head -1)
if [[ -z "${PYTHON3_PATH}" ]]; then
die "ERROR: Failed to locate ${TF_BUILD_PYTHON_VERSION} binary on path"
else
echo "Found ${TF_BUILD_PYTHON_VERSION} binary at: ${PYTHON3_PATH}"
fi
export PYTHON_BIN_PATH="${PYTHON3_PATH}"
fi
else
die "Unrecognized value in TF_BUILD_PYTHON_VERSION: "\
"\"${TF_BUILD_PYTHON_VERSION}\""
fi
# Append additional Docker extra parameters
EXTRA_PARAMS="${EXTRA_PARAMS} ${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}"
# Finally, do a dry run or call the command
# The command, which may consist of multiple parts (e.g., in the case of
# TF_BUILD_SERIAL_TESTS=1), are written to a bash script, which is
# then called. The name of the script is randomized to make concurrent
# builds on the node possible.
TMP_SCRIPT="$(mktemp)_ci_parameterized_build.sh"
if [[ "${DO_DOCKER}" == "1" ]]; then
# Map the tmp script into the Docker container
EXTRA_PARAMS="${EXTRA_PARAMS} -v ${TMP_SCRIPT}:/tmp/tf_build.sh"
if [[ ! -z "${TF_BUILD_BAZEL_CLEAN}" ]] &&
[[ "${TF_BUILD_BAZEL_CLEAN}" != "0" ]] &&
[[ "${TF_BUILD_IS_PIP}" != "both" ]]; then
# For TF_BUILD_IS_PIP == both, "bazel clean" will have already
# been performed before the "bazel test" step
EXTRA_PARAMS="${EXTRA_PARAMS} -e TF_BUILD_BAZEL_CLEAN=1"
fi
EXTRA_PARAMS=$(str_strip "${EXTRA_PARAMS}")
echo "Exporting CI_DOCKER_EXTRA_PARAMS: ${EXTRA_PARAMS}"
export CI_DOCKER_EXTRA_PARAMS="${EXTRA_PARAMS}"
fi
# Write to the tmp script
echo "#!/usr/bin/env bash" > ${TMP_SCRIPT}
if [[ ! -z "${TF_BUILD_BAZEL_CLEAN}" ]] &&
[[ "${TF_BUILD_BAZEL_CLEAN}" != "0" ]]; then
echo ${BAZEL_CLEAN_CMD} >> ${TMP_SCRIPT}
fi
echo ${MAIN_CMD} >> ${TMP_SCRIPT}
echo "Executing final command (${TMP_SCRIPT})..."
echo "=========================================="
cat ${TMP_SCRIPT}
echo "=========================================="
echo ""
TMP_DIR=""
DOCKERFILE_FLAG=""
if [[ "${DO_DOCKER}" == "1" ]]; then
if [[ "${TF_BUILD_PYTHON_VERSION}" == "python3.5" ]] ||
[[ "${TF_BUILD_PYTHON_VERSION}" == "python3.6" ]]; then
# Modify Dockerfile for Python3.5 | Python3.6 build
TMP_DIR=$(mktemp -d)
echo "Docker build will occur in temporary directory: ${TMP_DIR}"
# Copy the files required for the docker build
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cp -r "${SCRIPT_DIR}/install" "${TMP_DIR}/install" || \
die "ERROR: Failed to copy directory ${SCRIPT_DIR}/install"
DOCKERFILE="${SCRIPT_DIR}/Dockerfile.${TF_BUILD_CONTAINER_TYPE}"
cp "${DOCKERFILE}" "${TMP_DIR}/" || \
die "ERROR: Failed to copy Dockerfile at ${DOCKERFILE}"
DOCKERFILE="${TMP_DIR}/Dockerfile.${TF_BUILD_CONTAINER_TYPE}"
# Replace a line in the Dockerfile
if sed -i \
"s/RUN \/install\/install_pip_packages.sh/RUN \/install\/install_${TF_BUILD_PYTHON_VERSION}_pip_packages.sh/g" \
"${DOCKERFILE}"
then
echo "Copied and modified Dockerfile for ${TF_BUILD_PYTHON_VERSION} build: ${DOCKERFILE}"
else
die "ERROR: Faild to copy and modify Dockerfile: ${DOCKERFILE}"
fi
DOCKERFILE_FLAG="--dockerfile ${DOCKERFILE}"
fi
fi
chmod +x ${TMP_SCRIPT}
# Map TF_BUILD container types to containers we actually have.
if [[ "${CTYPE}" == "android_full" ]]; then
CONTAINER="android"
else
CONTAINER=${CTYPE}
fi
FAILURE=0
if [[ ! -z "${TF_BUILD_DRY_RUN}" ]] && [[ ${TF_BUILD_DRY_RUN} != "0" ]]; then
# Do a dry run: just print the final command
echo "*** This is a DRY RUN ***"
else
# Actually run the command
if [[ "${DO_DOCKER}" == "1" ]]; then
${DOCKER_MAIN_CMD} ${CONTAINER} ${DOCKERFILE_FLAG} /tmp/tf_build.sh
else
${TMP_SCRIPT}
fi
if [[ $? != "0" ]]; then
FAILURE=1
fi
fi
[[ ${FAILURE} == "0" ]] && RESULT="SUCCESS" || RESULT="FAILURE"
rm -f ${TMP_SCRIPT}
END_TIME=$(date +'%s')
echo ""
echo "Parameterized build ends with ${RESULT} at: $(date) "\
"(Elapsed time: $((END_TIME - START_TIME)) s)"
# Clean up temporary directory if it exists
if [[ ! -z "${TMP_DIR}" ]]; then
echo "Cleaning up temporary directory: ${TMP_DIR}"
rm -rf "${TMP_DIR}"
fi
exit ${FAILURE}