github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/infra/bazel/zip.bzl (about) 1 # Copied from google/nomulus project as we don't want to import the whole repository. 2 3 ZIPPER = "@bazel_tools//tools/zip:zipper" 4 5 def long_path(ctx, file_): 6 """Constructs canonical runfile path relative to TEST_SRCDIR. 7 Args: 8 ctx: A Skylark rule context. 9 file_: A File object that should appear in the runfiles for the test. 10 Returns: 11 A string path relative to TEST_SRCDIR suitable for use in tests and 12 testing infrastructure. 13 """ 14 if file_.short_path.startswith("../"): 15 return file_.short_path[3:] 16 if file_.owner and file_.owner.workspace_root: 17 return file_.owner.workspace_root + "/" + file_.short_path 18 return ctx.workspace_name + "/" + file_.short_path 19 20 def collect_runfiles(targets): 21 """Aggregates runfiles from targets. 22 Args: 23 targets: A list of Bazel targets. 24 Returns: 25 A list of Bazel files. 26 """ 27 data = depset() 28 for target in targets: 29 if hasattr(target, "runfiles"): 30 data += target.runfiles.files 31 continue 32 if hasattr(target, "data_runfiles"): 33 data += target.data_runfiles.files 34 if hasattr(target, "default_runfiles"): 35 data += target.default_runfiles.files 36 return data 37 38 def _get_runfiles(target, attribute): 39 runfiles = getattr(target, attribute, None) 40 if runfiles: 41 return runfiles.files 42 return [] 43 44 def _zip_file(ctx): 45 """Implementation of zip_file() rule.""" 46 for s, d in ctx.attr.mappings.items(): 47 if (s.startswith("/") or s.endswith("/") or 48 d.startswith("/") or d.endswith("/")): 49 fail("mappings should not begin or end with slash") 50 srcs = depset(transitive = [depset(ctx.files.srcs),depset(ctx.files.data),depset(collect_runfiles(ctx.attr.data))]) 51 mapped = _map_sources(ctx, srcs, ctx.attr.mappings) 52 cmd = [ 53 "#!/bin/sh", 54 "set -e", 55 'repo="$(pwd)"', 56 'zipper="${repo}/%s"' % ctx.file._zipper.path, 57 'archive="${repo}/%s"' % ctx.outputs.out.path, 58 'tmp="$(mktemp -d "${TMPDIR:-/tmp}/zip_file.XXXXXXXXXX")"', 59 'cd "${tmp}"', 60 ] 61 cmd += [ 62 '"${zipper}" x "${repo}/%s"' % dep.zip_file.path 63 for dep in ctx.attr.deps 64 ] 65 cmd += ["rm %s" % filename for filename in ctx.attr.exclude] 66 cmd += [ 67 'mkdir -p "${tmp}/%s"' % zip_path 68 for zip_path in depset( 69 [ 70 zip_path[:zip_path.rindex("/")] 71 for _, zip_path in mapped 72 if "/" in zip_path 73 ], 74 ).to_list() 75 ] 76 cmd += [ 77 'ln -sf "${repo}/%s" "${tmp}/%s"' % (path, zip_path) 78 for path, zip_path in mapped 79 ] 80 cmd += [ 81 ("find . | sed 1d | cut -c 3- | LC_ALL=C sort" + 82 ' | xargs "${zipper}" cC "${archive}"'), 83 'cd "${repo}"', 84 'rm -rf "${tmp}"', 85 ] 86 script = ctx.actions.declare_file("%s/%s.sh" % (ctx.bin_dir, ctx.label.name)) 87 ctx.actions.write(output = script, content = "\n".join(cmd), is_executable = True) 88 inputs = [ctx.file._zipper] 89 inputs += [dep.zip_file for dep in ctx.attr.deps] 90 inputs += list(srcs.to_list()) 91 ctx.actions.run( 92 inputs = inputs, 93 outputs = [ctx.outputs.out], 94 executable = script, 95 mnemonic = "zip", 96 progress_message = "Creating zip with %d inputs %s" % ( 97 len(inputs), 98 ctx.label, 99 ), 100 ) 101 return struct(files = depset([ctx.outputs.out]), zip_file = ctx.outputs.out) 102 103 def _map_sources(ctx, srcs, mappings): 104 """Calculates paths in zip file for srcs.""" 105 106 # order mappings with more path components first 107 mappings = sorted([ 108 (-len(source.split("/")), source, dest) 109 for source, dest in mappings.items() 110 ]) 111 112 # get rid of the integer part of tuple used for sorting 113 mappings = [(source, dest) for _, source, dest in mappings] 114 mappings_indexes = range(len(mappings)) 115 used = {i: False for i in mappings_indexes} 116 mapped = [] 117 for file_ in srcs.to_list(): 118 run_path = long_path(ctx, file_) 119 zip_path = None 120 for i in mappings_indexes: 121 source = mappings[i][0] 122 dest = mappings[i][1] 123 if not source: 124 if dest: 125 zip_path = dest + "/" + run_path 126 else: 127 zip_path = run_path 128 elif source == run_path: 129 if dest: 130 zip_path = dest 131 else: 132 zip_path = run_path 133 elif run_path.startswith(source + "/"): 134 if dest: 135 zip_path = dest + run_path[len(source):] 136 else: 137 zip_path = run_path[len(source) + 1:] 138 else: 139 continue 140 used[i] = True 141 break 142 if not zip_path: 143 fail("no mapping matched: " + run_path) 144 mapped += [(file_.path, zip_path)] 145 for i in mappings_indexes: 146 if not used[i]: 147 fail('superfluous mapping: "%s" -> "%s"' % mappings[i]) 148 return mapped 149 150 pkg_zip = rule( 151 implementation = _zip_file, 152 attrs = { 153 "out": attr.output(mandatory = True), 154 "srcs": attr.label_list(allow_files = True), 155 "data": attr.label_list(allow_files = True), 156 "deps": attr.label_list(providers = ["zip_file"]), 157 "exclude": attr.string_list(), 158 "mappings": attr.string_dict(), 159 "_zipper": attr.label(default = Label(ZIPPER), allow_single_file = True), 160 }, 161 )