1*bcb5dc79SHONG Yifan# Copyright 2019 The Bazel Authors. All rights reserved. 2*bcb5dc79SHONG Yifan# 3*bcb5dc79SHONG Yifan# Licensed under the Apache License, Version 2.0 (the "License"); 4*bcb5dc79SHONG Yifan# you may not use this file except in compliance with the License. 5*bcb5dc79SHONG Yifan# You may obtain a copy of the License at 6*bcb5dc79SHONG Yifan# 7*bcb5dc79SHONG Yifan# http://www.apache.org/licenses/LICENSE-2.0 8*bcb5dc79SHONG Yifan# 9*bcb5dc79SHONG Yifan# Unless required by applicable law or agreed to in writing, software 10*bcb5dc79SHONG Yifan# distributed under the License is distributed on an "AS IS" BASIS, 11*bcb5dc79SHONG Yifan# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*bcb5dc79SHONG Yifan# See the License for the specific language governing permissions and 13*bcb5dc79SHONG Yifan# limitations under the License. 14*bcb5dc79SHONG Yifan 15*bcb5dc79SHONG Yifan"""Implementation of write_file macro and underlying rules. 16*bcb5dc79SHONG Yifan 17*bcb5dc79SHONG YifanThese rules write a UTF-8 encoded text file, using Bazel's FileWriteAction. 18*bcb5dc79SHONG Yifan'_write_xfile' marks the resulting file executable, '_write_file' does not. 19*bcb5dc79SHONG Yifan""" 20*bcb5dc79SHONG Yifan 21*bcb5dc79SHONG Yifandef _common_impl(ctx, is_windows, is_executable): 22*bcb5dc79SHONG Yifan if ctx.attr.newline == "auto": 23*bcb5dc79SHONG Yifan newline = "\r\n" if is_windows else "\n" 24*bcb5dc79SHONG Yifan elif ctx.attr.newline == "windows": 25*bcb5dc79SHONG Yifan newline = "\r\n" 26*bcb5dc79SHONG Yifan else: 27*bcb5dc79SHONG Yifan newline = "\n" 28*bcb5dc79SHONG Yifan 29*bcb5dc79SHONG Yifan # ctx.actions.write creates a FileWriteAction which uses UTF-8 encoding. 30*bcb5dc79SHONG Yifan ctx.actions.write( 31*bcb5dc79SHONG Yifan output = ctx.outputs.out, 32*bcb5dc79SHONG Yifan content = newline.join(ctx.attr.content) if ctx.attr.content else "", 33*bcb5dc79SHONG Yifan is_executable = is_executable, 34*bcb5dc79SHONG Yifan ) 35*bcb5dc79SHONG Yifan files = depset(direct = [ctx.outputs.out]) 36*bcb5dc79SHONG Yifan runfiles = ctx.runfiles(files = [ctx.outputs.out]) 37*bcb5dc79SHONG Yifan if is_executable: 38*bcb5dc79SHONG Yifan return [DefaultInfo(files = files, runfiles = runfiles, executable = ctx.outputs.out)] 39*bcb5dc79SHONG Yifan else: 40*bcb5dc79SHONG Yifan # Do not include the copied file into the default runfiles of the 41*bcb5dc79SHONG Yifan # target, but ensure that it is picked up by native rule's data 42*bcb5dc79SHONG Yifan # attribute despite https://github.com/bazelbuild/bazel/issues/15043. 43*bcb5dc79SHONG Yifan return [DefaultInfo(files = files, data_runfiles = runfiles)] 44*bcb5dc79SHONG Yifan 45*bcb5dc79SHONG Yifandef _impl(ctx): 46*bcb5dc79SHONG Yifan return _common_impl(ctx, ctx.attr.is_windows, False) 47*bcb5dc79SHONG Yifan 48*bcb5dc79SHONG Yifandef _ximpl(ctx): 49*bcb5dc79SHONG Yifan return _common_impl(ctx, ctx.attr.is_windows, True) 50*bcb5dc79SHONG Yifan 51*bcb5dc79SHONG Yifan_ATTRS = { 52*bcb5dc79SHONG Yifan "out": attr.output(mandatory = True), 53*bcb5dc79SHONG Yifan "content": attr.string_list(mandatory = False, allow_empty = True), 54*bcb5dc79SHONG Yifan "newline": attr.string(values = ["unix", "windows", "auto"], default = "auto"), 55*bcb5dc79SHONG Yifan "is_windows": attr.bool(mandatory = True), 56*bcb5dc79SHONG Yifan} 57*bcb5dc79SHONG Yifan 58*bcb5dc79SHONG Yifan_write_file = rule( 59*bcb5dc79SHONG Yifan implementation = _impl, 60*bcb5dc79SHONG Yifan provides = [DefaultInfo], 61*bcb5dc79SHONG Yifan attrs = _ATTRS, 62*bcb5dc79SHONG Yifan) 63*bcb5dc79SHONG Yifan 64*bcb5dc79SHONG Yifan_write_xfile = rule( 65*bcb5dc79SHONG Yifan implementation = _ximpl, 66*bcb5dc79SHONG Yifan executable = True, 67*bcb5dc79SHONG Yifan provides = [DefaultInfo], 68*bcb5dc79SHONG Yifan attrs = _ATTRS, 69*bcb5dc79SHONG Yifan) 70*bcb5dc79SHONG Yifan 71*bcb5dc79SHONG Yifandef write_file( 72*bcb5dc79SHONG Yifan name, 73*bcb5dc79SHONG Yifan out, 74*bcb5dc79SHONG Yifan content = [], 75*bcb5dc79SHONG Yifan is_executable = False, 76*bcb5dc79SHONG Yifan newline = "auto", 77*bcb5dc79SHONG Yifan **kwargs): 78*bcb5dc79SHONG Yifan """Creates a UTF-8 encoded text file. 79*bcb5dc79SHONG Yifan 80*bcb5dc79SHONG Yifan Args: 81*bcb5dc79SHONG Yifan name: Name of the rule. 82*bcb5dc79SHONG Yifan out: Path of the output file, relative to this package. 83*bcb5dc79SHONG Yifan content: A list of strings. Lines of text, the contents of the file. 84*bcb5dc79SHONG Yifan Newlines are added automatically after every line except the last one. 85*bcb5dc79SHONG Yifan is_executable: A boolean. Whether to make the output file executable. 86*bcb5dc79SHONG Yifan When True, the rule's output can be executed using `bazel run` and can 87*bcb5dc79SHONG Yifan be in the srcs of binary and test rules that require executable 88*bcb5dc79SHONG Yifan sources. 89*bcb5dc79SHONG Yifan newline: one of ["auto", "unix", "windows"]: line endings to use. "auto" 90*bcb5dc79SHONG Yifan for platform-determined, "unix" for LF, and "windows" for CRLF. 91*bcb5dc79SHONG Yifan **kwargs: further keyword arguments, e.g. `visibility` 92*bcb5dc79SHONG Yifan """ 93*bcb5dc79SHONG Yifan if is_executable: 94*bcb5dc79SHONG Yifan _write_xfile( 95*bcb5dc79SHONG Yifan name = name, 96*bcb5dc79SHONG Yifan content = content, 97*bcb5dc79SHONG Yifan out = out, 98*bcb5dc79SHONG Yifan newline = newline or "auto", 99*bcb5dc79SHONG Yifan is_windows = select({ 100*bcb5dc79SHONG Yifan "@bazel_tools//src/conditions:host_windows": True, 101*bcb5dc79SHONG Yifan "//conditions:default": False, 102*bcb5dc79SHONG Yifan }), 103*bcb5dc79SHONG Yifan **kwargs 104*bcb5dc79SHONG Yifan ) 105*bcb5dc79SHONG Yifan else: 106*bcb5dc79SHONG Yifan _write_file( 107*bcb5dc79SHONG Yifan name = name, 108*bcb5dc79SHONG Yifan content = content, 109*bcb5dc79SHONG Yifan out = out, 110*bcb5dc79SHONG Yifan newline = newline or "auto", 111*bcb5dc79SHONG Yifan is_windows = select({ 112*bcb5dc79SHONG Yifan "@bazel_tools//src/conditions:host_windows": True, 113*bcb5dc79SHONG Yifan "//conditions:default": False, 114*bcb5dc79SHONG Yifan }), 115*bcb5dc79SHONG Yifan **kwargs 116*bcb5dc79SHONG Yifan ) 117