blob: 1446d811630c1fd2023291aed5c1dd6194ca6c39 [file] [log] [blame]
brettw@chromium.orgc976b182014-04-06 13:35:10 +09001# Copyright 2014 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
5"""Converts a given gypi file to a python scope and writes the result to stdout.
6
7It is assumed that the file contains a toplevel dictionary, and this script
8will return that dictionary as a GN "scope" (see example below). This script
9does not know anything about GYP and it will not expand variables or execute
10conditions (it will check for the presence of a "conditions" value in the
11dictionary and will abort if it is present). It also does not support nested
12dictionaries.
13
14Say your_file.gypi looked like this:
15 {
16 'sources': [ 'a.cc', 'b.cc' ],
17 'defines': [ 'ENABLE_DOOM_MELON' ],
18 }
19
20You would call it like this:
21 gypi_values = exec_script("//build/gypi_to_gn.py",
22 [ rebase_path("your_file.gypi") ],
23 "scope",
24 [ "your_file.gypi" ])
25
26Notes:
27 - The rebase_path call converts the gypi file from being relative to the
28 current build file to being system absolute for calling the script, which
29 will have a different current directory than this file.
30
31 - The "scope" parameter tells GN to interpret the result as a series of GN
32 variable assignments.
33
34 - The last file argument to exec_script tells GN that the given file is a
35 dependency of the build so Ninja can automatically re-run GN if the file
36 changes.
37
38Read the values into a target like this:
39 component("mycomponent") {
40 sources = gypi_values.sources
41 defines = gypi_values.defines
42 }
43
44Sometimes your .gypi file will include paths relative to a different
45directory than the current .gn file. In this case, you can rebase them to
46be relative to the current directory.
47 sources = rebase_path(gypi_values.sources, ".",
48 "//path/gypi/input/values/are/relative/to")
49"""
50
51import gn_helpers
52from optparse import OptionParser
53import sys
54
55def LoadPythonDictionary(path):
56 file_string = open(path).read()
57 try:
58 file_data = eval(file_string, {'__builtins__': None}, None)
59 except SyntaxError, e:
60 e.filename = path
61 raise
62 except Exception, e:
63 raise Exception("Unexpected error while reading %s: %s" % (path, str(e)))
64
65 assert isinstance(file_data, dict), "%s does not eval to a dictionary" % path
66 assert 'conditions' not in file_data, \
67 "The file %s has conditions in it, these aren't supported." % path
68
69 return file_data
70
71
72def main():
73 parser = OptionParser()
74 (options, args) = parser.parse_args()
75
76 if len(args) != 1:
77 raise Exception("Need one argument which is the .gypi file to read.")
78
79 data = LoadPythonDictionary(args[0])
80 print gn_helpers.ToGNString(data)
81
82if __name__ == '__main__':
83 try:
84 main()
85 except Exception, e:
86 print str(e)
87 sys.exit(1)