|  | # Copyright 2015 The Bazel Authors. All rights reserved. | 
|  | # | 
|  | # Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | # you may not use this file except in compliance with the License. | 
|  | # You may obtain a copy of the License at | 
|  | # | 
|  | #    http://www.apache.org/licenses/LICENSE-2.0 | 
|  | # | 
|  | # Unless required by applicable law or agreed to in writing, software | 
|  | # distributed under the License is distributed on an "AS IS" BASIS, | 
|  | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | # See the License for the specific language governing permissions and | 
|  | # limitations under the License. | 
|  | """Self-extracting binary. | 
|  |  | 
|  | Generate a binary suitable for self-extraction: | 
|  |  | 
|  | self_extract_binary( | 
|  | name = "install.sh", | 
|  | launcher = "launcher.sh", | 
|  | resources = ["path1/file1", "path2/file2"], | 
|  | flatten_ressources = ["path3/file3"], | 
|  | ) | 
|  |  | 
|  | will generate a file 'install.sh' with a header (launcher.sh) | 
|  | and a ZIP footer with the following entries: | 
|  | path1/ | 
|  | path1/file1 | 
|  | path2/ | 
|  | path2/file2 | 
|  | file3 | 
|  |  | 
|  | """ | 
|  |  | 
|  | def _self_extract_binary(ctx): | 
|  | """Implementation for the self_extract_binary rule.""" | 
|  | # This is a bit complex for stripping out timestamps | 
|  | zip_artifact = ctx.new_file(ctx.label.name + ".zip") | 
|  | touch_empty_files = [ | 
|  | "mkdir -p $(dirname ${tmpdir}/%s); touch ${tmpdir}/%s" % (f, f) | 
|  | for f in ctx.attr.empty_files | 
|  | ] | 
|  | cp_resources = [ | 
|  | ("mkdir -p $(dirname ${tmpdir}/%s)\n" % r.short_path + | 
|  | "cp %s ${tmpdir}/%s" % (r.path, r.short_path)) | 
|  | for r in ctx.files.resources | 
|  | ] | 
|  | cp_flatten_resources = [ | 
|  | "cp %s ${tmpdir}/%s" % (r.path, r.basename) | 
|  | for r in ctx.files.flatten_resources | 
|  | ] | 
|  | ctx.action( | 
|  | inputs = ctx.files.resources + ctx.files.flatten_resources, | 
|  | outputs = [zip_artifact], | 
|  | command = "\n".join([ | 
|  | "tmpdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXX)", | 
|  | "trap \"rm -fr ${tmpdir}\" EXIT" | 
|  | ] + touch_empty_files + cp_resources + cp_flatten_resources + [ | 
|  | "find ${tmpdir} -exec touch -t 198001010000.00 '{}' ';'", | 
|  | "(d=${PWD}; cd ${tmpdir}; zip -rq ${d}/%s *)" % zip_artifact.path, | 
|  | ]), | 
|  | mnemonic = "ZipBin", | 
|  | ) | 
|  | ctx.action( | 
|  | inputs = [ctx.file.launcher, zip_artifact], | 
|  | outputs = [ctx.outputs.executable], | 
|  | command = "\n".join([ | 
|  | "cat %s %s > %s" % (ctx.file.launcher.path, | 
|  | zip_artifact.path, | 
|  | ctx.outputs.executable.path), | 
|  | "zip -qA %s" % ctx.outputs.executable.path | 
|  | ]), | 
|  | mnemonic = "BuildSelfExtractable", | 
|  | ) | 
|  |  | 
|  | self_extract_binary = rule( | 
|  | _self_extract_binary, | 
|  | executable = True, | 
|  | attrs = { | 
|  | "launcher": attr.label( | 
|  | mandatory=True, | 
|  | allow_files=True, | 
|  | single_file=True), | 
|  | "empty_files": attr.string_list(default=[]), | 
|  | "resources": attr.label_list( | 
|  | default=[], | 
|  | allow_files=True), | 
|  | "flatten_resources": attr.label_list( | 
|  | default=[], | 
|  | allow_files=True), | 
|  | }, | 
|  | ) |