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 # 17 # Usage: 18 # ci_parameterized_build.sh 19 # 20 # The script obeys the following required environment variables: 21 # TF_BUILD_CONTAINER_TYPE: (CPU | GPU | ANDROID | ANDROID_FULL) 22 # TF_BUILD_PYTHON_VERSION: (PYTHON2 | PYTHON3 | PYTHON3.5) 23 # TF_BUILD_IS_PIP: (NO_PIP | PIP | BOTH) 24 # 25 # The below environment variable is required, but will be deprecated together 26 # with TF_BUILD_MAVX and both will be replaced by TF_BUILD_OPTIONS. 27 # TF_BUILD_IS_OPT: (NO_OPT | OPT) 28 # 29 # Note: 30 # 1) Certain combinations of parameter values are regarded 31 # as invalid and will cause the script to exit with code 0. For example: 32 # NO_OPT & PIP (PIP builds should always use OPT) 33 # ANDROID & PIP (Android and PIP builds are mutually exclusive) 34 # 35 # 2) TF_BUILD_PYTHON_VERSION is set to PYTHON3, the build will use the version 36 # pointed to by "which python3" on the system, which is typically python3.4. To 37 # build for python3.5, set the environment variable to PYTHON3.5 38 # 39 # 40 # Additionally, the script follows the directions of optional environment 41 # variables: 42 # TF_BUILD_DRY_RUN: If it is set to any non-empty value that is not "0", 43 # the script will just generate and print the final 44 # command, but not actually run it. 45 # TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS: 46 # String appended to the content of CI_DOCKER_EXTRA_PARAMS 47 # TF_BUILD_APPEND_ARGUMENTS: 48 # Additional command line arguments for the bazel, 49 # pip.sh or android.sh command 50 # TF_BUILD_MAVX: (Soon to be deprecated, use TF_BUILD_OPTIONS instead) 51 # (unset | MAVX | MAVX2) 52 # If set to MAVX or MAVX2, will cause bazel to use the 53 # additional flag --copt=-mavx or --copt=-mavx2, to 54 # perform AVX or AVX2 builds, respectively. This requires 55 # AVX- or AVX2-compatible CPUs. 56 # TF_BUILD_BAZEL_TARGET: 57 # Used to override the default bazel build target: 58 # //tensorflow/... -//tensorflow/compiler 59 # TF_BUILD_BAZEL_CLEAN: 60 # Will perform "bazel clean", if and only if this variable 61 # is set to any non-empty and non-0 value 62 # TF_BAZEL_BUILD_ONLY: 63 # If it is set to any non-empty value that is not "0", Bazel 64 # will only build specified targets 65 # TF_GPU_COUNT: 66 # Run this many parallel tests for serial builds. 67 # For now, only can be edited for PIP builds. 68 # TF_BUILD_TEST_TUTORIALS: 69 # If set to any non-empty and non-0 value, will perform 70 # tutorials tests (Applicable only if TF_BUILD_IS_PIP is 71 # PIP or BOTH). 72 # See builds/test_tutorials.sh 73 # TF_BUILD_INTEGRATION_TESTS: 74 # If set this will perform integration tests. See 75 # builds/integration_tests.sh. 76 # TF_BUILD_RUN_BENCHMARKS: 77 # If set to any non-empty and non-0 value, will perform 78 # the benchmark tests (see *_logged_benchmark targets in 79 # tools/test/BUILD) 80 # TF_BUILD_OPTIONS: 81 # (FASTBUILD | OPT | OPTDBG | MAVX | MAVX2_FMA | MAVX_DBG | 82 # MAVX2_FMA_DBG) 83 # Use the specified configurations when building. 84 # When set, overrides TF_BUILD_IS_OPT and TF_BUILD_MAVX 85 # options, as this will replace the two. 86 # TF_BUILD_TEST_TIMEOUT: 87 # Sets the value of bazel --test_timeout, defaults to -1 88 # which uses the bazel defaults. 89 # TF_SKIP_CONTRIB_TESTS: 90 # If set to any non-empty or non-0 value, will skip running 91 # contrib tests. 92 # TF_NIGHTLY: 93 # If this run is being used to build the tf_nightly pip 94 # packages. 95 # TF_CUDA_CLANG: 96 # If set to 1, builds and runs cuda_clang configuration. 97 # Only available inside GPU containers. 98 # 99 # This script can be used by Jenkins parameterized / matrix builds. 100 101 # Helper function: Convert to lower case 102 to_lower () { 103 echo "$1" | tr '[:upper:]' '[:lower:]' 104 } 105 106 # Helper function: Strip leading and trailing whitespaces 107 str_strip () { 108 echo -e "$1" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' 109 } 110 111 # Helper function: Exit on failure 112 die () { 113 echo $@ 114 exit 1 115 } 116 117 ########################################################## 118 # Default configuration 119 CI_BUILD_DIR="tensorflow/tools/ci_build" 120 121 # Command to call when Docker is available 122 DOCKER_MAIN_CMD="${CI_BUILD_DIR}/ci_build.sh" 123 # Command to call when Docker is unavailable 124 NO_DOCKER_MAIN_CMD="${CI_BUILD_DIR}/builds/configured" 125 126 # Additional option flags to apply when Docker is unavailable (e.g., on Mac) 127 NO_DOCKER_OPT_FLAG="--genrule_strategy=standalone" 128 129 DO_DOCKER=1 130 131 # Default values for various settings. 132 TF_BUILD_TEST_TIMEOUT=${TF_BUILD_TEST_TIMEOUT:--1} # Use bazel defaults 133 TF_GPU_COUNT=${TF_GPU_COUNT:-4} 134 135 # Helpful flags: 136 # --test_summary=detailed: Tell us more about which targets are being built 137 # --keep_going: Don't stop at the first failure; tell us all the failures 138 # --build_tests_only: Don't build targets depended on by tests if the test is 139 # disabled. Also saves some compilation time. Otherwise, 140 # tries to build everything. 141 # --test_timeout: Test timeouts in the order short,moderate,long,eternal. 142 # --test_env: Environment variables to set when running bazel tests. These are 143 # especially important when using --run_under with 144 # parallel_gpu_execute. 145 BAZEL_TEST_FLAGS=""\ 146 "--test_summary=detailed --build_tests_only --keep_going "\ 147 "--test_timeout=${TF_BUILD_TEST_TIMEOUT} "\ 148 "--test_env=TF_GPU_COUNT=${TF_GPU_COUNT}" 149 150 # Only set these environment variables if they're specified, to avoid causing 151 # problems like b/118404869, where an envvar set to the empty string has 152 # different semantics from an unset envvar. 153 if [ -n "${TF_TESTS_PER_GPU}" ]; then 154 BAZEL_TEST_FLAGS="${BAZEL_TEST_FLAGS} "\ 155 "--test_env=TF_TESTS_PER_GPU=${TF_TESTS_PER_GPU}" 156 fi 157 if [ -n "${TF_PER_DEVICE_MEMORY_LIMIT_MB}" ]; then 158 BAZEL_TEST_FLAGS="${BAZEL_TEST_FLAGS} "\ 159 "--test_env=TF_PER_DEVICE_MEMORY_LIMIT_MB=${TF_PER_DEVICE_MEMORY_LIMIT_MB}" 160 fi 161 162 BAZEL_BUILD_FLAGS="--keep_going" 163 164 # Explicitly set jdk8 since that's what's installed in our images. Note that 165 # bazel 0.16 and higher defaults to jdk9, which causes failures. See b/117634064 166 BAZEL_JAVA_FLAGS="--java_toolchain=@bazel_tools//tools/jdk:toolchain_hostjdk8" 167 168 BAZEL_CMD="bazel test ${BAZEL_TEST_FLAGS} ${BAZEL_JAVA_FLAGS}" 169 BAZEL_BUILD_ONLY_CMD="bazel build ${BAZEL_BUILD_FLAGS} ${BAZEL_JAVA_FLAGS}" 170 BAZEL_CLEAN_CMD="bazel clean" 171 172 PIP_CMD="${CI_BUILD_DIR}/builds/pip.sh" 173 PIP_TEST_TUTORIALS_FLAG="--test_tutorials" 174 PIP_INTEGRATION_TESTS_FLAG="--integration_tests" 175 ANDROID_CMD="${CI_BUILD_DIR}/builds/android.sh" 176 ANDROID_FULL_CMD="${CI_BUILD_DIR}/builds/android_full.sh" 177 178 PARALLEL_GPU_TEST_CMD='//tensorflow/tools/ci_build/gpu_build:parallel_gpu_execute' 179 180 BENCHMARK_CMD="${CI_BUILD_DIR}/builds/benchmark.sh" 181 182 EXTRA_PARAMS="" 183 BAZEL_TARGET="//tensorflow/... -//tensorflow/compiler/..." 184 185 if [[ -n "$TF_SKIP_CONTRIB_TESTS" ]]; then 186 BAZEL_TARGET="${BAZEL_TARGET} -//tensorflow/contrib/..." 187 fi 188 189 TUT_TEST_DATA_DIR="/tmp/tf_tutorial_test_data" 190 191 ########################################################## 192 193 echo "Parameterized build starts at: $(date)" 194 echo "" 195 START_TIME=$(date +'%s') 196 197 # Convert all the required environment variables to lower case 198 TF_BUILD_CONTAINER_TYPE=$(to_lower ${TF_BUILD_CONTAINER_TYPE}) 199 TF_BUILD_PYTHON_VERSION=$(to_lower ${TF_BUILD_PYTHON_VERSION}) 200 TF_BUILD_IS_OPT=$(to_lower ${TF_BUILD_IS_OPT}) 201 TF_BUILD_IS_PIP=$(to_lower ${TF_BUILD_IS_PIP}) 202 203 if [[ ! -z "${TF_BUILD_MAVX}" ]]; then 204 TF_BUILD_MAVX=$(to_lower ${TF_BUILD_MAVX}) 205 fi 206 207 208 # Print parameter values 209 echo "Required build parameters:" 210 echo " TF_BUILD_CONTAINER_TYPE=${TF_BUILD_CONTAINER_TYPE}" 211 echo " TF_BUILD_PYTHON_VERSION=${TF_BUILD_PYTHON_VERSION}" 212 echo " TF_BUILD_IS_OPT=${TF_BUILD_IS_OPT}" 213 echo " TF_BUILD_IS_PIP=${TF_BUILD_IS_PIP}" 214 echo "Optional build parameters:" 215 echo " TF_BUILD_DRY_RUN=${TF_BUILD_DRY_RUN}" 216 echo " TF_BUILD_MAVX=${TF_BUILD_MAVX}" 217 echo " TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="\ 218 "${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}" 219 echo " TF_BUILD_APPEND_ARGUMENTS=${TF_BUILD_APPEND_ARGUMENTS}" 220 echo " TF_BUILD_BAZEL_TARGET=${TF_BUILD_BAZEL_TARGET}" 221 echo " TF_BUILD_BAZEL_CLEAN=${TF_BUILD_BAZEL_CLEAN}" 222 echo " TF_BUILD_TEST_TUTORIALS=${TF_BUILD_TEST_TUTORIALS}" 223 echo " TF_BUILD_INTEGRATION_TESTS=${TF_BUILD_INTEGRATION_TESTS}" 224 echo " TF_BUILD_RUN_BENCHMARKS=${TF_BUILD_RUN_BENCHMARKS}" 225 echo " TF_BUILD_OPTIONS=${TF_BUILD_OPTIONS}" 226 227 228 # Function that tries to determine CUDA capability, if deviceQuery binary 229 # is available on path 230 function get_cuda_capability_version() { 231 if [[ ! -z $(which deviceQuery) ]]; then 232 # The first listed device is used 233 deviceQuery | grep "CUDA Capability .* version" | \ 234 head -1 | awk '{print $NF}' 235 fi 236 } 237 238 # Container type, e.g., CPU, GPU 239 CTYPE=${TF_BUILD_CONTAINER_TYPE} 240 241 # Determine if the machine is a Mac 242 OPT_FLAG="--test_output=errors" 243 if [[ "$(uname -s)" == "Darwin" ]]; then 244 DO_DOCKER=0 245 246 echo "It appears this machine is a Mac. "\ 247 "We will perform this build without Docker." 248 echo "Also, the additional option flags will be applied to the build:" 249 echo " ${NO_DOCKER_OPT_FLAG}" 250 MAIN_CMD="${NO_DOCKER_MAIN_CMD} ${CTYPE}" 251 OPT_FLAG="${OPT_FLAG} ${NO_DOCKER_OPT_FLAG}" 252 fi 253 254 # In DO_DOCKER mode, appends environment variable to docker's run invocation. 255 # Otherwise, exports the corresponding variable. 256 function set_script_variable() { 257 local VAR="$1" 258 local VALUE="$2" 259 if [[ $DO_DOCKER == "1" ]]; then 260 TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS} -e $VAR=$VALUE" 261 else 262 export $VAR="$VALUE" 263 fi 264 } 265 266 267 # Process container type 268 if [[ ${CTYPE} == cpu* ]] || [[ ${CTYPE} == "debian.jessie.cpu" ]]; then 269 : 270 elif [[ ${CTYPE} == gpu* ]]; then 271 set_script_variable TF_NEED_CUDA 1 272 273 if [[ $TF_CUDA_CLANG == "1" ]]; then 274 OPT_FLAG="${OPT_FLAG} --config=cuda_clang" 275 276 set_script_variable TF_CUDA_CLANG 1 277 # For cuda_clang we download `clang` while building. 278 set_script_variable TF_DOWNLOAD_CLANG 1 279 else 280 OPT_FLAG="${OPT_FLAG} --config=cuda" 281 fi 282 283 # Attempt to determine CUDA capability version automatically and use it if 284 # CUDA capability version is not specified by the environment variables. 285 CUDA_CAPA_VER=$(get_cuda_capability_version) 286 287 if [[ ! -z ${CUDA_CAPA_VER} ]]; then 288 AUTO_CUDA_CAPA_VER=0 289 if [[ ${DO_DOCKER} == "1" ]] && \ 290 [[ "${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}" != \ 291 *"TF_CUDA_COMPUTE_CAPABILITIES="* ]]; then 292 AUTO_CUDA_CAPA_VER=1 293 TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS=\ 294 "${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS} -e "\ 295 "TF_CUDA_COMPUTE_CAPABILITIES=${CUDA_CAPA_VER}" 296 297 echo "Docker GPU build: TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS="\ 298 "\"${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}\"" 299 elif [[ ${DO_DOCKER} == "0" ]] && \ 300 [[ -z "${TF_CUDA_COMPUTE_CAPABILITIES}" ]]; then 301 AUTO_CUDA_CAPA_VER=1 302 TF_CUDA_COMPUTE_CAPABILITIES="${CUDA_CAPA_VER}" 303 304 echo "Non-Docker GPU build: TF_CUDA_COMPUTE_CAPABILITIES="\ 305 "\"${TF_CUDA_COMPUTE_CAPABILITIES}\"" 306 fi 307 308 if [[ ${AUTO_CUDA_CAPA_VER} == "1" ]]; then 309 echo "TF_CUDA_COMPUTE_CAPABILITIES is not set:" 310 echo "Using CUDA capability version from deviceQuery: ${CUDA_CAPA_VER}" 311 echo "" 312 fi 313 fi 314 elif [[ ${CTYPE} == "android" ]] || [[ ${CTYPE} == "android_full" ]]; then 315 : 316 else 317 die "Unrecognized value in TF_BUILD_CONTAINER_TYPE: "\ 318 "\"${TF_BUILD_CONTAINER_TYPE}\"" 319 fi 320 321 # Determine if this is a benchmarks job 322 RUN_BENCHMARKS=0 323 if [[ ! -z "${TF_BUILD_RUN_BENCHMARKS}" ]] && 324 [[ "${TF_BUILD_RUN_BENCHMARKS}" != "0" ]]; then 325 RUN_BENCHMARKS=1 326 fi 327 328 # Process Bazel "-c opt" flag 329 if [[ -z "${TF_BUILD_OPTIONS}" ]]; then 330 if [[ ${TF_BUILD_IS_OPT} == "no_opt" ]]; then 331 # PIP builds are done only with the -c opt flag 332 if [[ ${TF_BUILD_IS_PIP} == "pip" ]]; then 333 echo "Skipping parameter combination: ${TF_BUILD_IS_OPT} & "\ 334 "${TF_BUILD_IS_PIP}" 335 exit 0 336 fi 337 338 elif [[ ${TF_BUILD_IS_OPT} == "opt" ]]; then 339 OPT_FLAG="${OPT_FLAG} -c opt" 340 else 341 die "Unrecognized value in TF_BUILD_IS_OPT: \"${TF_BUILD_IS_OPT}\"" 342 fi 343 344 # Process MAVX option 345 if [[ ! -z "${TF_BUILD_MAVX}" ]]; then 346 if [[ "${TF_BUILD_MAVX}" == "mavx" ]]; then 347 OPT_FLAG="${OPT_FLAG} --copt=-mavx" 348 elif [[ "${TF_BUILD_MAVX}" == "mavx2" ]]; then 349 OPT_FLAG="${OPT_FLAG} --copt=-mavx2" 350 else 351 die "Unsupported value in TF_BUILD_MAVX: ${TF_BUILD_MAVX}" 352 fi 353 fi 354 else 355 case $TF_BUILD_OPTIONS in 356 FASTBUILD) 357 echo "Running FASTBUILD mode (noopt, nodbg)." 358 ;; 359 OPT) 360 OPT_FLAG="${OPT_FLAG} -c opt" 361 ;; 362 OPTDBG) 363 OPT_FLAG="${OPT_FLAG} -c opt --copt=-g" 364 ;; 365 MAVX) 366 OPT_FLAG="${OPT_FLAG} -c opt --copt=-mavx" 367 ;; 368 MAVX_DBG) 369 OPT_FLAG="${OPT_FLAG} -c opt --copt=-g --copt=-mavx" 370 ;; 371 MAVX2_FMA) 372 OPT_FLAG="${OPT_FLAG} -c opt --copt=-mavx2 --copt=-mfma" 373 ;; 374 MAVX2_FMA_DBG) 375 OPT_FLAG="${OPT_FLAG} -c opt --copt=-g --copt=-mavx2 --copt=-mfma" 376 ;; 377 esac 378 fi 379 380 # Strip whitespaces from OPT_FLAG 381 OPT_FLAG=$(str_strip "${OPT_FLAG}") 382 383 384 # 1) Filter out benchmark tests if this is not a benchmarks job; 385 # 2) Filter out tests with the "nomac" tag if the build is on Mac OS X. 386 EXTRA_ARGS=${DEFAULT_BAZEL_CONFIGS} 387 IS_MAC=0 388 if [[ "$(uname)" == "Darwin" ]]; then 389 IS_MAC=1 390 fi 391 if [[ "${TF_BUILD_APPEND_ARGUMENTS}" == *"--test_tag_filters="* ]]; then 392 ITEMS=(${TF_BUILD_APPEND_ARGUMENTS}) 393 394 for ITEM in "${ITEMS[@]}"; do 395 if [[ ${ITEM} == *"--test_tag_filters="* ]]; then 396 NEW_ITEM="${ITEM}" 397 if [[ ${NEW_ITEM} != *"benchmark-test"* ]]; then 398 NEW_ITEM="${NEW_ITEM},-benchmark-test" 399 fi 400 if [[ ${IS_MAC} == "1" ]] && [[ ${NEW_ITEM} != *"nomac"* ]]; then 401 # TODO(b/122370901): Fix nomac, no_mac inconsistency. 402 NEW_ITEM="${NEW_ITEM},-nomac,-no_mac" 403 fi 404 EXTRA_ARGS="${EXTRA_ARGS} ${NEW_ITEM}" 405 else 406 EXTRA_ARGS="${EXTRA_ARGS} ${ITEM}" 407 fi 408 done 409 else 410 EXTRA_ARGS="${EXTRA_ARGS} ${TF_BUILD_APPEND_ARGUMENTS} --test_tag_filters=-no_oss,-oss_serial,-benchmark-test" 411 if [[ ${IS_MAC} == "1" ]]; then 412 # TODO(b/122370901): Fix nomac, no_mac inconsistency. 413 EXTRA_ARGS="${EXTRA_ARGS},-nomac,-no_mac" 414 fi 415 EXTRA_ARGS="${EXTRA_ARGS} --build_tag_filters=-no_oss,-oss_serial,-benchmark-test" 416 if [[ ${IS_MAC} == "1" ]]; then 417 # TODO(b/122370901): Fix nomac, no_mac inconsistency. 418 EXTRA_ARGS="${EXTRA_ARGS},-nomac,-no_mac" 419 fi 420 fi 421 422 # For any "tool" dependencies in genrules, Bazel will build them for host 423 # instead of the target configuration. We can save some build time by setting 424 # this flag, and it only affects a few tests. 425 EXTRA_ARGS="${EXTRA_ARGS} --distinct_host_configuration=false" 426 427 if [[ ! -z "${TF_BAZEL_BUILD_ONLY}" ]] && 428 [[ "${TF_BAZEL_BUILD_ONLY}" != "0" ]];then 429 BAZEL_CMD=${BAZEL_BUILD_ONLY_CMD} 430 fi 431 432 # Process PIP install-test option 433 if [[ ${TF_BUILD_IS_PIP} == "no_pip" ]] || 434 [[ ${TF_BUILD_IS_PIP} == "both" ]]; then 435 # Process optional bazel target override 436 if [[ ! -z "${TF_BUILD_BAZEL_TARGET}" ]]; then 437 BAZEL_TARGET=${TF_BUILD_BAZEL_TARGET} 438 fi 439 440 if [[ ${CTYPE} == cpu* ]] || \ 441 [[ ${CTYPE} == "debian.jessie.cpu" ]]; then 442 # CPU only command, fully parallel. 443 NO_PIP_MAIN_CMD="${MAIN_CMD} ${BAZEL_CMD} ${OPT_FLAG} "\ 444 "${EXTRA_ARGS} -- ${BAZEL_TARGET}" 445 elif [[ ${CTYPE} == gpu* ]]; then 446 # GPU only command, run as many jobs as the GPU count only. 447 NO_PIP_MAIN_CMD="${BAZEL_CMD} ${OPT_FLAG} "\ 448 "--local_test_jobs=${TF_GPU_COUNT} "\ 449 "--run_under=${PARALLEL_GPU_TEST_CMD} "\ 450 "${EXTRA_ARGS} -- ${BAZEL_TARGET}" 451 elif [[ ${CTYPE} == "android" ]]; then 452 # Run android specific script for android build. 453 NO_PIP_MAIN_CMD="${ANDROID_CMD} ${OPT_FLAG} " 454 elif [[ ${CTYPE} == "android_full" ]]; then 455 # Run android specific script for full android build. 456 NO_PIP_MAIN_CMD="${ANDROID_FULL_CMD} ${OPT_FLAG} " 457 fi 458 459 fi 460 461 if [[ ${TF_BUILD_IS_PIP} == "pip" ]] || 462 [[ ${TF_BUILD_IS_PIP} == "both" ]]; then 463 # Android builds conflict with PIP builds 464 if [[ ${CTYPE} == "android" ]]; then 465 echo "Skipping parameter combination: ${TF_BUILD_IS_PIP} & "\ 466 "${TF_BUILD_CONTAINER_TYPE}" 467 exit 0 468 fi 469 470 PIP_MAIN_CMD="${MAIN_CMD} ${PIP_CMD} ${CTYPE} ${EXTRA_ARGS} ${OPT_FLAG}" 471 472 # Add flag for integration tests 473 if [[ ! -z "${TF_BUILD_INTEGRATION_TESTS}" ]] && 474 [[ "${TF_BUILD_INTEGRATION_TESTS}" != "0" ]]; then 475 PIP_MAIN_CMD="${PIP_MAIN_CMD} ${PIP_INTEGRATION_TESTS_FLAG}" 476 fi 477 478 # Add command for tutorial test 479 if [[ ! -z "${TF_BUILD_TEST_TUTORIALS}" ]] && 480 [[ "${TF_BUILD_TEST_TUTORIALS}" != "0" ]]; then 481 PIP_MAIN_CMD="${PIP_MAIN_CMD} ${PIP_TEST_TUTORIALS_FLAG}" 482 483 # Prepare data directory for tutorial tests 484 mkdir -p "${TUT_TEST_DATA_DIR}" || 485 die "FAILED to create data directory for tutorial tests: "\ 486 "${TUT_TEST_DATA_DIR}" 487 488 if [[ "${DO_DOCKER}" == "1" ]]; then 489 EXTRA_PARAMS="${EXTRA_PARAMS} -v ${TUT_TEST_DATA_DIR}:${TUT_TEST_DATA_DIR}" 490 fi 491 fi 492 fi 493 494 495 if [[ ${RUN_BENCHMARKS} == "1" ]]; then 496 MAIN_CMD="${BENCHMARK_CMD} ${OPT_FLAG}" 497 elif [[ ${TF_BUILD_IS_PIP} == "no_pip" ]]; then 498 MAIN_CMD="${NO_PIP_MAIN_CMD}" 499 elif [[ ${TF_BUILD_IS_PIP} == "pip" ]]; then 500 MAIN_CMD="${PIP_MAIN_CMD}" 501 elif [[ ${TF_BUILD_IS_PIP} == "both" ]]; then 502 MAIN_CMD="${NO_PIP_MAIN_CMD} && ${PIP_MAIN_CMD}" 503 else 504 die "Unrecognized value in TF_BUILD_IS_PIP: \"${TF_BUILD_IS_PIP}\"" 505 fi 506 507 # Check if this is a tf_nightly build 508 if [[ "${TF_NIGHTLY}" == "1" ]]; then 509 EXTRA_PARAMS="${EXTRA_PARAMS} -e TF_NIGHTLY=1" 510 fi 511 512 # Process Python version 513 if [[ ${TF_BUILD_PYTHON_VERSION} == "python2" ]]; then 514 : 515 elif [[ ${TF_BUILD_PYTHON_VERSION} == "python3" || \ 516 ${TF_BUILD_PYTHON_VERSION} == "python3.4" || \ 517 ${TF_BUILD_PYTHON_VERSION} == "python3.5" || \ 518 ${TF_BUILD_PYTHON_VERSION} == "python3.6" ]]; then 519 # Supply proper environment variable to select Python 3 520 if [[ "${DO_DOCKER}" == "1" ]]; then 521 EXTRA_PARAMS="${EXTRA_PARAMS} -e CI_BUILD_PYTHON=${TF_BUILD_PYTHON_VERSION}" 522 else 523 # Determine the path to python3 524 PYTHON3_PATH=$(which "${TF_BUILD_PYTHON_VERSION}" | head -1) 525 if [[ -z "${PYTHON3_PATH}" ]]; then 526 die "ERROR: Failed to locate ${TF_BUILD_PYTHON_VERSION} binary on path" 527 else 528 echo "Found ${TF_BUILD_PYTHON_VERSION} binary at: ${PYTHON3_PATH}" 529 fi 530 531 export PYTHON_BIN_PATH="${PYTHON3_PATH}" 532 fi 533 534 else 535 die "Unrecognized value in TF_BUILD_PYTHON_VERSION: "\ 536 "\"${TF_BUILD_PYTHON_VERSION}\"" 537 fi 538 539 # Append additional Docker extra parameters 540 EXTRA_PARAMS="${EXTRA_PARAMS} ${TF_BUILD_APPEND_CI_DOCKER_EXTRA_PARAMS}" 541 542 # Finally, do a dry run or call the command 543 544 # The command, which may consist of multiple parts (e.g., in the case of 545 # TF_BUILD_SERIAL_TESTS=1), are written to a bash script, which is 546 # then called. The name of the script is randomized to make concurrent 547 # builds on the node possible. 548 TMP_SCRIPT="$(mktemp)_ci_parameterized_build.sh" 549 550 if [[ "${DO_DOCKER}" == "1" ]]; then 551 # Map the tmp script into the Docker container 552 EXTRA_PARAMS="${EXTRA_PARAMS} -v ${TMP_SCRIPT}:/tmp/tf_build.sh" 553 554 if [[ ! -z "${TF_BUILD_BAZEL_CLEAN}" ]] && 555 [[ "${TF_BUILD_BAZEL_CLEAN}" != "0" ]] && 556 [[ "${TF_BUILD_IS_PIP}" != "both" ]]; then 557 # For TF_BUILD_IS_PIP == both, "bazel clean" will have already 558 # been performed before the "bazel test" step 559 EXTRA_PARAMS="${EXTRA_PARAMS} -e TF_BUILD_BAZEL_CLEAN=1" 560 fi 561 562 EXTRA_PARAMS=$(str_strip "${EXTRA_PARAMS}") 563 564 echo "Exporting CI_DOCKER_EXTRA_PARAMS: ${EXTRA_PARAMS}" 565 export CI_DOCKER_EXTRA_PARAMS="${EXTRA_PARAMS}" 566 fi 567 568 # Write to the tmp script 569 echo "#!/usr/bin/env bash" > ${TMP_SCRIPT} 570 if [[ ! -z "${TF_BUILD_BAZEL_CLEAN}" ]] && 571 [[ "${TF_BUILD_BAZEL_CLEAN}" != "0" ]]; then 572 echo ${BAZEL_CLEAN_CMD} >> ${TMP_SCRIPT} 573 fi 574 echo ${MAIN_CMD} >> ${TMP_SCRIPT} 575 576 echo "Executing final command (${TMP_SCRIPT})..." 577 echo "==========================================" 578 cat ${TMP_SCRIPT} 579 echo "==========================================" 580 echo "" 581 582 583 TMP_DIR="" 584 DOCKERFILE_FLAG="" 585 if [[ "${DO_DOCKER}" == "1" ]]; then 586 if [[ "${TF_BUILD_PYTHON_VERSION}" == "python3.5" ]] || 587 [[ "${TF_BUILD_PYTHON_VERSION}" == "python3.6" ]]; then 588 # Modify Dockerfile for Python3.5 | Python3.6 build 589 TMP_DIR=$(mktemp -d) 590 echo "Docker build will occur in temporary directory: ${TMP_DIR}" 591 592 # Copy the files required for the docker build 593 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 594 cp -r "${SCRIPT_DIR}/install" "${TMP_DIR}/install" || \ 595 die "ERROR: Failed to copy directory ${SCRIPT_DIR}/install" 596 597 DOCKERFILE="${SCRIPT_DIR}/Dockerfile.${TF_BUILD_CONTAINER_TYPE}" 598 cp "${DOCKERFILE}" "${TMP_DIR}/" || \ 599 die "ERROR: Failed to copy Dockerfile at ${DOCKERFILE}" 600 DOCKERFILE="${TMP_DIR}/Dockerfile.${TF_BUILD_CONTAINER_TYPE}" 601 602 # Replace a line in the Dockerfile 603 if sed -i \ 604 "s/RUN \/install\/install_pip_packages.sh/RUN \/install\/install_${TF_BUILD_PYTHON_VERSION}_pip_packages.sh/g" \ 605 "${DOCKERFILE}" 606 then 607 echo "Copied and modified Dockerfile for ${TF_BUILD_PYTHON_VERSION} build: ${DOCKERFILE}" 608 else 609 die "ERROR: Faild to copy and modify Dockerfile: ${DOCKERFILE}" 610 fi 611 612 DOCKERFILE_FLAG="--dockerfile ${DOCKERFILE}" 613 fi 614 fi 615 616 # Set a disk usage trap. 617 function debug_disk_usage { 618 echo "Finished script... disk usage report in ${TMP_DIR}" 619 du -k -d 2 ${TMP_DIR} | sort -n -r 620 } 621 # trap debug_disk_usage EXIT 622 623 chmod +x ${TMP_SCRIPT} 624 625 # Map TF_BUILD container types to containers we actually have. 626 if [[ "${CTYPE}" == "android_full" ]]; then 627 CONTAINER="android" 628 else 629 CONTAINER=${CTYPE} 630 fi 631 632 FAILURE=0 633 if [[ ! -z "${TF_BUILD_DRY_RUN}" ]] && [[ ${TF_BUILD_DRY_RUN} != "0" ]]; then 634 # Do a dry run: just print the final command 635 echo "*** This is a DRY RUN ***" 636 else 637 # Actually run the command 638 if [[ "${DO_DOCKER}" == "1" ]]; then 639 ${DOCKER_MAIN_CMD} ${CONTAINER} ${DOCKERFILE_FLAG} /tmp/tf_build.sh 640 else 641 ${TMP_SCRIPT} 642 fi 643 644 if [[ $? != "0" ]]; then 645 FAILURE=1 646 fi 647 fi 648 649 [[ ${FAILURE} == "0" ]] && RESULT="SUCCESS" || RESULT="FAILURE" 650 651 rm -f ${TMP_SCRIPT} 652 653 END_TIME=$(date +'%s') 654 echo "" 655 echo "Parameterized build ends with ${RESULT} at: $(date) "\ 656 "(Elapsed time: $((END_TIME - START_TIME)) s)" 657 658 # Dump disk usage 659 debug_disk_usage 660 661 # Clean up temporary directory if it exists 662 if [[ ! -z "${TMP_DIR}" ]]; then 663 echo "Cleaning up temporary directory: ${TMP_DIR}" 664 rm -rf "${TMP_DIR}" 665 fi 666 667 exit ${FAILURE} 668