1# Copyright (C) 2023 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("@bazel_skylib//lib:paths.bzl", "paths") 16load(":cc_library_common.bzl", "create_ccinfo_for_includes") 17load(":cc_library_static.bzl", "cc_library_static") 18 19""" 20Generate C/C++ parser from a .y/.yy grammar file. 21The generated file might depend on external headers and has to be compiled 22separately. 23""" 24 25def _cc_yacc_parser_gen_impl(ctx): 26 ext = ".c" 27 if paths.split_extension(ctx.file.src.basename)[1] == ".yy": 28 ext = ".cpp" 29 30 # C/CPP file 31 output_c_file = ctx.actions.declare_file( 32 paths.join( 33 ctx.attr.name, # Prevent name collisions (esp for tests) 34 paths.replace_extension(ctx.file.src.basename, ext), 35 ), 36 ) 37 38 # Header file 39 output_h_file = ctx.actions.declare_file( 40 paths.join( 41 ctx.attr.name, # Prevent name collisions (esp for tests) 42 paths.replace_extension(ctx.file.src.basename, ".h"), 43 ), 44 ) 45 outputs = [ 46 output_c_file, 47 output_h_file, 48 ] 49 output_hdrs = [ 50 output_h_file, 51 ] 52 53 # Path of location.hh in the same dir as the generated C/CPP file 54 if ctx.attr.gen_location_hh: 55 location_hh_file = ctx.actions.declare_file( 56 paths.join( 57 ctx.attr.name, 58 "location.hh", 59 ), 60 ) 61 outputs.append(location_hh_file) 62 output_hdrs.append(location_hh_file) 63 64 # Path of position.hh in the same dir as the generated C/CPP file 65 if ctx.attr.gen_position_hh: 66 position_hh_file = ctx.actions.declare_file( 67 paths.join( 68 ctx.attr.name, 69 "position.hh", 70 ), 71 ) 72 outputs.append(position_hh_file) 73 output_hdrs.append(position_hh_file) 74 75 args = ctx.actions.args() 76 args.add("-d") # Generate headers 77 args.add_all(ctx.attr.flags) 78 args.add("--defines=" + output_h_file.path) 79 args.add("-o", output_c_file) 80 args.add(ctx.file.src) 81 82 ctx.actions.run( 83 executable = ctx.executable._bison, 84 inputs = [ctx.file.src], 85 outputs = outputs, 86 arguments = [args], 87 # Explicitly set some environment variables to ensure Android's hermetic tools are used. 88 env = { 89 "BISON_PKGDATADIR": "prebuilts/build-tools/common/bison", 90 "M4": ctx.executable._m4.path, 91 }, 92 tools = [ctx.executable._m4] + ctx.files._bison_runfiles, 93 mnemonic = "YaccCompile", 94 ) 95 96 return [ 97 DefaultInfo( 98 # Return the C/C++ file. 99 # Skip headers since rdep does not compile headers. 100 files = depset([output_c_file]), 101 ), 102 create_ccinfo_for_includes( 103 ctx, 104 hdrs = output_hdrs, 105 includes = [ctx.attr.name], 106 ), 107 ] 108 109_cc_yacc_parser_gen = rule( 110 implementation = _cc_yacc_parser_gen_impl, 111 doc = "This rule generates a C/C++ parser from a .y/.yy grammar file using bison", 112 attrs = { 113 "src": attr.label( 114 allow_single_file = [".y", ".yy"], 115 doc = "The grammar file for the parser", 116 ), 117 "flags": attr.string_list( 118 default = [], 119 doc = "List of flags that will be used in yacc compile", 120 ), 121 "gen_location_hh": attr.bool( 122 default = False, 123 doc = "Whether the yacc file will produce a location.hh file.", 124 ), 125 "gen_position_hh": attr.bool( 126 default = False, 127 doc = "Whether the yacc file will produce a location.hh file.", 128 ), 129 "_m4": attr.label( 130 executable = True, 131 cfg = "exec", 132 default = Label("//prebuilts/build-tools:m4"), 133 ), 134 "_bison": attr.label( 135 executable = True, 136 cfg = "exec", 137 default = Label("//prebuilts/build-tools:bison"), 138 ), 139 "_bison_runfiles": attr.label( 140 default = Label("//prebuilts/build-tools:bison.runfiles"), 141 ), 142 }, 143 provides = [ 144 CcInfo, 145 ], 146) 147 148def cc_yacc_static_library( 149 name, 150 src, 151 flags = [], 152 gen_location_hh = False, 153 gen_position_hh = False, 154 local_includes = [], 155 implementation_deps = [], 156 implementation_dynamic_deps = [], 157 **kwargs): 158 """ 159 Generate C/C++ parser from .y/.yy grammar file and wrap it in a cc_library_static target. 160 161 """ 162 _output_parser = name + "_parser" 163 164 _cc_yacc_parser_gen( 165 name = _output_parser, 166 src = src, 167 flags = flags, 168 gen_location_hh = gen_location_hh, 169 gen_position_hh = gen_position_hh, 170 **kwargs 171 ) 172 173 cc_library_static( 174 name = name, 175 srcs = [_output_parser], 176 deps = [_output_parser], # Generated hdrs 177 local_includes = local_includes, 178 implementation_deps = implementation_deps, 179 implementation_dynamic_deps = implementation_dynamic_deps, 180 **kwargs 181 ) 182