1#!/usr/bin/env python
2# This Source Code Form is subject to the terms of the Mozilla Public
3# License, v. 2.0. If a copy of the MPL was not distributed with this
4# file, You can obtain one at http://mozilla.org/MPL/2.0/.
5
6# This script is used to generate an output header and xpt file for
7# input IDL file(s). It's purpose is to directly support the build
8# system. The API will change to meet the needs of the build system.
9
10from __future__ import absolute_import
11
12import argparse
13import os
14import sys
15
16from io import BytesIO
17
18from buildconfig import topsrcdir
19from xpidl.header import print_header
20from xpidl.typelib import write_typelib
21from xpidl.xpidl import IDLParser
22from xpt import xpt_link
23
24from mozbuild.makeutil import Makefile
25from mozbuild.pythonutil import iter_modules_in_path
26from mozbuild.util import FileAvoidWrite
27
28
29def process(input_dir, inc_paths, cache_dir, header_dir, xpt_dir, deps_dir, module, stems):
30    p = IDLParser(outputdir=cache_dir)
31
32    xpts = {}
33    mk = Makefile()
34    rule = mk.create_rule()
35
36    # Write out dependencies for Python modules we import. If this list isn't
37    # up to date, we will not re-process XPIDL files if the processor changes.
38    rule.add_dependencies(iter_modules_in_path(topsrcdir))
39
40    for stem in stems:
41        path = os.path.join(input_dir, '%s.idl' % stem)
42        idl_data = open(path).read()
43
44        idl = p.parse(idl_data, filename=path)
45        idl.resolve([input_dir] + inc_paths, p)
46
47        header_path = os.path.join(header_dir, '%s.h' % stem)
48
49        xpt = BytesIO()
50        write_typelib(idl, xpt, path)
51        xpt.seek(0)
52        xpts[stem] = xpt
53
54        rule.add_dependencies(idl.deps)
55
56        with FileAvoidWrite(header_path) as fh:
57            print_header(idl, fh, path)
58
59    # TODO use FileAvoidWrite once it supports binary mode.
60    xpt_path = os.path.join(xpt_dir, '%s.xpt' % module)
61    xpt_link(xpts.values()).write(xpt_path)
62
63    rule.add_targets([xpt_path])
64    if deps_dir:
65        deps_path = os.path.join(deps_dir, '%s.pp' % module)
66        with FileAvoidWrite(deps_path) as fh:
67            mk.dump(fh)
68
69
70def main(argv):
71    parser = argparse.ArgumentParser()
72    parser.add_argument('--cache-dir',
73        help='Directory in which to find or write cached lexer data.')
74    parser.add_argument('--depsdir',
75        help='Directory in which to write dependency files.')
76    parser.add_argument('inputdir',
77        help='Directory in which to find source .idl files.')
78    parser.add_argument('headerdir',
79        help='Directory in which to write header files.')
80    parser.add_argument('xptdir',
81        help='Directory in which to write xpt file.')
82    parser.add_argument('module',
83        help='Final module name to use for linked output xpt file.')
84    parser.add_argument('idls', nargs='+',
85        help='Source .idl file(s). Specified as stems only.')
86    parser.add_argument('-I', dest='incpath', action='append', default=[],
87        help='Extra directories where to look for included .idl files.')
88
89    args = parser.parse_args(argv)
90    process(args.inputdir, args.incpath, args.cache_dir, args.headerdir,
91        args.xptdir, args.depsdir, args.module, args.idls)
92
93if __name__ == '__main__':
94    main(sys.argv[1:])
95