1"""Build rule for generating C or C++ sources with Bison. 2 3Notes about compiling libraries using bison: Make sure to use 4 5 cc_library( 6 ... 7 copts = [ 8 "-Wno-implicit-fallthrough", 9 "-O2", 10 "-Wno-sign-compare", 11 ], 12 13The Bison skeleton uses implicit fallthrough, so libraries won't compile unless 14we turn the 'no-implicit-fallthrough' warning off. The -O2 is required because 15the generated bison parser uses a ton of stack space in non-optimized builds. 16The entire parser is contained in a single giant function, and non-optimized 17compilation does not reuse stack slots for local variables. Without -O2, clients 18are likely to fail in fastbuild with default 64KB stack sizes, or to start 19failing when the parser is extended further. 20 21""" 22 23load("@rules_m4//m4:m4.bzl", "M4_TOOLCHAIN_TYPE", "m4_toolchain") 24 25def _genyacc_impl(ctx): 26 """Implementation for genyacc rule.""" 27 28 # Argument list 29 args = ctx.actions.args() 30 args.add("--defines=%s" % ctx.outputs.header_out.path) 31 if ctx.outputs.location_out: 32 args.add('--define=api.location.file="%s"' % ctx.outputs.location_out.basename) 33 args.add('--define=api.location.include=""%s""' % ctx.outputs.location_out.short_path) 34 args.add("--output-file=%s" % ctx.outputs.source_out.path) 35 if ctx.attr.prefix: 36 args.add("--name-prefix=%s" % ctx.attr.prefix) 37 args.add_all([ctx.expand_location(opt) for opt in ctx.attr.extra_options]) 38 args.add(ctx.file.src.path) 39 40 # Output files 41 outputs = ctx.outputs.extra_outs + [ 42 ctx.outputs.header_out, 43 ctx.outputs.location_out, 44 ctx.outputs.source_out, 45 ] 46 47 m4 = m4_toolchain(ctx) 48 ctx.actions.run( 49 executable = ctx.executable._bison, 50 env = { 51 "M4": m4.m4_tool.executable.path, 52 }, 53 arguments = [args], 54 inputs = ctx.files.src, 55 tools = [m4.m4_tool.executable], 56 outputs = outputs, 57 mnemonic = "Yacc", 58 progress_message = "Generating %s and %s from %s" % 59 ( 60 ctx.outputs.source_out.short_path, 61 ctx.outputs.header_out.short_path, 62 ctx.file.src.short_path, 63 ), 64 ) 65 66genyacc = rule( 67 implementation = _genyacc_impl, 68 doc = "Generate C/C++-language sources from a Yacc file using Bison.", 69 attrs = { 70 "src": attr.label( 71 mandatory = True, 72 allow_single_file = [".y", ".yy", ".yc", ".ypp", ".yxx"], 73 doc = "The .y, .yy, or .yc source file for this rule", 74 ), 75 "header_out": attr.output( 76 mandatory = True, 77 doc = "The generated 'defines' header file", 78 ), 79 "location_out": attr.output( 80 mandatory = False, 81 doc = "The generated 'location' header file", 82 ), 83 "source_out": attr.output(mandatory = True, doc = "The generated source file"), 84 "prefix": attr.string( 85 doc = "External symbol prefix for Bison. This string is " + 86 "passed to bison as the -p option, causing the resulting C " + 87 "file to define external functions named 'prefix'parse, " + 88 "'prefix'lex, etc. instead of yyparse, yylex, etc.", 89 ), 90 "extra_outs": attr.output_list(doc = "A list of extra generated output files."), 91 "extra_options": attr.string_list( 92 doc = "A list of extra options to pass to Bison. These are " + 93 "subject to $(location ...) expansion.", 94 ), 95 "_bison": attr.label( 96 default = Label("//third_party/parser:bison_bin"), 97 executable = True, 98 cfg = "host", 99 ), 100 }, 101 output_to_genfiles = True, 102 toolchains = [M4_TOOLCHAIN_TYPE], 103) 104