xref: /aosp_15_r20/external/angle/build/write_buildflag_header.py (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*8975f5c5SAndroid Build Coastguard Worker# Copyright 2015 The Chromium Authors
3*8975f5c5SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker# found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker
6*8975f5c5SAndroid Build Coastguard Worker# This writes headers for build flags. See buildflag_header.gni for usage of
7*8975f5c5SAndroid Build Coastguard Worker# this system as a whole.
8*8975f5c5SAndroid Build Coastguard Worker#
9*8975f5c5SAndroid Build Coastguard Worker# The parameters are passed in a response file so we don't have to worry
10*8975f5c5SAndroid Build Coastguard Worker# about command line lengths. The name of the response file is passed on the
11*8975f5c5SAndroid Build Coastguard Worker# command line.
12*8975f5c5SAndroid Build Coastguard Worker#
13*8975f5c5SAndroid Build Coastguard Worker# The format of the response file is:
14*8975f5c5SAndroid Build Coastguard Worker#    [--flags <list of one or more flag values>]
15*8975f5c5SAndroid Build Coastguard Worker
16*8975f5c5SAndroid Build Coastguard Workerimport optparse
17*8975f5c5SAndroid Build Coastguard Workerimport os
18*8975f5c5SAndroid Build Coastguard Workerimport re
19*8975f5c5SAndroid Build Coastguard Workerimport shlex
20*8975f5c5SAndroid Build Coastguard Worker
21*8975f5c5SAndroid Build Coastguard Worker
22*8975f5c5SAndroid Build Coastguard Workerclass Options:
23*8975f5c5SAndroid Build Coastguard Worker  def __init__(self, output, rulename, header_guard, flags):
24*8975f5c5SAndroid Build Coastguard Worker    self.output = output
25*8975f5c5SAndroid Build Coastguard Worker    self.rulename = rulename
26*8975f5c5SAndroid Build Coastguard Worker    self.header_guard = header_guard
27*8975f5c5SAndroid Build Coastguard Worker    self.flags = flags
28*8975f5c5SAndroid Build Coastguard Worker
29*8975f5c5SAndroid Build Coastguard Worker
30*8975f5c5SAndroid Build Coastguard Workerdef GetOptions():
31*8975f5c5SAndroid Build Coastguard Worker  parser = optparse.OptionParser()
32*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--output', help="Output header name inside --gen-dir.")
33*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--rulename',
34*8975f5c5SAndroid Build Coastguard Worker                    help="Helpful name of build rule for including in the " +
35*8975f5c5SAndroid Build Coastguard Worker                         "comment at the top of the file.")
36*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--gen-dir',
37*8975f5c5SAndroid Build Coastguard Worker                    help="Path to root of generated file directory tree.")
38*8975f5c5SAndroid Build Coastguard Worker  parser.add_option('--definitions',
39*8975f5c5SAndroid Build Coastguard Worker                    help="Name of the response file containing the flags.")
40*8975f5c5SAndroid Build Coastguard Worker  cmdline_options, cmdline_flags = parser.parse_args()
41*8975f5c5SAndroid Build Coastguard Worker
42*8975f5c5SAndroid Build Coastguard Worker  # Compute a valid C++ header guard by replacing non valid chars with '_',
43*8975f5c5SAndroid Build Coastguard Worker  # upper-casing everything and prepending '_' if first symbol is digit.
44*8975f5c5SAndroid Build Coastguard Worker  header_guard = cmdline_options.output.upper()
45*8975f5c5SAndroid Build Coastguard Worker  if header_guard[0].isdigit():
46*8975f5c5SAndroid Build Coastguard Worker    header_guard = '_' + header_guard
47*8975f5c5SAndroid Build Coastguard Worker  header_guard = re.sub(r'[^\w]', '_', header_guard)
48*8975f5c5SAndroid Build Coastguard Worker  header_guard += '_'
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker  # The actual output file is inside the gen dir.
51*8975f5c5SAndroid Build Coastguard Worker  output = os.path.join(cmdline_options.gen_dir, cmdline_options.output)
52*8975f5c5SAndroid Build Coastguard Worker
53*8975f5c5SAndroid Build Coastguard Worker  # Definition file in GYP is newline separated, in GN they are shell formatted.
54*8975f5c5SAndroid Build Coastguard Worker  # shlex can parse both of these.
55*8975f5c5SAndroid Build Coastguard Worker  with open(cmdline_options.definitions, 'r') as def_file:
56*8975f5c5SAndroid Build Coastguard Worker    defs = shlex.split(def_file.read())
57*8975f5c5SAndroid Build Coastguard Worker  flags_index = defs.index('--flags')
58*8975f5c5SAndroid Build Coastguard Worker
59*8975f5c5SAndroid Build Coastguard Worker  # Everything after --flags are flags. true/false are remapped to 1/0,
60*8975f5c5SAndroid Build Coastguard Worker  # everything else is passed through.
61*8975f5c5SAndroid Build Coastguard Worker  flags = []
62*8975f5c5SAndroid Build Coastguard Worker  for flag in defs[flags_index + 1 :]:
63*8975f5c5SAndroid Build Coastguard Worker    equals_index = flag.index('=')
64*8975f5c5SAndroid Build Coastguard Worker    key = flag[:equals_index]
65*8975f5c5SAndroid Build Coastguard Worker    value = flag[equals_index + 1:]
66*8975f5c5SAndroid Build Coastguard Worker
67*8975f5c5SAndroid Build Coastguard Worker    # Canonicalize and validate the value.
68*8975f5c5SAndroid Build Coastguard Worker    if value == 'true':
69*8975f5c5SAndroid Build Coastguard Worker      value = '1'
70*8975f5c5SAndroid Build Coastguard Worker    elif value == 'false':
71*8975f5c5SAndroid Build Coastguard Worker      value = '0'
72*8975f5c5SAndroid Build Coastguard Worker    flags.append((key, str(value)))
73*8975f5c5SAndroid Build Coastguard Worker
74*8975f5c5SAndroid Build Coastguard Worker  return Options(output=output,
75*8975f5c5SAndroid Build Coastguard Worker                 rulename=cmdline_options.rulename,
76*8975f5c5SAndroid Build Coastguard Worker                 header_guard=header_guard,
77*8975f5c5SAndroid Build Coastguard Worker                 flags=flags)
78*8975f5c5SAndroid Build Coastguard Worker
79*8975f5c5SAndroid Build Coastguard Worker
80*8975f5c5SAndroid Build Coastguard Workerdef WriteHeader(options):
81*8975f5c5SAndroid Build Coastguard Worker  with open(options.output, 'w') as output_file:
82*8975f5c5SAndroid Build Coastguard Worker    output_file.write("// Generated by build/write_buildflag_header.py\n")
83*8975f5c5SAndroid Build Coastguard Worker    if options.rulename:
84*8975f5c5SAndroid Build Coastguard Worker      output_file.write('// From "' + options.rulename + '"\n')
85*8975f5c5SAndroid Build Coastguard Worker
86*8975f5c5SAndroid Build Coastguard Worker    output_file.write('\n#ifndef %s\n' % options.header_guard)
87*8975f5c5SAndroid Build Coastguard Worker    output_file.write('#define %s\n\n' % options.header_guard)
88*8975f5c5SAndroid Build Coastguard Worker    output_file.write('#include "build/buildflag.h" // IWYU pragma: export\n\n')
89*8975f5c5SAndroid Build Coastguard Worker    # Clangd does not detect BUILDFLAG_INTERNAL_* indirect usage, so mark the
90*8975f5c5SAndroid Build Coastguard Worker    # header as "always_keep" to avoid "unused include" warning.
91*8975f5c5SAndroid Build Coastguard Worker    output_file.write('// IWYU pragma: always_keep\n\n')
92*8975f5c5SAndroid Build Coastguard Worker
93*8975f5c5SAndroid Build Coastguard Worker    for pair in options.flags:
94*8975f5c5SAndroid Build Coastguard Worker      output_file.write('#define BUILDFLAG_INTERNAL_%s() (%s)\n' % pair)
95*8975f5c5SAndroid Build Coastguard Worker
96*8975f5c5SAndroid Build Coastguard Worker    output_file.write('\n#endif  // %s\n' % options.header_guard)
97*8975f5c5SAndroid Build Coastguard Worker
98*8975f5c5SAndroid Build Coastguard Worker
99*8975f5c5SAndroid Build Coastguard Workeroptions = GetOptions()
100*8975f5c5SAndroid Build Coastguard WorkerWriteHeader(options)
101