Home | History | Annotate | Download | only in builds
      1 #!/usr/bin/env bash
      2 # Copyright 2016 The TensorFlow Authors. All Rights Reserved.
      3 #
      4 # Licensed under the Apache License, Version 2.0 (the "License");
      5 # you may not use this file except in compliance with the License.
      6 # You may obtain a copy of the License at
      7 #
      8 #     http://www.apache.org/licenses/LICENSE-2.0
      9 #
     10 # Unless required by applicable law or agreed to in writing, software
     11 # distributed under the License is distributed on an "AS IS" BASIS,
     12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 # See the License for the specific language governing permissions and
     14 # limitations under the License.
     15 # ==============================================================================
     16 # Build the Python PIP installation package for TensorFlow and install
     17 # the package.
     18 #
     19 # Usage:
     20 #   pip_new.sh
     21 #
     22 # Required step(s):
     23 #   Run configure.py prior to running this script.
     24 #
     25 # Required environment variable(s):
     26 #   CONTAINER_TYPE:      (CPU | GPU)
     27 #   OS_TYPE:             (UBUNTU | MACOS)
     28 #   TF_PYTHON_VERSION:   (python2 | python2.7 | python3.5 | python3.7)
     29 #   TF_BUILD_FLAGS:      Bazel build flags.
     30 #                          e.g. TF_BUILD_FLAGS="--config=opt"
     31 #   TF_TEST_FLAGS:       Bazel test flags.
     32 #                          e.g. TF_TEST_FLAGS="--verbose_failures=true \
     33 #                               --build_tests_only --test_output=errors"
     34 #   TF_TEST_FILTER_TAGS: Filtering tags for bazel tests. More specifically,
     35 #                        input tags for `--test_filter_tags` flag.
     36 #                          e.g. TF_TEST_FILTER_TAGS="no_pip,-nomac,no_oss"
     37 #   TF_TEST_TARGETS:     Bazel test targets.
     38 #                          e.g. TF_TEST_TARGETS="//tensorflow/... \
     39 #                               -//tensorflow/contrib/... \
     40 #                               -//tensorflow/python/..."
     41 #   IS_NIGHTLY:          Nightly run flag.
     42 #                          e.g. IS_NIGHTLY=1  # nightly runs
     43 #                          e.g. IS_NIGHTLY=0  # non-nightly runs
     44 #
     45 # Optional environment variables. If provided, overwrites any default values.
     46 #   TF_PIP_TESTS:        PIP tests to run. If NOT specified, skips all tests.
     47 #                          e.g. TF_PIP_TESTS="test_pip_virtualenv_clean \
     48 #                               test_pip_virtualenv_clean \
     49 #                               test_pip_virtualenv_oss_serial"
     50 #   TF_PROJECT_NAME:     Name of the project. This string will be pass onto
     51 #                        the wheel file name. For nightly builds, it will be
     52 #                        overwritten to 'tf_nightly'. For gpu builds, '_gpu'
     53 #                        will be appended.
     54 #                          e.g. TF_PROJECT_NAME="tensorflow"
     55 #                          e.g. TF_PROJECT_NAME="tf_nightly_gpu"
     56 #   TF_PIP_TEST_ROOT:    Root directory for building and testing pip pkgs.
     57 #                          e.g. TF_PIP_TEST_ROOT="pip_test"
     58 #
     59 # To-be-deprecated variable(s).
     60 #   GIT_TAG_OVERRIDE:    Values for `--git_tag_override`. This flag gets passed
     61 #                        in as `--action_env` for bazel build and tests.
     62 #   TF_BUILD_INSTALL_EXTRA_PIP_PACKAGES:
     63 #                        Additonal pip packages to be installed.
     64 #                        Caveat: pip version needs to be checked prior.
     65 #
     66 # ==============================================================================
     67 
     68 # set bash options
     69 set -e
     70 set -x
     71 
     72 ###########################################################################
     73 # General helper function(s)
     74 ###########################################################################
     75 
     76 # Strip leading and trailing whitespaces
     77 str_strip () {
     78   echo -e "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'
     79 }
     80 
     81 # Convert string to all lower case
     82 lowercase() {
     83   if [[ -z "${1}" ]]; then
     84     die "Nothing to convert to lowercase. No argument given."
     85   fi
     86   echo "${1}" | tr '[:upper:]' '[:lower:]'
     87 }
     88 
     89 check_global_vars() {
     90   # Check container type
     91   if ! [[ ${CONTAINER_TYPE} == "cpu" ]] && \
     92      ! [[ ${CONTAINER_TYPE} == "rocm" ]] && \
     93      ! [[ ${CONTAINER_TYPE} == "gpu" ]]; then
     94     die "Error: Provided CONTAINER_TYPE \"${CONTAINER_TYPE}\" "\
     95         "is not supported."
     96   fi
     97   # Check OS type
     98   if ! [[ ${OS_TYPE} == "ubuntu" ]] && \
     99      ! [[ ${OS_TYPE} == "macos" ]]; then
    100     die "Error: Provided OS_TYPE \"${OS_TYPE}\" is not supported."
    101   fi
    102   # Check build flags
    103   if [[ -z ${TF_BUILD_FLAGS} ]]; then
    104     die "Error: TF_BUILD_FLAGS is not specified."
    105   fi
    106   # Check test flags
    107   if [[ -z ${TF_TEST_FLAGS} ]]; then
    108     die "Error: TF_TEST_FLAGS is not specified."
    109   fi
    110   # Check test filter tags
    111   if [[ -z ${TF_TEST_FILTER_TAGS} ]]; then
    112     die "Error: TF_TEST_FILTER_TAGS is not specified."
    113   fi
    114   # Check test targets
    115   if [[ -z ${TF_TEST_TARGETS} ]]; then
    116     die "Error: TF_TEST_TARGETS is not specified."
    117   fi
    118   # Check nightly status
    119   if [[ -z ${IS_NIGHTLY} ]]; then
    120     die "Error: IS_NIGHTLY is not specified."
    121   fi
    122 }
    123 
    124 add_test_filter_tag() {
    125   EMPTY=""
    126   while true; do
    127     FILTER="${1:$EMPTY}"
    128     if ! [[ $TF_TEST_FILTER_TAGS == *"${FILTER}"* ]]; then
    129       TF_TEST_FILTER_TAGS="${FILTER},${TF_TEST_FILTER_TAGS}"
    130     fi
    131     shift
    132     if [[ -z "${1}" ]]; then
    133       break
    134     fi
    135   done
    136 }
    137 
    138 remove_test_filter_tag() {
    139   EMPTY=""
    140   while true; do
    141     FILTER="${1:$EMPTY}"
    142     TF_TEST_FILTER_TAGS="$(echo ${TF_TEST_FILTER_TAGS} | sed -e 's/^'${FILTER}',//g' -e 's/,'${FILTER}'//g')"
    143     shift
    144     if [[ -z "${1}" ]]; then
    145       break
    146     fi
    147   done
    148 }
    149 
    150 # Clean up bazel build & test flags with proper configuration.
    151 update_bazel_flags() {
    152   # Add git tag override flag if necessary.
    153   GIT_TAG_STR=" --action_env=GIT_TAG_OVERRIDE"
    154   if [[ -z "${GIT_TAG_OVERRIDE}" ]] && \
    155     ! [[ ${TF_BUILD_FLAGS} = *${GIT_TAG_STR}* ]]; then
    156     TF_BUILD_FLAGS+="${GIT_TAG_STR}"
    157   fi
    158   # Clean up whitespaces
    159   TF_BUILD_FLAGS=$(str_strip "${TF_BUILD_FLAGS}")
    160   TF_TEST_FLAGS=$(str_strip "${TF_TEST_FLAGS}")
    161   # Cleaned bazel flags
    162   echo "Bazel build flags (cleaned):\n" "${TF_BUILD_FLAGS}"
    163   echo "Bazel test flags (cleaned):\n" "${TF_TEST_FLAGS}"
    164 }
    165 
    166 update_test_filter_tags() {
    167   # Add test filter tags
    168   # This script is for validating built PIP packages. Add pip tags.
    169   add_test_filter_tag -no_pip -nopip
    170   # MacOS filter tags
    171   if [[ ${OS_TYPE} == "macos" ]]; then
    172     remove_test_filter_tag nomac no_mac
    173     add_test_filter_tag -nomac -no_mac
    174   fi
    175   echo "Final test filter tags: ${TF_TEST_FILTER_TAGS}"
    176 }
    177 
    178 # Check currently running python and pip version
    179 check_python_pip_version() {
    180   # Check if only the major version of python is provided by the user.
    181   MAJOR_VER_ONLY=0
    182   if [[ ${#PYTHON_VER} -lt 9 ]]; then
    183     # User only provided major version (e.g. 'python2' instead of 'python2.7')
    184     MAJOR_VER_ONLY=1
    185   fi
    186 
    187   # Retrieve only the version number of the user requested python.
    188   PYTHON_VER_REQUESTED=${PYTHON_VER:6:3}
    189   echo "PYTHON_VER_REQUESTED: ${PYTHON_VER_REQUESTED}"
    190 
    191   # Retrieve only the version numbers of the python & pip in use currently.
    192   PYTHON_VER_IN_USE=$(python --version 2>&1)
    193   PYTHON_VER_IN_USE=${PYTHON_VER_IN_USE:7:3}
    194   PIP_VER_IN_USE=$(${PIP_BIN_PATH} --version)
    195   PIP_VER_IN_USE=${PIP_VER_IN_USE:${#PIP_VER_IN_USE}-4:3}
    196 
    197   # If only major versions are applied, drop minor versions.
    198   if [[ $MAJOR_VER_ONLY == 1 ]]; then
    199     PYTHON_VER_IN_USE=${PYTHON_VER_IN_USE:0:1}
    200     PIP_VER_IN_USE=${PIP_VER_IN_USE:0:1}
    201   fi
    202 
    203   # Check if all versions match.
    204   echo -e "User requested python version: '${PYTHON_VER_REQUESTED}'\n" \
    205     "Detected python version in use: '${PYTHON_VER_IN_USE}'\n"\
    206     "Detected pip version in use: '${PIP_VER_IN_USE}'"
    207   if ! [[ $PYTHON_VER_REQUESTED == $PYTHON_VER_IN_USE ]]; then
    208     die "Error: Mismatch in python versions detected."
    209   else:
    210     echo "Python and PIP versions in use match the requested."
    211   fi
    212 }
    213 
    214 ###########################################################################
    215 # Setup: directories, local/global variables
    216 ###########################################################################
    217 
    218 # Script directory and source necessary files.
    219 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
    220 source "${SCRIPT_DIR}/builds_common.sh"
    221 
    222 # Required global variables
    223 # Checks on values for these vars are done in "Build TF PIP Package" section.
    224 CONTAINER_TYPE=$(lowercase "${CONTAINER_TYPE}")
    225 OS_TYPE=$(lowercase "${OS_TYPE}")
    226 PYTHON_VER=$(lowercase "${TF_PYTHON_VERSION}")
    227 
    228 # Python bin path
    229 if [[ -z "$PYTHON_BIN_PATH" ]]; then
    230   die "Error: PYTHON_BIN_PATH was not provided. Did you run configure?"
    231 fi
    232 
    233 # Set optional environment variables; set to default in case not user defined.
    234 DEFAULT_PIP_TESTS="" # Do not run any tests by default
    235 DEFAULT_PROJECT_NAME="tensorflow"
    236 DEFAULT_PIP_TEST_ROOT="pip_test"
    237 # Take in optional global variables
    238 PIP_TESTS=${TF_PIP_TESTS:-$DEFAULT_PIP_TESTS}
    239 PROJECT_NAME=${TF_PROJECT_NAME:-$DEFAULT_PROJECT_NAME}
    240 PIP_TEST_ROOT=${TF_PIP_TEST_ROOT:-$DEFAULT_PIP_TEST_ROOT}
    241 
    242 # Local variables
    243 PIP_WHL_DIR="${KOKORO_ARTIFACTS_DIR}/tensorflow/${PIP_TEST_ROOT}/whl"
    244 mkdir -p "${PIP_WHL_DIR}"
    245 PIP_WHL_DIR=$(realpath "${PIP_WHL_DIR}") # Get absolute path
    246 WHL_PATH=""
    247 # Determine the major.minor versions of python being used (e.g., 2.7).
    248 # Useful for determining the directory of the local pip installation.
    249 PY_MAJOR_MINOR_VER=$(${PYTHON_BIN_PATH} -c "print(__import__('sys').version)" 2>&1 | awk '{ print $1 }' | head -n 1 | cut -c1-3)
    250 
    251 if [[ -z "${PY_MAJOR_MINOR_VER}" ]]; then
    252   die "ERROR: Unable to determine the major.minor version of Python."
    253 fi
    254 echo "Python binary path to be used in PIP install: ${PYTHON_BIN_PATH} "\
    255 "(Major.Minor version: ${PY_MAJOR_MINOR_VER})"
    256 PYTHON_BIN_PATH_INIT=${PYTHON_BIN_PATH}
    257 PIP_BIN_PATH="$(which pip${PY_MAJOR_MINOR_VER})"
    258 
    259 # PIP packages
    260 INSTALL_EXTRA_PIP_PACKAGES=${TF_BUILD_INSTALL_EXTRA_PIP_PACKAGES}
    261 
    262 ###########################################################################
    263 # Build TF PIP Package
    264 ###########################################################################
    265 
    266 # First remove any already existing binaries for a clean start and test.
    267 if [[ -d ${PIP_TEST_ROOT} ]]; then
    268   echo "Test root directory ${PIP_TEST_ROOT} already exists. Deleting it."
    269   sudo rm -rf ${PIP_TEST_ROOT}
    270 fi
    271 
    272 # Check that global variables are properly set.
    273 check_global_vars
    274 
    275 # Check if in a virtualenv and exit if yes.
    276 IN_VENV=$(python -c 'import sys; print("1" if hasattr(sys, "real_prefix") else "0")')
    277 if [[ "$IN_VENV" == "1" ]]; then
    278   echo "It appears that we are already in a virtualenv. Deactivating..."
    279   deactivate || source deactivate || die "FAILED: Unable to deactivate from existing virtualenv."
    280 fi
    281 
    282 # Configure python. Obtain the path to python binary.
    283 source tools/python_bin_path.sh
    284 # Assume PYTHON_BIN_PATH is exported by the script above.
    285 if [[ -z "$PYTHON_BIN_PATH" ]]; then
    286   die "PYTHON_BIN_PATH was not provided. Did you run configure?"
    287 fi
    288 
    289 # Bazel build the file.
    290 PIP_BUILD_TARGET="//tensorflow/tools/pip_package:build_pip_package"
    291 # Clean bazel cache.
    292 bazel clean
    293 # Clean up and update bazel flags
    294 update_bazel_flags
    295 # Build. This outputs the file `build_pip_package`.
    296 bazel build ${TF_BUILD_FLAGS} ${PIP_BUILD_TARGET} || \
    297   die "Error: Bazel build failed for target: '${PIP_BUILD_TARGET}'"
    298 
    299 ###########################################################################
    300 # Test function(s)
    301 ###########################################################################
    302 
    303 test_pip_virtualenv() {
    304   # Get args
    305   VENV_DIR_NAME=$1
    306   shift
    307   TEST_TYPE_FLAG=$1
    308 
    309   # Check test type args
    310   if ! [[ ${TEST_TYPE_FLAG} == "--oss_serial" ]] && \
    311      ! [[ ${TEST_TYPE_FLAG} == "--clean" ]] && \
    312      ! [[ ${TEST_TYPE_FLAG} == "" ]]; then
    313      die "Error: Wrong test type given. TEST_TYPE_FLAG=${TEST_TYPE_FLAG}"
    314   fi
    315 
    316   # Create virtualenv directory for test
    317   VENV_DIR="${PIP_TEST_ROOT}/${VENV_DIR_NAME}"
    318 
    319   # Activate virtualenv
    320   create_activate_virtualenv ${TEST_TYPE_FLAG} ${VENV_DIR}
    321   # Install TF with pip
    322   TIME_START=$SECONDS
    323   install_tensorflow_pip "${WHL_PATH}"
    324   TIME_ELAPSED=$(($SECONDS - $TIME_START))
    325   echo "Time elapsed installing tensorflow = ${TIME_ELAPSED} seconds"
    326 
    327   # cd to a temporary directory to avoid picking up Python files in the source
    328   # tree.
    329   TMP_DIR=$(mktemp -d)
    330   pushd "${TMP_DIR}"
    331 
    332   # Run a quick check on tensorflow installation.
    333   RET_VAL=$(python -c "import tensorflow as tf; t1=tf.constant([1,2,3,4]); t2=tf.constant([5,6,7,8]); print(tf.add(t1,t2).shape)")
    334 
    335   # Return to original directory. Remove temp dirs.
    336   popd
    337   sudo rm -rf "${TMP_DIR}"
    338 
    339   # Check result to see if tensorflow is properly installed.
    340   if ! [[ ${RET_VAL} == *'(4,)'* ]]; then
    341     echo "PIP test on virtualenv (non-clean) FAILED"
    342     return 1
    343   fi
    344 
    345   # Install extra pip packages, if specified.
    346   for PACKAGE in ${INSTALL_EXTRA_PIP_PACKAGES}; do
    347     echo "Installing extra pip package required by test-on-install: ${PACKAGE}"
    348 
    349     ${PIP_BIN_PATH} install ${PACKAGE}
    350     if [[ $? != 0 ]]; then
    351       echo "${PIP_BIN_PATH} install ${PACKAGE} FAILED."
    352       deactivate || source deactivate || die "FAILED: Unable to deactivate from existing virtualenv."
    353       return 1
    354     fi
    355   done
    356 
    357   # Run bazel test.
    358   run_test_with_bazel ${TEST_TYPE_FLAG}
    359   RESULT=$?
    360 
    361   # Deactivate from virtualenv.
    362   deactivate || source deactivate || die "FAILED: Unable to deactivate from existing virtualenv."
    363   sudo rm -rf "${VENV_DIR}"
    364 
    365   return $RESULT
    366 }
    367 
    368 ###########################################################################
    369 # Test helper function(s)
    370 ###########################################################################
    371 
    372 create_activate_virtualenv() {
    373   VIRTUALENV_FLAGS="--system-site-packages"
    374   if [[ "${1}" == "--clean" ]]; then
    375     VIRTUALENV_FLAGS=""
    376     shift
    377   elif [[ "{1}" == "--oss_serial" ]]; then
    378     shift
    379   fi
    380 
    381   VIRTUALENV_DIR="${1}"
    382   if [[ -d "${VIRTUALENV_DIR}" ]]; then
    383     if sudo rm -rf "${VIRTUALENV_DIR}"
    384     then
    385       echo "Removed existing virtualenv directory: ${VIRTUALENV_DIR}"
    386     else
    387       die "Failed to remove existing virtualenv directory: ${VIRTUALENV_DIR}"
    388     fi
    389   fi
    390 
    391   if mkdir -p "${VIRTUALENV_DIR}"
    392   then
    393     echo "Created virtualenv directory: ${VIRTUALENV_DIR}"
    394   else
    395     die "FAILED to create virtualenv directory: ${VIRTUALENV_DIR}"
    396   fi
    397 
    398   # Use the virtualenv from the default python version (i.e., python-virtualenv)
    399   # to create the virtualenv directory for testing. Use the -p flag to specify
    400   # the python version inside the to-be-created virtualenv directory.
    401   ${PYTHON_BIN_PATH_INIT} -m virtualenv -p ${PYTHON_BIN_PATH_INIT} ${VIRTUALENV_FLAGS} ${VIRTUALENV_DIR} || \
    402     die "FAILED: Unable to create virtualenv"
    403 
    404   source "${VIRTUALENV_DIR}/bin/activate" || \
    405     die "FAILED: Unable to activate virtualenv in ${VIRTUALENV_DIR}"
    406 
    407   # Update .tf_configure.bazelrc with venv python path for bazel test.
    408   PYTHON_BIN_PATH="$(which python)"
    409   yes "" | ./configure
    410 }
    411 
    412 install_tensorflow_pip() {
    413   if [[ -z "${1}" ]]; then
    414     die "Please provide a proper wheel file path."
    415   fi
    416 
    417   # Set path to pip.
    418   PIP_BIN_PATH="$(which pip${PY_MAJOR_MINOR_VER})"
    419 
    420   # Print python and pip bin paths
    421   echo "PYTHON_BIN_PATH to be used to install the .whl: ${PYTHON_BIN_PATH}"
    422   echo "PIP_BIN_PATH to be used to install the .whl: ${PIP_BIN_PATH}"
    423 
    424   # Upgrade pip so it supports tags such as cp27mu, manylinux1 etc.
    425   echo "Upgrade pip in virtualenv"
    426 
    427   # NOTE: pip install --upgrade pip leads to a documented TLS issue for
    428   # some versions in python
    429   curl https://bootstrap.pypa.io/get-pip.py | ${PYTHON_BIN_PATH} || \
    430     die "Error: pip install (get-pip.py) FAILED"
    431 
    432   # Check that requested python version matches configured one.
    433   check_python_pip_version
    434 
    435   # Force upgrade of setuptools. This must happen before the pip install of the
    436   # WHL_PATH, which pulls in absl-py, which uses install_requires notation
    437   # introduced in setuptools >=20.5. The default version of setuptools is 5.5.1,
    438   # which is too old for absl-py.
    439   ${PIP_BIN_PATH} install --upgrade setuptools==39.1.0 || \
    440     die "Error: setuptools install, upgrade FAILED"
    441 
    442   # Force tensorflow reinstallation. Otherwise it may not get installed from
    443   # last build if it had the same version number as previous build.
    444   PIP_FLAGS="--upgrade --force-reinstall"
    445   ${PIP_BIN_PATH} install -v ${PIP_FLAGS} ${WHL_PATH} || \
    446     die "pip install (forcing to reinstall tensorflow) FAILED"
    447   echo "Successfully installed pip package ${WHL_PATH}"
    448 
    449   # Force downgrade of setuptools. This must happen after the pip install of the
    450   # WHL_PATH, which ends up upgrading to the latest version of setuptools.
    451   # Versions of setuptools >= 39.1.0 will cause tests to fail like this:
    452   #   ImportError: cannot import name py31compat
    453   ${PIP_BIN_PATH} install --upgrade setuptools==39.1.0 || \
    454     die "Error: setuptools install, upgrade FAILED"
    455 }
    456 
    457 run_test_with_bazel() {
    458   IS_OSS_SERIAL=0
    459   if [[ "${1}" == "--oss_serial" ]]; then
    460     IS_OSS_SERIAL=1
    461   fi
    462   TF_GPU_COUNT=${TF_GPU_COUNT:-4}
    463 
    464   # PIP tests should have a "different" path. Different than the one we place
    465   # virtualenv, because we are deleting and recreating it here.
    466   PIP_TEST_PREFIX=bazel_pip
    467   TEST_ROOT=$(pwd)/${PIP_TEST_PREFIX}
    468   sudo rm -rf $TEST_ROOT
    469   mkdir -p $TEST_ROOT
    470   ln -s $(pwd)/tensorflow $TEST_ROOT/tensorflow
    471 
    472   if [[ "${IS_OSS_SERIAL}" == "1" ]]; then
    473     remove_test_filter_tag -no_oss
    474     add_test_filter_tag oss_serial
    475   else
    476     add_test_filter_tag -oss_serial
    477   fi
    478 
    479   # Clean the bazel cache
    480   bazel clean
    481   # Clean up flags before running bazel commands
    482   update_bazel_flags
    483   # Clean up and update test filter tags
    484   update_test_filter_tags
    485 
    486   # Figure out how many concurrent tests we can run and do run the tests.
    487   BAZEL_PARALLEL_TEST_FLAGS=""
    488   if [[ $CONTAINER_TYPE == "gpu" ]]; then
    489     # Number of test threads is the number of GPU cards available.
    490     if [[ $OS_TYPE == "macos" ]]; then
    491       BAZEL_PARALLEL_TEST_FLAGS="--local_test_jobs=1"
    492     else
    493       BAZEL_PARALLEL_TEST_FLAGS="--local_test_jobs=${TF_GPU_COUNT} \
    494         --run_under=//tensorflow/tools/ci_build/gpu_build:parallel_gpu_execute"
    495     fi
    496   else
    497     # Number of test threads is the number of physical CPUs.
    498     if [[ $OS_TYPE == "macos" ]]; then
    499       BAZEL_PARALLEL_TEST_FLAGS="--local_test_jobs=$(sysctl -n hw.ncpu)"
    500     else
    501       BAZEL_PARALLEL_TEST_FLAGS="--local_test_jobs=$(grep -c ^processor /proc/cpuinfo)"
    502     fi
    503   fi
    504 
    505   if [[ ${IS_OSS_SERIAL} == 1 ]]; then
    506     BAZEL_PARALLEL_TEST_FLAGS="--local_test_jobs=1"
    507   fi
    508 
    509   TEST_TARGETS_SYMLINK=""
    510   for TARGET in ${TF_TEST_TARGETS[@]}; do
    511     TARGET_NEW=$(echo ${TARGET} | sed -e "s/\/\//\/\/${PIP_TEST_PREFIX}\//g")
    512     TEST_TARGETS_SYMLINK+="${TARGET_NEW} "
    513   done
    514   echo "Test targets (symlink): ${TEST_TARGETS_SYMLINK}"
    515 
    516   # Run the test.
    517   bazel test --build_tests_only ${TF_TEST_FLAGS} ${BAZEL_PARALLEL_TEST_FLAGS} --test_tag_filters=${TF_TEST_FILTER_TAGS} -k -- ${TEST_TARGETS_SYMLINK}
    518 
    519   unlink ${TEST_ROOT}/tensorflow
    520 }
    521 
    522 run_all_tests() {
    523   if [[ -z "${PIP_TESTS}" ]]; then
    524     echo "No test was specified to run. Skipping all tests."
    525     return 0
    526   fi
    527   FAIL_COUNTER=0
    528   PASS_COUNTER=0
    529   for TEST in ${PIP_TESTS[@]}; do
    530 
    531     # Run tests.
    532     case "${TEST}" in
    533     "test_pip_virtualenv_clean")
    534       test_pip_virtualenv venv_clean --clean
    535       ;;
    536     "test_pip_virtualenv_non_clean")
    537       test_pip_virtualenv venv
    538       ;;
    539     "test_pip_virtualenv_oss_serial")
    540       test_pip_virtualenv venv_oss --oss_serial
    541       ;;
    542     *)
    543       die "No matching test ${TEST} was found. Stopping test."
    544       ;;
    545     esac
    546 
    547     # Check and update the results.
    548     RETVAL=$?
    549 
    550     # Update results counter
    551     if [ ${RETVAL} -eq 0 ]; then
    552       echo "Test (${TEST}) PASSED. (PASS COUNTER: ${PASS_COUNTER})"
    553       PASS_COUNTER=$(($PASS_COUNTER+1))
    554     else
    555       echo "Test (${TEST}) FAILED. (FAIL COUNTER: ${FAIL_COUNTER})"
    556       FAIL_COUNTER=$(($FAIL_COUNTER+1))
    557     fi
    558   done
    559   printf "${PASS_COUNTER} PASSED | ${FAIL_COUNTER} FAILED"
    560   if [[ "${FAIL_COUNTER}" == "0" ]]; then
    561     printf "PIP tests ${COLOR_GREEN}PASSED${COLOR_NC}\n"
    562     return 0
    563   else:
    564     printf "PIP tests ${COLOR_RED}FAILED${COLOR_NC}\n"
    565     return 1
    566   fi
    567 }
    568 
    569 ###########################################################################
    570 # Build TF PIP Wheel file
    571 ###########################################################################
    572 
    573 # Update the build flags for building whl.
    574 # Flags: GPU, OS, tf_nightly, project name
    575 GPU_FLAG=""
    576 NIGHTLY_FLAG=""
    577 
    578 # TF Nightly flag
    579 if [[ "$IS_NIGHTLY" == 1 ]]; then
    580   # If 'nightly' is not specified in the project name already, then add.
    581   if ! [[ $PROJECT_NAME == *"nightly"* ]]; then
    582     echo "WARNING: IS_NIGHTLY=${IS_NIGHTLY} but requested project name \
    583     (PROJECT_NAME=${PROJECT_NAME}) does not include 'nightly' string. \
    584     Renaming it to 'tf_nightly'."
    585     PROJECT_NAME="tf_nightly"
    586   fi
    587   NIGHTLY_FLAG="--nightly_flag"
    588 fi
    589 
    590 # CPU / GPU flag
    591 if [[ ${CONTAINER_TYPE} == "gpu" ]]; then
    592   GPU_FLAG="--gpu"
    593   if ! [[ $PROJECT_NAME == *"gpu"* ]]; then
    594     echo "WARNING: GPU is specified but requested project name (PROJECT_NAME=${PROJECT_NAME}) \
    595     does not include 'gpu'. Appending '_gpu' to the project name."
    596     PROJECT_NAME="${PROJECT_NAME}_gpu"
    597   fi
    598 fi
    599 
    600 ./bazel-bin/tensorflow/tools/pip_package/build_pip_package ${PIP_WHL_DIR} ${GPU_FLAG} ${NIGHTLY_FLAG} "--project_name" ${PROJECT_NAME} || die "build_pip_package FAILED"
    601 
    602 PY_DOTLESS_MAJOR_MINOR_VER=$(echo $PY_MAJOR_MINOR_VER | tr -d '.')
    603 if [[ $PY_DOTLESS_MAJOR_MINOR_VER == "2" ]]; then
    604   PY_DOTLESS_MAJOR_MINOR_VER="27"
    605 fi
    606 
    607 # Set wheel path and verify that there is only one .whl file in the path.
    608 WHL_PATH=$(ls "${PIP_WHL_DIR}"/"${PROJECT_NAME}"-*"${PY_DOTLESS_MAJOR_MINOR_VER}"*"${PY_DOTLESS_MAJOR_MINOR_VER}"*.whl)
    609 if [[ $(echo "${WHL_PATH}" | wc -w) -ne 1 ]]; then
    610   echo "ERROR: Failed to find exactly one built TensorFlow .whl file in "\
    611   "directory: ${PIP_WHL_DIR}"
    612 fi
    613 
    614 WHL_DIR=$(dirname "${WHL_PATH}")
    615 WHL_BASE_NAME=$(basename "${WHL_PATH}")
    616 AUDITED_WHL_NAME="${WHL_DIR}"/$(echo "${WHL_BASE_NAME//linux/manylinux1}")
    617 
    618 # Print the size of the wheel file.
    619 echo "Size of the PIP wheel file built: $(ls -l ${WHL_PATH} | awk '{print $5}')"
    620 
    621 # Run tests (if any is specified).
    622 run_all_tests
    623 
    624 for WHL_PATH in $(ls ${PIP_WHL_DIR}/${PROJECT_NAME}*.whl); do
    625   if [[ "${TF_NEED_CUDA}" -eq "1" ]]; then
    626     # Copy and rename for gpu manylinux as we do not want auditwheel to package in libcudart.so
    627     WHL_PATH=${AUDITED_WHL_NAME}
    628     cp "${WHL_DIR}"/"${WHL_BASE_NAME}" "${WHL_PATH}"
    629     echo "Copied manylinux1 wheel file at ${WHL_PATH}"
    630   else
    631     if [[ ${OS_TYPE} == "ubuntu" ]]; then
    632       # Avoid Python3.6 abnormality by installing auditwheel here.
    633       pip3 show auditwheel
    634       set +e
    635       pip3 install auditwheel==1.5.0
    636       sudo pip3 install auditwheel==1.5.0
    637       set -e
    638       auditwheel --version
    639 
    640       # Repair the wheels for cpu manylinux1
    641       echo "auditwheel repairing ${WHL_PATH}"
    642       auditwheel repair -w "${WHL_DIR}" "${WHL_PATH}"
    643 
    644       if [[ -f ${AUDITED_WHL_NAME} ]]; then
    645         WHL_PATH=${AUDITED_WHL_NAME}
    646         echo "Repaired manylinux1 wheel file at: ${WHL_PATH}"
    647       else
    648         die "WARNING: Cannot find repaired wheel."
    649       fi
    650     fi
    651   fi
    652 done
    653 
    654 echo "EOF: Successfully ran pip_new.sh"
    655