1*b16991f9SAndroid Build Coastguard Worker# Copyright 2020 The TensorFlow Authors. All rights reserved. 2*b16991f9SAndroid Build Coastguard Worker# 3*b16991f9SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*b16991f9SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*b16991f9SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*b16991f9SAndroid Build Coastguard Worker# 7*b16991f9SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*b16991f9SAndroid Build Coastguard Worker# 9*b16991f9SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*b16991f9SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*b16991f9SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*b16991f9SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*b16991f9SAndroid Build Coastguard Worker# limitations under the License. 14*b16991f9SAndroid Build Coastguard Worker 15*b16991f9SAndroid Build Coastguard Worker"""Utilities for defining TensorFlow Lite Support Bazel dependencies.""" 16*b16991f9SAndroid Build Coastguard Worker 17*b16991f9SAndroid Build Coastguard Worker_SINGLE_URL_WHITELIST = [] 18*b16991f9SAndroid Build Coastguard Worker 19*b16991f9SAndroid Build Coastguard Workerdef _is_windows(ctx): 20*b16991f9SAndroid Build Coastguard Worker return ctx.os.name.lower().find("windows") != -1 21*b16991f9SAndroid Build Coastguard Worker 22*b16991f9SAndroid Build Coastguard Workerdef _wrap_bash_cmd(ctx, cmd): 23*b16991f9SAndroid Build Coastguard Worker if _is_windows(ctx): 24*b16991f9SAndroid Build Coastguard Worker bazel_sh = _get_env_var(ctx, "BAZEL_SH") 25*b16991f9SAndroid Build Coastguard Worker if not bazel_sh: 26*b16991f9SAndroid Build Coastguard Worker fail("BAZEL_SH environment variable is not set") 27*b16991f9SAndroid Build Coastguard Worker cmd = [bazel_sh, "-l", "-c", " ".join(["\"%s\"" % s for s in cmd])] 28*b16991f9SAndroid Build Coastguard Worker return cmd 29*b16991f9SAndroid Build Coastguard Worker 30*b16991f9SAndroid Build Coastguard Workerdef _get_env_var(ctx, name): 31*b16991f9SAndroid Build Coastguard Worker if name in ctx.os.environ: 32*b16991f9SAndroid Build Coastguard Worker return ctx.os.environ[name] 33*b16991f9SAndroid Build Coastguard Worker else: 34*b16991f9SAndroid Build Coastguard Worker return None 35*b16991f9SAndroid Build Coastguard Worker 36*b16991f9SAndroid Build Coastguard Worker# Checks if we should use the system lib instead of the bundled one 37*b16991f9SAndroid Build Coastguard Workerdef _use_system_lib(ctx, name): 38*b16991f9SAndroid Build Coastguard Worker syslibenv = _get_env_var(ctx, "TF_SYSTEM_LIBS") 39*b16991f9SAndroid Build Coastguard Worker if syslibenv: 40*b16991f9SAndroid Build Coastguard Worker for n in syslibenv.strip().split(","): 41*b16991f9SAndroid Build Coastguard Worker if n.strip() == name: 42*b16991f9SAndroid Build Coastguard Worker return True 43*b16991f9SAndroid Build Coastguard Worker return False 44*b16991f9SAndroid Build Coastguard Worker 45*b16991f9SAndroid Build Coastguard Worker# Executes specified command with arguments and calls 'fail' if it exited with 46*b16991f9SAndroid Build Coastguard Worker# non-zero code 47*b16991f9SAndroid Build Coastguard Workerdef _execute_and_check_ret_code(repo_ctx, cmd_and_args): 48*b16991f9SAndroid Build Coastguard Worker result = repo_ctx.execute(cmd_and_args, timeout = 60) 49*b16991f9SAndroid Build Coastguard Worker if result.return_code != 0: 50*b16991f9SAndroid Build Coastguard Worker fail(("Non-zero return code({1}) when executing '{0}':\n" + "Stdout: {2}\n" + 51*b16991f9SAndroid Build Coastguard Worker "Stderr: {3}").format( 52*b16991f9SAndroid Build Coastguard Worker " ".join([str(x) for x in cmd_and_args]), 53*b16991f9SAndroid Build Coastguard Worker result.return_code, 54*b16991f9SAndroid Build Coastguard Worker result.stdout, 55*b16991f9SAndroid Build Coastguard Worker result.stderr, 56*b16991f9SAndroid Build Coastguard Worker )) 57*b16991f9SAndroid Build Coastguard Worker 58*b16991f9SAndroid Build Coastguard Worker# Apply a patch_file to the repository root directory 59*b16991f9SAndroid Build Coastguard Worker# Runs 'patch -p1' on both Windows and Unix. 60*b16991f9SAndroid Build Coastguard Workerdef _apply_patch(ctx, patch_file): 61*b16991f9SAndroid Build Coastguard Worker patch_command = ["patch", "-p1", "-d", ctx.path("."), "-i", ctx.path(patch_file)] 62*b16991f9SAndroid Build Coastguard Worker cmd = _wrap_bash_cmd(ctx, patch_command) 63*b16991f9SAndroid Build Coastguard Worker _execute_and_check_ret_code(ctx, cmd) 64*b16991f9SAndroid Build Coastguard Worker 65*b16991f9SAndroid Build Coastguard Workerdef _apply_delete(ctx, paths): 66*b16991f9SAndroid Build Coastguard Worker for path in paths: 67*b16991f9SAndroid Build Coastguard Worker if path.startswith("/"): 68*b16991f9SAndroid Build Coastguard Worker fail("refusing to rm -rf path starting with '/': " + path) 69*b16991f9SAndroid Build Coastguard Worker if ".." in path: 70*b16991f9SAndroid Build Coastguard Worker fail("refusing to rm -rf path containing '..': " + path) 71*b16991f9SAndroid Build Coastguard Worker cmd = _wrap_bash_cmd(ctx, ["rm", "-rf"] + [ctx.path(path) for path in paths]) 72*b16991f9SAndroid Build Coastguard Worker _execute_and_check_ret_code(ctx, cmd) 73*b16991f9SAndroid Build Coastguard Worker 74*b16991f9SAndroid Build Coastguard Workerdef _third_party_http_archive(ctx): 75*b16991f9SAndroid Build Coastguard Worker """Downloads and creates Bazel repos for dependencies. 76*b16991f9SAndroid Build Coastguard Worker 77*b16991f9SAndroid Build Coastguard Worker This is a swappable replacement for both http_archive() and 78*b16991f9SAndroid Build Coastguard Worker new_http_archive() that offers some additional features. It also helps 79*b16991f9SAndroid Build Coastguard Worker ensure best practices are followed. 80*b16991f9SAndroid Build Coastguard Worker """ 81*b16991f9SAndroid Build Coastguard Worker if ("mirror.tensorflow.org" not in ctx.attr.urls[0] and 82*b16991f9SAndroid Build Coastguard Worker (len(ctx.attr.urls) < 2 and 83*b16991f9SAndroid Build Coastguard Worker ctx.attr.name not in _SINGLE_URL_WHITELIST.to_list())): 84*b16991f9SAndroid Build Coastguard Worker fail("third_party_http_archive(urls) must have redundant URLs. The " + 85*b16991f9SAndroid Build Coastguard Worker "mirror.tensorflow.org URL must be present and it must come first. " + 86*b16991f9SAndroid Build Coastguard Worker "Even if you don't have permission to mirror the file, please " + 87*b16991f9SAndroid Build Coastguard Worker "put the correctly formatted mirror URL there anyway, because " + 88*b16991f9SAndroid Build Coastguard Worker "someone will come along shortly thereafter and mirror the file.") 89*b16991f9SAndroid Build Coastguard Worker 90*b16991f9SAndroid Build Coastguard Worker use_syslib = _use_system_lib(ctx, ctx.attr.name) 91*b16991f9SAndroid Build Coastguard Worker 92*b16991f9SAndroid Build Coastguard Worker # Use "BUILD.bazel" to avoid conflict with third party projects that contain a 93*b16991f9SAndroid Build Coastguard Worker # file or directory called "BUILD" 94*b16991f9SAndroid Build Coastguard Worker buildfile_path = ctx.path("BUILD.bazel") 95*b16991f9SAndroid Build Coastguard Worker 96*b16991f9SAndroid Build Coastguard Worker if use_syslib: 97*b16991f9SAndroid Build Coastguard Worker if ctx.attr.system_build_file == None: 98*b16991f9SAndroid Build Coastguard Worker fail("Bazel was configured with TF_SYSTEM_LIBS to use a system " + 99*b16991f9SAndroid Build Coastguard Worker "library for %s, but no system build file for %s was configured. " + 100*b16991f9SAndroid Build Coastguard Worker "Please add a system_build_file attribute to the repository rule" + 101*b16991f9SAndroid Build Coastguard Worker "for %s." % (ctx.attr.name, ctx.attr.name, ctx.attr.name)) 102*b16991f9SAndroid Build Coastguard Worker ctx.symlink(Label(ctx.attr.system_build_file), buildfile_path) 103*b16991f9SAndroid Build Coastguard Worker 104*b16991f9SAndroid Build Coastguard Worker else: 105*b16991f9SAndroid Build Coastguard Worker ctx.download_and_extract( 106*b16991f9SAndroid Build Coastguard Worker ctx.attr.urls, 107*b16991f9SAndroid Build Coastguard Worker "", 108*b16991f9SAndroid Build Coastguard Worker ctx.attr.sha256, 109*b16991f9SAndroid Build Coastguard Worker ctx.attr.type, 110*b16991f9SAndroid Build Coastguard Worker ctx.attr.strip_prefix, 111*b16991f9SAndroid Build Coastguard Worker ) 112*b16991f9SAndroid Build Coastguard Worker if ctx.attr.delete: 113*b16991f9SAndroid Build Coastguard Worker _apply_delete(ctx, ctx.attr.delete) 114*b16991f9SAndroid Build Coastguard Worker if ctx.attr.patch_file != None: 115*b16991f9SAndroid Build Coastguard Worker _apply_patch(ctx, ctx.attr.patch_file) 116*b16991f9SAndroid Build Coastguard Worker ctx.symlink(Label(ctx.attr.build_file), buildfile_path) 117*b16991f9SAndroid Build Coastguard Worker 118*b16991f9SAndroid Build Coastguard Worker link_dict = {} 119*b16991f9SAndroid Build Coastguard Worker if use_syslib: 120*b16991f9SAndroid Build Coastguard Worker link_dict.update(ctx.attr.system_link_files) 121*b16991f9SAndroid Build Coastguard Worker 122*b16991f9SAndroid Build Coastguard Worker for internal_src, external_dest in ctx.attr.link_files.items(): 123*b16991f9SAndroid Build Coastguard Worker # if syslib and link exists in both, use the system one 124*b16991f9SAndroid Build Coastguard Worker if external_dest not in link_dict.values(): 125*b16991f9SAndroid Build Coastguard Worker link_dict[internal_src] = external_dest 126*b16991f9SAndroid Build Coastguard Worker 127*b16991f9SAndroid Build Coastguard Worker for internal_src, external_dest in link_dict.items(): 128*b16991f9SAndroid Build Coastguard Worker ctx.symlink(Label(internal_src), ctx.path(external_dest)) 129*b16991f9SAndroid Build Coastguard Worker 130*b16991f9SAndroid Build Coastguard Worker# For link_files, specify each dict entry as: 131*b16991f9SAndroid Build Coastguard Worker# "//path/to/source:file": "localfile" 132*b16991f9SAndroid Build Coastguard Workerthird_party_http_archive = repository_rule( 133*b16991f9SAndroid Build Coastguard Worker attrs = { 134*b16991f9SAndroid Build Coastguard Worker "sha256": attr.string(mandatory = True), 135*b16991f9SAndroid Build Coastguard Worker "urls": attr.string_list( 136*b16991f9SAndroid Build Coastguard Worker mandatory = True, 137*b16991f9SAndroid Build Coastguard Worker allow_empty = False, 138*b16991f9SAndroid Build Coastguard Worker ), 139*b16991f9SAndroid Build Coastguard Worker "strip_prefix": attr.string(), 140*b16991f9SAndroid Build Coastguard Worker "type": attr.string(), 141*b16991f9SAndroid Build Coastguard Worker "delete": attr.string_list(), 142*b16991f9SAndroid Build Coastguard Worker "build_file": attr.string(mandatory = True), 143*b16991f9SAndroid Build Coastguard Worker "system_build_file": attr.string(mandatory = False), 144*b16991f9SAndroid Build Coastguard Worker "patch_file": attr.label(), 145*b16991f9SAndroid Build Coastguard Worker "link_files": attr.string_dict(), 146*b16991f9SAndroid Build Coastguard Worker "system_link_files": attr.string_dict(), 147*b16991f9SAndroid Build Coastguard Worker }, 148*b16991f9SAndroid Build Coastguard Worker environ = [ 149*b16991f9SAndroid Build Coastguard Worker "TF_SYSTEM_LIBS", 150*b16991f9SAndroid Build Coastguard Worker ], 151*b16991f9SAndroid Build Coastguard Worker implementation = _third_party_http_archive, 152*b16991f9SAndroid Build Coastguard Worker) 153