1"""Utilities directly related to bootstrapping `cargo-bazel`""" 2 3_SRCS_TEMPLATE = """\ 4\"\"\"A generate file containing all source files used to produce `cargo-bazel`\"\"\" 5 6# Each source file is tracked as a target so the `cargo_bootstrap_repository` 7# rule will know to automatically rebuild if any of the sources changed. 8 9# Run 'bazel run //crate_universe/private:srcs_module.install' to regenerate. 10 11CARGO_BAZEL_SRCS = [ 12 {srcs} 13] 14""" 15 16def _format_src_label(label): 17 if label.workspace_name != "": 18 fail("`srcs` must be from the rules_rust repository") 19 return "Label(\"{}\"),".format(str(label).lstrip("@")) 20 21def _srcs_module_impl(ctx): 22 srcs = [_format_src_label(src.owner) for src in ctx.files.srcs] 23 if not srcs: 24 fail("`srcs` cannot be empty") 25 output = ctx.actions.declare_file(ctx.label.name) 26 27 ctx.actions.write( 28 output = output, 29 content = _SRCS_TEMPLATE.format( 30 srcs = "\n ".join(srcs), 31 ), 32 ) 33 34 return DefaultInfo( 35 files = depset([output]), 36 ) 37 38_srcs_module = rule( 39 doc = "A rule for writing a list of sources to a templated file", 40 implementation = _srcs_module_impl, 41 attrs = { 42 "srcs": attr.label( 43 doc = "A filegroup of source files", 44 allow_files = True, 45 ), 46 }, 47) 48 49_INSTALLER_TEMPLATE = """\ 50#!/usr/bin/env bash 51set -euo pipefail 52cp -f "{path}" "${{BUILD_WORKSPACE_DIRECTORY}}/{dest}" 53""" 54 55def _srcs_installer_impl(ctx): 56 output = ctx.actions.declare_file(ctx.label.name + ".sh") 57 target_file = ctx.file.input 58 dest = ctx.file.dest.short_path 59 60 ctx.actions.write( 61 output = output, 62 content = _INSTALLER_TEMPLATE.format( 63 path = target_file.short_path, 64 dest = dest, 65 ), 66 is_executable = True, 67 ) 68 69 return DefaultInfo( 70 files = depset([output]), 71 runfiles = ctx.runfiles(files = [target_file]), 72 executable = output, 73 ) 74 75_srcs_installer = rule( 76 doc = "A rule for writing a file back to the repository", 77 implementation = _srcs_installer_impl, 78 attrs = { 79 "dest": attr.label( 80 doc = "the file name to use for installation", 81 allow_single_file = True, 82 mandatory = True, 83 ), 84 "input": attr.label( 85 doc = "The file to write back to the repository", 86 allow_single_file = True, 87 mandatory = True, 88 ), 89 }, 90 executable = True, 91) 92 93def srcs_module(name, dest, **kwargs): 94 """A helper rule to ensure the bootstrapping functionality of `cargo-bazel` is always up to date 95 96 Args: 97 name (str): The name of the sources module 98 dest (str): The filename the module should be written as in the current package. 99 **kwargs (dict): Additional keyword arguments 100 """ 101 tags = kwargs.pop("tags", []) 102 103 _srcs_module( 104 name = name, 105 tags = tags, 106 **kwargs 107 ) 108 109 _srcs_installer( 110 name = name + ".install", 111 input = name, 112 dest = dest, 113 tags = tags, 114 ) 115