1# Copyright 2020 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import argparse
6import errno
7import io
8import json
9import os
10import sys
11
12import grit.format.html_inline
13import grit.node.base
14import grit.util
15
16_CWD = os.getcwd()
17
18
19class PreprocessNode(grit.node.base.Node):
20  def __init__(self):
21    super(PreprocessNode, self).__init__()
22
23  def ProcessFile(self, filepath):
24    return grit.format.html_inline.InlineToString(
25        filepath,
26        self,
27        preprocess_only=True,
28        allow_external_script=False,
29        strip_whitespace=False,
30        rewrite_function=None,
31        filename_expansion_function=None)
32
33  def EvaluateCondition(self, expr):
34    return grit.node.base.Node.EvaluateExpression(expr, self.defines,
35                                                  self.target_platform, {})
36
37  def SetDefines(self, defines):
38    self.defines = defines
39
40  def SetTargetPlatform(self, target_platform):
41    self.target_platform = target_platform
42
43  @staticmethod
44  def Construct(defines, target_platform):
45    node = PreprocessNode()
46    node.SetDefines(defines)
47    node.SetTargetPlatform(target_platform or sys.platform)
48    return node
49
50
51def main(argv):
52  parser = argparse.ArgumentParser()
53  parser.add_argument('--in-folder', required=True)
54  parser.add_argument('--out-folder', required=True)
55  parser.add_argument('--out-manifest')
56  parser.add_argument('--in-files', required=True, nargs="*")
57  parser.add_argument('-D', '--defines', nargs="*", action='append')
58  parser.add_argument('-E', '--environment')
59  parser.add_argument('-t', '--target')
60  args = parser.parse_args(argv)
61
62  in_folder = os.path.normpath(os.path.join(_CWD, args.in_folder))
63  out_folder = os.path.normpath(os.path.join(_CWD, args.out_folder))
64
65  defines = {}
66  for define_arg in args.defines:
67    define, = define_arg
68    name, val = grit.util.ParseDefine(define)
69    defines[name] = val
70
71  node = PreprocessNode.Construct(defines, args.target)
72
73  for input_file in args.in_files:
74    output = node.ProcessFile(os.path.join(in_folder, input_file))
75
76    out_path = os.path.join(out_folder, input_file)
77    out_dir = os.path.dirname(out_path)
78    assert out_dir.startswith(out_folder), \
79           'Cannot preprocess files to locations not under %s.' % out_dir
80    try:
81      os.makedirs(out_dir)
82    except OSError as e:
83      # Ignore directory exists errors. This can happen if two build rules
84      # for overlapping directories hit the makedirs line at the same time.
85      if e.errno != errno.EEXIST:
86        raise
87    with io.open(out_path, mode='wb') as f:
88      f.write(output.encode('utf-8'))
89
90  if args.out_manifest:
91    manifest_data = {}
92    manifest_data['base_dir'] = '%s' % args.out_folder
93    manifest_data['files'] = args.in_files
94    manifest_file = open(
95        os.path.normpath(os.path.join(_CWD, args.out_manifest)), 'wb')
96    json.dump(manifest_data, manifest_file)
97  return
98
99
100if __name__ == '__main__':
101  main(sys.argv[1:])
102