1*b6fb3261SAndroid Build Coastguard Worker# Copyright 2017 The TensorFlow Authors. All rights reserved. 2*b6fb3261SAndroid Build Coastguard Worker# 3*b6fb3261SAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License"); 4*b6fb3261SAndroid Build Coastguard Worker# you may not use this file except in compliance with the License. 5*b6fb3261SAndroid Build Coastguard Worker# You may obtain a copy of the License at 6*b6fb3261SAndroid Build Coastguard Worker# 7*b6fb3261SAndroid Build Coastguard Worker# http://www.apache.org/licenses/LICENSE-2.0 8*b6fb3261SAndroid Build Coastguard Worker# 9*b6fb3261SAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software 10*b6fb3261SAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS, 11*b6fb3261SAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*b6fb3261SAndroid Build Coastguard Worker# See the License for the specific language governing permissions and 13*b6fb3261SAndroid Build Coastguard Worker# limitations under the License. 14*b6fb3261SAndroid Build Coastguard Worker 15*b6fb3261SAndroid Build Coastguard Worker"""Utilities for defining TensorFlow Bazel dependencies.""" 16*b6fb3261SAndroid Build Coastguard Worker 17*b6fb3261SAndroid Build Coastguard Workerdef tf_mirror_urls(url): 18*b6fb3261SAndroid Build Coastguard Worker """A helper for generating TF-mirror versions of URLs. 19*b6fb3261SAndroid Build Coastguard Worker 20*b6fb3261SAndroid Build Coastguard Worker Given a URL, it returns a list of the TF-mirror cache version of that URL 21*b6fb3261SAndroid Build Coastguard Worker and the original URL, suitable for use in `urls` field of `tf_http_archive`. 22*b6fb3261SAndroid Build Coastguard Worker """ 23*b6fb3261SAndroid Build Coastguard Worker if not url.startswith("https://"): 24*b6fb3261SAndroid Build Coastguard Worker return [url] 25*b6fb3261SAndroid Build Coastguard Worker return [ 26*b6fb3261SAndroid Build Coastguard Worker "https://storage.googleapis.com/mirror.tensorflow.org/%s" % url[8:], 27*b6fb3261SAndroid Build Coastguard Worker url, 28*b6fb3261SAndroid Build Coastguard Worker ] 29*b6fb3261SAndroid Build Coastguard Worker 30*b6fb3261SAndroid Build Coastguard Workerdef _get_env_var(ctx, name): 31*b6fb3261SAndroid Build Coastguard Worker if name in ctx.os.environ: 32*b6fb3261SAndroid Build Coastguard Worker return ctx.os.environ[name] 33*b6fb3261SAndroid Build Coastguard Worker else: 34*b6fb3261SAndroid Build Coastguard Worker return None 35*b6fb3261SAndroid Build Coastguard Worker 36*b6fb3261SAndroid Build Coastguard Worker# Checks if we should use the system lib instead of the bundled one 37*b6fb3261SAndroid Build Coastguard Workerdef _use_system_lib(ctx, name): 38*b6fb3261SAndroid Build Coastguard Worker syslibenv = _get_env_var(ctx, "TF_SYSTEM_LIBS") 39*b6fb3261SAndroid Build Coastguard Worker if not syslibenv: 40*b6fb3261SAndroid Build Coastguard Worker return False 41*b6fb3261SAndroid Build Coastguard Worker return name in [n.strip() for n in syslibenv.split(",")] 42*b6fb3261SAndroid Build Coastguard Worker 43*b6fb3261SAndroid Build Coastguard Workerdef _get_link_dict(ctx, link_files, build_file): 44*b6fb3261SAndroid Build Coastguard Worker link_dict = {ctx.path(v): ctx.path(Label(k)) for k, v in link_files.items()} 45*b6fb3261SAndroid Build Coastguard Worker if build_file: 46*b6fb3261SAndroid Build Coastguard Worker # Use BUILD.bazel because it takes precedence over BUILD. 47*b6fb3261SAndroid Build Coastguard Worker link_dict[ctx.path("BUILD.bazel")] = ctx.path(Label(build_file)) 48*b6fb3261SAndroid Build Coastguard Worker return link_dict 49*b6fb3261SAndroid Build Coastguard Worker 50*b6fb3261SAndroid Build Coastguard Workerdef _tf_http_archive_impl(ctx): 51*b6fb3261SAndroid Build Coastguard Worker # Construct all paths early on to prevent rule restart. We want the 52*b6fb3261SAndroid Build Coastguard Worker # attributes to be strings instead of labels because they refer to files 53*b6fb3261SAndroid Build Coastguard Worker # in the TensorFlow repository, not files in repos depending on TensorFlow. 54*b6fb3261SAndroid Build Coastguard Worker # See also https://github.com/bazelbuild/bazel/issues/10515. 55*b6fb3261SAndroid Build Coastguard Worker link_dict = _get_link_dict(ctx, ctx.attr.link_files, ctx.attr.build_file) 56*b6fb3261SAndroid Build Coastguard Worker 57*b6fb3261SAndroid Build Coastguard Worker # For some reason, we need to "resolve" labels once before the 58*b6fb3261SAndroid Build Coastguard Worker # download_and_extract otherwise it'll invalidate and re-download the 59*b6fb3261SAndroid Build Coastguard Worker # archive each time. 60*b6fb3261SAndroid Build Coastguard Worker # https://github.com/bazelbuild/bazel/issues/10515 61*b6fb3261SAndroid Build Coastguard Worker patch_files = ctx.attr.patch_file 62*b6fb3261SAndroid Build Coastguard Worker for patch_file in patch_files: 63*b6fb3261SAndroid Build Coastguard Worker if patch_file: 64*b6fb3261SAndroid Build Coastguard Worker ctx.path(Label(patch_file)) 65*b6fb3261SAndroid Build Coastguard Worker 66*b6fb3261SAndroid Build Coastguard Worker if _use_system_lib(ctx, ctx.attr.name): 67*b6fb3261SAndroid Build Coastguard Worker link_dict.update(_get_link_dict( 68*b6fb3261SAndroid Build Coastguard Worker ctx = ctx, 69*b6fb3261SAndroid Build Coastguard Worker link_files = ctx.attr.system_link_files, 70*b6fb3261SAndroid Build Coastguard Worker build_file = ctx.attr.system_build_file, 71*b6fb3261SAndroid Build Coastguard Worker )) 72*b6fb3261SAndroid Build Coastguard Worker else: 73*b6fb3261SAndroid Build Coastguard Worker ctx.download_and_extract( 74*b6fb3261SAndroid Build Coastguard Worker url = ctx.attr.urls, 75*b6fb3261SAndroid Build Coastguard Worker sha256 = ctx.attr.sha256, 76*b6fb3261SAndroid Build Coastguard Worker type = ctx.attr.type, 77*b6fb3261SAndroid Build Coastguard Worker stripPrefix = ctx.attr.strip_prefix, 78*b6fb3261SAndroid Build Coastguard Worker ) 79*b6fb3261SAndroid Build Coastguard Worker if patch_files: 80*b6fb3261SAndroid Build Coastguard Worker for patch_file in patch_files: 81*b6fb3261SAndroid Build Coastguard Worker patch_file = ctx.path(Label(patch_file)) if patch_file else None 82*b6fb3261SAndroid Build Coastguard Worker if patch_file: 83*b6fb3261SAndroid Build Coastguard Worker ctx.patch(patch_file, strip = 1) 84*b6fb3261SAndroid Build Coastguard Worker 85*b6fb3261SAndroid Build Coastguard Worker for dst, src in link_dict.items(): 86*b6fb3261SAndroid Build Coastguard Worker ctx.delete(dst) 87*b6fb3261SAndroid Build Coastguard Worker ctx.symlink(src, dst) 88*b6fb3261SAndroid Build Coastguard Worker 89*b6fb3261SAndroid Build Coastguard Worker_tf_http_archive = repository_rule( 90*b6fb3261SAndroid Build Coastguard Worker implementation = _tf_http_archive_impl, 91*b6fb3261SAndroid Build Coastguard Worker attrs = { 92*b6fb3261SAndroid Build Coastguard Worker "sha256": attr.string(mandatory = True), 93*b6fb3261SAndroid Build Coastguard Worker "urls": attr.string_list(mandatory = True), 94*b6fb3261SAndroid Build Coastguard Worker "strip_prefix": attr.string(), 95*b6fb3261SAndroid Build Coastguard Worker "type": attr.string(), 96*b6fb3261SAndroid Build Coastguard Worker "patch_file": attr.string_list(), 97*b6fb3261SAndroid Build Coastguard Worker "build_file": attr.string(), 98*b6fb3261SAndroid Build Coastguard Worker "system_build_file": attr.string(), 99*b6fb3261SAndroid Build Coastguard Worker "link_files": attr.string_dict(), 100*b6fb3261SAndroid Build Coastguard Worker "system_link_files": attr.string_dict(), 101*b6fb3261SAndroid Build Coastguard Worker }, 102*b6fb3261SAndroid Build Coastguard Worker environ = ["TF_SYSTEM_LIBS"], 103*b6fb3261SAndroid Build Coastguard Worker) 104*b6fb3261SAndroid Build Coastguard Worker 105*b6fb3261SAndroid Build Coastguard Workerdef tf_http_archive(name, sha256, urls, **kwargs): 106*b6fb3261SAndroid Build Coastguard Worker """Downloads and creates Bazel repos for dependencies. 107*b6fb3261SAndroid Build Coastguard Worker 108*b6fb3261SAndroid Build Coastguard Worker This is a swappable replacement for both http_archive() and 109*b6fb3261SAndroid Build Coastguard Worker new_http_archive() that offers some additional features. It also helps 110*b6fb3261SAndroid Build Coastguard Worker ensure best practices are followed. 111*b6fb3261SAndroid Build Coastguard Worker 112*b6fb3261SAndroid Build Coastguard Worker File arguments are relative to the TensorFlow repository by default. Dependent 113*b6fb3261SAndroid Build Coastguard Worker repositories that use this rule should refer to files either with absolute 114*b6fb3261SAndroid Build Coastguard Worker labels (e.g. '@foo//:bar') or from a label created in their repository (e.g. 115*b6fb3261SAndroid Build Coastguard Worker 'str(Label("//:bar"))'). 116*b6fb3261SAndroid Build Coastguard Worker """ 117*b6fb3261SAndroid Build Coastguard Worker if len(urls) < 2: 118*b6fb3261SAndroid Build Coastguard Worker fail("tf_http_archive(urls) must have redundant URLs.") 119*b6fb3261SAndroid Build Coastguard Worker 120*b6fb3261SAndroid Build Coastguard Worker if not any([mirror in urls[0] for mirror in ( 121*b6fb3261SAndroid Build Coastguard Worker "mirror.tensorflow.org", 122*b6fb3261SAndroid Build Coastguard Worker "mirror.bazel.build", 123*b6fb3261SAndroid Build Coastguard Worker "storage.googleapis.com", 124*b6fb3261SAndroid Build Coastguard Worker )]): 125*b6fb3261SAndroid Build Coastguard Worker fail("The first entry of tf_http_archive(urls) must be a mirror " + 126*b6fb3261SAndroid Build Coastguard Worker "URL, preferrably mirror.tensorflow.org. Even if you don't have " + 127*b6fb3261SAndroid Build Coastguard Worker "permission to mirror the file, please put the correctly " + 128*b6fb3261SAndroid Build Coastguard Worker "formatted mirror URL there anyway, because someone will come " + 129*b6fb3261SAndroid Build Coastguard Worker "along shortly thereafter and mirror the file.") 130*b6fb3261SAndroid Build Coastguard Worker 131*b6fb3261SAndroid Build Coastguard Worker if native.existing_rule(name): 132*b6fb3261SAndroid Build Coastguard Worker print("\n\033[1;33mWarning:\033[0m skipping import of repository '" + 133*b6fb3261SAndroid Build Coastguard Worker name + "' because it already exists.\n") 134*b6fb3261SAndroid Build Coastguard Worker return 135*b6fb3261SAndroid Build Coastguard Worker 136*b6fb3261SAndroid Build Coastguard Worker _tf_http_archive( 137*b6fb3261SAndroid Build Coastguard Worker name = name, 138*b6fb3261SAndroid Build Coastguard Worker sha256 = sha256, 139*b6fb3261SAndroid Build Coastguard Worker urls = urls, 140*b6fb3261SAndroid Build Coastguard Worker **kwargs 141*b6fb3261SAndroid Build Coastguard Worker ) 142