1# Copyright (c) 2009-2021, Google LLC 2# All rights reserved. 3# 4# Redistribution and use in source and binary forms, with or without 5# modification, are permitted provided that the following conditions are met: 6# * Redistributions of source code must retain the above copyright 7# notice, this list of conditions and the following disclaimer. 8# * Redistributions in binary form must reproduce the above copyright 9# notice, this list of conditions and the following disclaimer in the 10# documentation and/or other materials provided with the distribution. 11# * Neither the name of Google LLC nor the 12# names of its contributors may be used to endorse or promote products 13# derived from this software without specific prior written permission. 14# 15# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18# DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY 19# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 26"""lua_proto_library(): a rule for building Lua protos.""" 27 28load("@bazel_skylib//lib:paths.bzl", "paths") 29 30# Generic support code ######################################################### 31 32# begin:github_only 33_is_google3 = False 34# end:github_only 35 36# begin:google_only 37# _is_google3 = True 38# end:google_only 39 40def _get_real_short_path(file): 41 # For some reason, files from other archives have short paths that look like: 42 # ../com_google_protobuf/google/protobuf/descriptor.proto 43 short_path = file.short_path 44 if short_path.startswith("../"): 45 second_slash = short_path.index("/", 3) 46 short_path = short_path[second_slash + 1:] 47 48 # Sometimes it has another few prefixes like: 49 # _virtual_imports/any_proto/google/protobuf/any.proto 50 # benchmarks/_virtual_imports/100_msgs_proto/benchmarks/100_msgs.proto 51 # We want just google/protobuf/any.proto. 52 virtual_imports = "_virtual_imports/" 53 if virtual_imports in short_path: 54 short_path = short_path.split(virtual_imports)[1].split("/", 1)[1] 55 return short_path 56 57def _get_real_root(ctx, file): 58 real_short_path = _get_real_short_path(file) 59 root = file.path[:-len(real_short_path) - 1] 60 if not _is_google3 and ctx.rule.attr.strip_import_prefix: 61 root = paths.join(root, ctx.rule.attr.strip_import_prefix[1:]) 62 return root 63 64def _generate_output_file(ctx, src, extension): 65 package = ctx.label.package 66 if not _is_google3 and ctx.rule.attr.strip_import_prefix and ctx.rule.attr.strip_import_prefix != "/": 67 package = package[len(ctx.rule.attr.strip_import_prefix):] 68 real_short_path = _get_real_short_path(src) 69 real_short_path = paths.relativize(real_short_path, package) 70 output_filename = paths.replace_extension(real_short_path, extension) 71 ret = ctx.actions.declare_file(output_filename) 72 return ret 73 74# upb_proto_library / upb_proto_reflection_library shared code ################# 75 76_LuaFilesInfo = provider( 77 "A set of lua files generated from .proto files", 78 fields = ["files"], 79) 80 81def _compile_upb_protos(ctx, proto_info, proto_sources): 82 files = [_generate_output_file(ctx, name, "_pb.lua") for name in proto_sources] 83 transitive_sets = proto_info.transitive_descriptor_sets.to_list() 84 ctx.actions.run( 85 inputs = depset( 86 direct = [proto_info.direct_descriptor_set], 87 transitive = [proto_info.transitive_descriptor_sets], 88 ), 89 tools = [ctx.executable._upbc], 90 outputs = files, 91 executable = ctx.executable._protoc, 92 arguments = [ 93 "--lua_out=" + _get_real_root(ctx, files[0]), 94 "--plugin=protoc-gen-lua=" + ctx.executable._upbc.path, 95 "--descriptor_set_in=" + ctx.configuration.host_path_separator.join([f.path for f in transitive_sets]), 96 ] + 97 [_get_real_short_path(file) for file in proto_sources], 98 progress_message = "Generating Lua protos for :" + ctx.label.name, 99 ) 100 return files 101 102def _lua_proto_rule_impl(ctx): 103 if len(ctx.attr.deps) != 1: 104 fail("only one deps dependency allowed.") 105 dep = ctx.attr.deps[0] 106 if _LuaFilesInfo not in dep: 107 fail("proto_library rule must generate _LuaFilesInfo (aspect should have handled this).") 108 files = dep[_LuaFilesInfo].files 109 return [ 110 DefaultInfo( 111 files = files, 112 data_runfiles = ctx.runfiles(files = files.to_list()), 113 ), 114 ] 115 116def _lua_proto_library_aspect_impl(target, ctx): 117 proto_info = target[ProtoInfo] 118 files = _compile_upb_protos(ctx, proto_info, proto_info.direct_sources) 119 deps = ctx.rule.attr.deps 120 transitive = [dep[_LuaFilesInfo].files for dep in deps if _LuaFilesInfo in dep] 121 return [_LuaFilesInfo(files = depset(direct = files, transitive = transitive))] 122 123# lua_proto_library() ########################################################## 124 125_lua_proto_library_aspect = aspect( 126 attrs = { 127 "_upbc": attr.label( 128 executable = True, 129 cfg = "exec", 130 default = "//lua:protoc-gen-lua", 131 ), 132 "_protoc": attr.label( 133 executable = True, 134 cfg = "exec", 135 default = "@com_google_protobuf//:protoc", 136 ), 137 }, 138 implementation = _lua_proto_library_aspect_impl, 139 provides = [_LuaFilesInfo], 140 attr_aspects = ["deps"], 141 fragments = ["cpp"], 142) 143 144lua_proto_library = rule( 145 output_to_genfiles = True, 146 implementation = _lua_proto_rule_impl, 147 attrs = { 148 "deps": attr.label_list( 149 aspects = [_lua_proto_library_aspect], 150 allow_rules = ["proto_library"], 151 providers = [ProtoInfo], 152 ), 153 }, 154) 155