- add sources.
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / build_tools / dsc2gyp.py
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 import StringIO
6 import sys
7 import os
8 import optparse
9
10 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
11 sys.path.append(os.path.join(os.path.dirname(SCRIPT_DIR), 'tools'))
12
13 import getos
14
15 valid_tools = ['newlib', 'glibc', getos.GetPlatform()]
16
17
18 def Error(msg):
19   print(msg)
20   sys.exit(1)
21
22
23 PREAMBLE = """\
24 {
25   'includes': ['%s/build_tools/nacl.gypi'],
26 """
27
28 NEXE_TARGET = """\
29     {
30       'target_name': '%(NAME)s_x86_32%(EXT)s',
31       'product_name': '%(NAME)s_x86_32%(EXT)s',
32       'type': '%(GYP_TYPE)s',
33       'sources': %(SOURCES)s,
34       'libraries': %(LIBS)s,
35       'include_dirs': %(INCLUDES)s,
36       'cflags': ['-m32', '-pedantic'] + %(CFLAGS)s,
37       'make_valid_configurations': ['newlib-debug', 'newlib-release',
38                                     'glibc-debug', 'glibc-release'],
39       'ldflags': ['-m32', '-L../../lib/x86_32/<(CONFIGURATION_NAME)'],
40       'toolset': 'target',
41       %(CONFIGS)s
42     },
43     {
44       'target_name': '%(NAME)s_x86_64%(EXT)s',
45       'product_name': '%(NAME)s_x86_64%(EXT)s',
46       'type': '%(GYP_TYPE)s',
47       'sources': %(SOURCES)s,
48       'libraries': %(LIBS)s,
49       'include_dirs': %(INCLUDES)s,
50       'make_valid_configurations': ['newlib-debug', 'newlib-release',
51                                     'glibc-debug', 'glibc-release'],
52       'cflags': ['-m64', '-pedantic'] + %(CFLAGS)s,
53       'ldflags': ['-m64', '-L../../lib/x86_64/<(CONFIGURATION_NAME)'],
54       'toolset': 'target',
55       %(CONFIGS)s
56     },
57 """
58
59 NLIB_TARGET = """\
60     {
61       'target_name': '%(NAME)s_x86_32%(EXT)s',
62       'product_name': 'lib%(NAME)s%(EXT)s',
63       'product_dir': '../../lib/x86_32/<(CONFIGURATION_NAME)',
64       'type': '%(GYP_TYPE)s',
65       'sources': %(SOURCES)s,
66       'libraries': %(LIBS)s,
67       'include_dirs': %(INCLUDES)s,
68       'cflags': ['-m32', '-pedantic'] + %(CFLAGS)s,
69       'make_valid_configurations': ['newlib-debug', 'newlib-release',
70                                     'glibc-debug', 'glibc-release'],
71       'ldflags': ['-m32'],
72       'toolset': 'target',
73       %(CONFIGS)s
74     },
75     {
76       'target_name': '%(NAME)s_x86_64%(EXT)s',
77       'product_name': 'lib%(NAME)s%(EXT)s',
78       'product_dir': '../../lib/x86_64/<(CONFIGURATION_NAME)',
79       'type': '%(GYP_TYPE)s',
80       'sources': %(SOURCES)s,
81       'libraries': %(LIBS)s,
82       'include_dirs': %(INCLUDES)s,
83       'make_valid_configurations': ['newlib-debug', 'newlib-release',
84                                     'glibc-debug', 'glibc-release'],
85       'cflags': ['-m64', '-pedantic'] + %(CFLAGS)s,
86       'ldflags': ['-m64'],
87       'toolset': 'target',
88       %(CONFIGS)s
89     },
90 """
91
92 HOST_LIB_TARGET = """\
93     {
94       'target_name': '%(NAME)s%(EXT)s',
95       'type': '%(GYP_TYPE)s',
96       'toolset': 'host',
97       'sources': %(SOURCES)s,
98       'cflags': %(CFLAGS)s,
99       'cflags_c': ['-std=gnu99'],
100       'include_dirs': %(INCLUDES)s,
101       'make_valid_configurations': ['host-debug', 'host-release'],
102       'product_dir': '../../lib/%(ARCH)s/<(CONFIGURATION_NAME)',
103       'product_name': '%(NAME)s%(EXT)s',
104       %(CONFIGS)s
105     },
106 """
107
108 HOST_EXE_TARGET = """\
109     {
110       'target_name': '%(NAME)s%(EXT)s',
111       'type': '%(GYP_TYPE)s',
112       'toolset': 'host',
113       'sources': %(SOURCES)s,
114       'cflags': %(CFLAGS)s,
115       'cflags_c': ['-std=gnu99'],
116       'ldflags': ['-L../../lib/%(ARCH)s/<(CONFIGURATION_NAME)'],
117       'libraries': %(LIBS)s,
118       'include_dirs': %(INCLUDES)s,
119       'make_valid_configurations': ['host-debug', 'host-release'],
120       'msvs_settings': {
121         'VCLinkerTool': {
122           'AdditionalLibraryDirectories':
123             ['../../lib/%(ARCH)s/<(CONFIGURATION_NAME)'],
124          }
125        },
126        %(CONFIGS)s
127     },
128 """
129
130 NMF_TARGET = """\
131     {
132       'target_name': '%(NAME)s_%(TOOLCHAIN)s.nmf',
133       'product_name': '%(NAME)s.nmf',
134       'product_dir': '<(PRODUCT_DIR)/%(TOOLCHAIN)s',
135       'type': 'none',
136       'make_valid_configurations': ['%(TOOLCHAIN)s-debug', '%(TOOLCHAIN)s-release'],
137       'actions': [
138         {
139           'action_name': 'nmf',
140           'inputs': ['<(PRODUCT_DIR)/%(NAME)s_x86_32.nexe',
141                      '<(PRODUCT_DIR)/%(NAME)s_x86_64.nexe'] + %(SODEPS)s,
142           'outputs': ['<(PRODUCT_DIR)/%(NAME)s.nmf'],
143           'action': ['../../tools/create_nmf.py', '-t', '%(TOOLCHAIN)s', '-s',
144                      '<(PRODUCT_DIR)'] + %(NMFACTION)s,
145         },
146       ]
147     },
148 """
149
150 TOOLCHAIN_CONFIG = """\
151         '%(toolchain)s-release' : {
152           'cflags' : ['-O2'],
153         },
154         '%(toolchain)s-debug' : {
155           'cflags' : ['-g', '-O0'],
156         },
157 """
158
159 NEXE_CONFIG = """\
160           '%(toolchain)s-release' : {
161             'cflags' : ['--%(toolchain)s', '-O2',
162                         '-idirafter', '../../include'],
163             'ldflags' : ['--%(toolchain)s'],
164             'arflags' : ['--%(toolchain)s'],
165           },
166           '%(toolchain)s-debug' : {
167             'cflags' : ['--%(toolchain)s', '-g', '-O0',
168                         '-idirafter', '../../include'],
169             'ldflags' : ['--%(toolchain)s'],
170             'arflags' : ['--%(toolchain)s'],
171           },
172 """
173
174 WIN32_CONFIGS = """\
175   'target_defaults': {
176     'default_configuration': 'Debug_PPAPI',
177     'configurations': {
178       'Debug_PPAPI': {
179         'msvs_configuration_platform': 'PPAPI',
180         'msbuild_configuration_attributes': {
181           'ConfigurationType': 'DynamicLibrary'
182         },
183         'include_dirs': ['../../include/win'],
184         'defines': ['_WINDOWS', '_DEBUG', 'WIN32'],
185       },
186       'Release_PPAPI': {
187         'msvs_configuration_platform': 'PPAPI',
188         'msbuild_configuration_attributes': {
189           'ConfigurationType': 'DynamicLibrary'
190         },
191         'include_dirs': ['../../include/win'],
192         'defines': ['_WINDOWS', 'NDEBUG', 'WIN32'],
193       },
194       'Debug_NaCl': {
195         'msvs_configuration_platform': 'NaCl',
196         'msbuild_configuration_attributes': {
197           'ConfigurationType': 'Application'
198         },
199       },
200       'Release_NaCl': {
201         'msvs_configuration_platform': 'NaCl',
202         'msbuild_configuration_attributes': {
203           'ConfigurationType': 'Application'
204         },
205       },
206     },
207   },
208 """
209
210
211 def WriteNaClTargets(output, target, tools):
212   configs = "'configurations' : {\n"
213   for tc in tools:
214     if tc not in valid_tools:
215       continue
216     if tc in ['newlib', 'glibc']:
217       configs += NEXE_CONFIG % {'toolchain': tc}
218   configs += "      }"
219   target['CONFIGS'] = configs
220   if target['TYPE'] == 'lib':
221     output.write(NLIB_TARGET % target)
222   else:
223     output.write(NEXE_TARGET % target)
224
225
226 def ConfigName(toolchain):
227   if toolchain == getos.GetPlatform():
228     return 'host'
229   else:
230     return toolchain
231
232
233 def ProcessDSC(filename, outfile=None):
234   if not os.path.exists(filename):
235     Error("file not found: %s" % filename)
236
237   desc = open(filename).read()
238   desc = eval(desc, {}, {})
239   if not desc.get('TARGETS'):
240     Error("no TARGETS found in dsc")
241
242   if not outfile:
243     outfile = desc['NAME'] + '.gyp'
244     outfile = os.path.join(os.path.dirname(filename), outfile)
245
246   output = StringIO.StringIO()
247
248   srcdir = os.path.dirname(SCRIPT_DIR)
249   output.write(PREAMBLE % srcdir.replace("\\", '/'))
250
251   win32 = sys.platform in ('win32', 'cygwin')
252   if win32:
253     output.write(WIN32_CONFIGS)
254   else:
255     for tc in desc['TOOLS']:
256       if tc in valid_tools:
257         default = '%s-debug' % ConfigName(tc)
258         break
259
260     output.write("""\
261   'target_defaults': {
262     'default_configuration': '%s',
263     'configurations' : {\n""" % default)
264
265     for tc in desc['TOOLS']:
266       if tc not in valid_tools:
267         continue
268       output.write(TOOLCHAIN_CONFIG % {'toolchain': ConfigName(tc)})
269
270     output.write("    }\n  },\n")
271
272   output.write("\n  'targets': [\n")
273
274   # make a list of all the so target names so that the nmf rules
275   # can depend on them all
276   sofiles = []
277   soremap = []
278   for target in desc['TARGETS']:
279     if target['TYPE'] == 'so':
280       name = target['NAME']
281       sofiles.append('<(PRODUCT_DIR)/%s_x86_64.so' % name)
282       sofiles.append('<(PRODUCT_DIR)/%s_x86_32.so' % name)
283       soremap += ['-n', '%s_x86_64.so,%s.so' % (name, name)]
284       soremap += ['-n', '%s_x86_32.so,%s.so' % (name, name)]
285
286
287   # iterate through dsc targets generating gyp targets
288   for target in desc['TARGETS']:
289     target.setdefault('INCLUDES', [])
290     target['INCLUDES'] = [x.replace("$(NACL_SDK_ROOT)", "../..")
291                           for x in target['INCLUDES']]
292
293     libs = target.get('LIBS', [])
294     if win32:
295       libs = [l for l in libs if l not in ('ppapi', 'ppapi_cpp')]
296       target['LIBS'] = ['-l' + l + '.lib' for l in libs]
297     else:
298       target['LIBS'] = ['-l' + l for l in libs]
299     if target['TYPE'] == 'so':
300       if win32:
301         target['EXT'] = ''
302       else:
303         target['EXT'] = '.so'
304       target['GYP_TYPE'] = 'shared_library'
305     elif target['TYPE'] == 'lib':
306       if win32:
307         target['EXT'] = ''
308       else:
309         target['EXT'] = '.a'
310       target['GYP_TYPE'] = 'static_library'
311     elif target['TYPE'] == 'main':
312       target['EXT'] = '.nexe'
313       target['GYP_TYPE'] = 'executable'
314     else:
315       Error("unknown type: %s" % target['TYPE'])
316
317     target['CFLAGS'] = target.get('CXXFLAGS', [])
318
319     if not win32 and ('newlib' in desc['TOOLS'] or 'glibc' in desc['TOOLS']):
320       WriteNaClTargets(output, target, desc['TOOLS'])
321       if target['TYPE'] == 'main':
322         target['SODEPS'] = sofiles
323         target['NMFACTION'] = ['-o', '<@(_outputs)', '-L<(NMF_PATH1)',
324                                '-L<(NMF_PATH2)', '-D', '<(OBJDUMP)',
325                                '<@(_inputs)']
326         target['NMFACTION'] += soremap
327         if 'newlib' in desc['TOOLS']:
328           target['TOOLCHAIN'] = 'newlib'
329           output.write(NMF_TARGET % target)
330         if 'glibc' in desc['TOOLS']:
331           target['TOOLCHAIN'] = 'glibc'
332           output.write(NMF_TARGET % target)
333
334     if win32 or getos.GetPlatform() in desc['TOOLS']:
335       target['ARCH'] = 'x86_32'
336       target['INCLUDES'].append('../../include')
337       if win32:
338         target['HOST'] = 'win'
339         target['CONFIGS'] = ''
340         target['CFLAGS'] = []
341       else:
342         target['CONFIGS'] = ''
343         target['HOST'] = 'linux'
344         target['CFLAGS'].append('-fPIC')
345       if target['TYPE'] == 'main':
346         target['GYP_TYPE'] = 'shared_library'
347         if win32:
348           target['EXT'] = ''
349         else:
350           target['EXT'] = '.so'
351         output.write(HOST_EXE_TARGET % target)
352       else:
353         output.write(HOST_LIB_TARGET % target)
354
355   output.write('  ],\n}\n')
356
357   print('Writing: ' + outfile)
358   open(outfile, 'w').write(output.getvalue())
359
360
361 def main(args):
362   parser = optparse.OptionParser()
363   parser.add_option('-o', help='Set output filename.', dest='output')
364   options, args = parser.parse_args(args)
365   if not args:
366     Error('No .dsc file specified.')
367
368   if options.output:
369     outdir = os.path.dirname(options.output)
370     if not os.path.exists(outdir):
371       os.makedirs(outdir)
372
373   assert len(args) == 1
374   ProcessDSC(args[0], options.output)
375
376
377 if __name__ == '__main__':
378   main(sys.argv[1:])