blob: 7032e94c0631d84d167f51e9e63be25507bbbec1 [file] [log] [blame]
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import StringIO
import sys
import os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.join(os.path.dirname(SCRIPT_DIR), 'tools'))
import getos
valid_tools = ['newlib', 'glibc', getos.GetPlatform()]
def Error(msg):
print(msg)
sys.exit(1)
PREAMBLE = """\
{
'includes': ['%s/build_tools/nacl.gypi'],
"""
NEXE_TARGET = """\
{
'target_name': '%(NAME)s_x86_32%(EXT)s',
'product_name': '%(NAME)s_x86_32%(EXT)s',
'type': '%(GYP_TYPE)s',
'sources': %(SOURCES)s,
'libraries': %(LIBS)s,
'include_dirs': %(INCLUDES)s,
'cflags': ['-m32', '-pedantic'] + %(CFLAGS)s,
'make_valid_configurations': ['newlib-debug', 'newlib-release',
'glibc-debug', 'glibc-release'],
'ldflags': ['-m32', '-L../../lib/x86_32/<(CONFIGURATION_NAME)'],
'toolset': 'target',
%(CONFIGS)s
},
{
'target_name': '%(NAME)s_x86_64%(EXT)s',
'product_name': '%(NAME)s_x86_64%(EXT)s',
'type': '%(GYP_TYPE)s',
'sources': %(SOURCES)s,
'libraries': %(LIBS)s,
'include_dirs': %(INCLUDES)s,
'make_valid_configurations': ['newlib-debug', 'newlib-release',
'glibc-debug', 'glibc-release'],
'cflags': ['-m64', '-pedantic'] + %(CFLAGS)s,
'ldflags': ['-m64', '-L../../lib/x86_64/<(CONFIGURATION_NAME)'],
'toolset': 'target',
%(CONFIGS)s
},
"""
NLIB_TARGET = """\
{
'target_name': '%(NAME)s_x86_32%(EXT)s',
'product_name': 'lib%(NAME)s%(EXT)s',
'product_dir': '../../lib/x86_32/<(CONFIGURATION_NAME)',
'type': '%(GYP_TYPE)s',
'sources': %(SOURCES)s,
'libraries': %(LIBS)s,
'include_dirs': %(INCLUDES)s,
'cflags': ['-m32', '-pedantic'] + %(CFLAGS)s,
'make_valid_configurations': ['newlib-debug', 'newlib-release',
'glibc-debug', 'glibc-release'],
'ldflags': ['-m32'],
'toolset': 'target',
%(CONFIGS)s
},
{
'target_name': '%(NAME)s_x86_64%(EXT)s',
'product_name': 'lib%(NAME)s%(EXT)s',
'product_dir': '../../lib/x86_64/<(CONFIGURATION_NAME)',
'type': '%(GYP_TYPE)s',
'sources': %(SOURCES)s,
'libraries': %(LIBS)s,
'include_dirs': %(INCLUDES)s,
'make_valid_configurations': ['newlib-debug', 'newlib-release',
'glibc-debug', 'glibc-release'],
'cflags': ['-m64', '-pedantic'] + %(CFLAGS)s,
'ldflags': ['-m64'],
'toolset': 'target',
%(CONFIGS)s
},
"""
HOST_LIB_TARGET = """\
{
'target_name': '%(NAME)s%(EXT)s',
'type': '%(GYP_TYPE)s',
'toolset': 'host',
'sources': %(SOURCES)s,
'cflags': %(CFLAGS)s,
'cflags_c': ['-std=gnu99'],
'include_dirs': %(INCLUDES)s,
'make_valid_configurations': ['host-debug', 'host-release'],
'product_dir': '../../lib/%(ARCH)s/<(CONFIGURATION_NAME)',
'product_name': '%(NAME)s%(EXT)s',
%(CONFIGS)s
},
"""
HOST_EXE_TARGET = """\
{
'target_name': '%(NAME)s%(EXT)s',
'type': '%(GYP_TYPE)s',
'toolset': 'host',
'sources': %(SOURCES)s,
'cflags': %(CFLAGS)s,
'cflags_c': ['-std=gnu99'],
'ldflags': ['-L../../lib/%(ARCH)s/<(CONFIGURATION_NAME)'],
'libraries': %(LIBS)s,
'include_dirs': %(INCLUDES)s,
'make_valid_configurations': ['host-debug', 'host-release'],
'msvs_settings': {
'VCLinkerTool': {
'AdditionalLibraryDirectories':
['../../lib/%(ARCH)s/<(CONFIGURATION_NAME)'],
}
},
%(CONFIGS)s
},
"""
NMF_TARGET = """\
{
'target_name': '%(NAME)s_%(TOOLCHAIN)s.nmf',
'product_name': '%(NAME)s.nmf',
'product_dir': '<(PRODUCT_DIR)/%(TOOLCHAIN)s',
'type': 'none',
'make_valid_configurations': ['%(TOOLCHAIN)s-debug', '%(TOOLCHAIN)s-release'],
'actions': [
{
'action_name': 'nmf',
'inputs': ['<(PRODUCT_DIR)/%(NAME)s_x86_32.nexe',
'<(PRODUCT_DIR)/%(NAME)s_x86_64.nexe'] + %(SODEPS)s,
'outputs': ['<(PRODUCT_DIR)/%(NAME)s.nmf'],
'action': ['../../tools/create_nmf.py', '-t', '%(TOOLCHAIN)s', '-s',
'<(PRODUCT_DIR)'] + %(NMFACTION)s,
},
]
},
"""
TOOLCHAIN_CONFIG = """\
'%(toolchain)s-release' : {
'cflags' : ['-O2'],
},
'%(toolchain)s-debug' : {
'cflags' : ['-g', '-O0'],
},
"""
NEXE_CONFIG = """\
'%(toolchain)s-release' : {
'cflags' : ['--%(toolchain)s', '-O2',
'-idirafter', '../../include'],
'ldflags' : ['--%(toolchain)s'],
'arflags' : ['--%(toolchain)s'],
},
'%(toolchain)s-debug' : {
'cflags' : ['--%(toolchain)s', '-g', '-O0',
'-idirafter', '../../include'],
'ldflags' : ['--%(toolchain)s'],
'arflags' : ['--%(toolchain)s'],
},
"""
WIN32_CONFIGS = """\
'target_defaults': {
'default_configuration': 'Debug_PPAPI',
'configurations': {
'Debug_PPAPI': {
'msvs_configuration_platform': 'PPAPI',
'msbuild_configuration_attributes': {
'ConfigurationType': 'DynamicLibrary'
},
'include_dirs': ['../../include/win'],
'defines': ['_WINDOWS', '_DEBUG', 'WIN32'],
},
'Release_PPAPI': {
'msvs_configuration_platform': 'PPAPI',
'msbuild_configuration_attributes': {
'ConfigurationType': 'DynamicLibrary'
},
'include_dirs': ['../../include/win'],
'defines': ['_WINDOWS', 'NDEBUG', 'WIN32'],
},
'Debug_NaCl': {
'msvs_configuration_platform': 'NaCl',
'msbuild_configuration_attributes': {
'ConfigurationType': 'Application'
},
},
'Release_NaCl': {
'msvs_configuration_platform': 'NaCl',
'msbuild_configuration_attributes': {
'ConfigurationType': 'Application'
},
},
},
},
"""
def WriteNaClTargets(output, target, tools):
configs = "'configurations' : {\n"
for tc in tools:
if tc not in valid_tools:
continue
if tc in ['newlib', 'glibc']:
configs += NEXE_CONFIG % {'toolchain': tc}
configs += " }"
target['CONFIGS'] = configs
if target['TYPE'] == 'lib':
output.write(NLIB_TARGET % target)
else:
output.write(NEXE_TARGET % target)
def ConfigName(toolchain):
if toolchain == getos.GetPlatform():
return 'host'
else:
return toolchain
def ProcessDSC(filename, outfile=None):
if not os.path.exists(filename):
Error("file not found: %s" % filename)
desc = open(filename).read()
desc = eval(desc, {}, {})
if not desc.get('TARGETS'):
Error("no TARGETS found in dsc")
if not outfile:
outfile = desc['NAME'] + '.gyp'
outfile = os.path.join(os.path.dirname(filename), outfile)
output = StringIO.StringIO()
srcdir = os.path.dirname(SCRIPT_DIR)
output.write(PREAMBLE % srcdir.replace("\\", '/'))
win32 = sys.platform in ('win32', 'cygwin')
if win32:
output.write(WIN32_CONFIGS)
else:
for tc in desc['TOOLS']:
if tc in valid_tools:
default = '%s-debug' % ConfigName(tc)
break
output.write("""\
'target_defaults': {
'default_configuration': '%s',
'configurations' : {\n""" % default)
for tc in desc['TOOLS']:
if tc not in valid_tools:
continue
output.write(TOOLCHAIN_CONFIG % {'toolchain': ConfigName(tc)})
output.write(" }\n },\n")
output.write("\n 'targets': [\n")
# make a list of all the so target names so that the nmf rules
# can depend on them all
sofiles = []
soremap = []
for target in desc['TARGETS']:
if target['TYPE'] == 'so':
name = target['NAME']
sofiles.append('<(PRODUCT_DIR)/%s_x86_64.so' % name)
sofiles.append('<(PRODUCT_DIR)/%s_x86_32.so' % name)
soremap += ['-n', '%s_x86_64.so,%s.so' % (name, name)]
soremap += ['-n', '%s_x86_32.so,%s.so' % (name, name)]
# iterate through dsc targets generating gyp targets
for target in desc['TARGETS']:
target.setdefault('INCLUDES', [])
target['INCLUDES'] = [x.replace("$(NACL_SDK_ROOT)", "../..")
for x in target['INCLUDES']]
libs = target.get('LIBS', [])
if win32:
libs = [l for l in libs if l not in ('ppapi', 'ppapi_cpp')]
target['LIBS'] = ['-l' + l + '.lib' for l in libs]
else:
target['LIBS'] = ['-l' + l for l in libs]
if target['TYPE'] == 'so':
if win32:
target['EXT'] = ''
else:
target['EXT'] = '.so'
target['GYP_TYPE'] = 'shared_library'
elif target['TYPE'] == 'lib':
if win32:
target['EXT'] = ''
else:
target['EXT'] = '.a'
target['GYP_TYPE'] = 'static_library'
elif target['TYPE'] == 'main':
target['EXT'] = '.nexe'
target['GYP_TYPE'] = 'executable'
else:
Error("unknown type: %s" % target['TYPE'])
target['CFLAGS'] = target.get('CXXFLAGS', [])
if not win32 and ('newlib' in desc['TOOLS'] or 'glibc' in desc['TOOLS']):
WriteNaClTargets(output, target, desc['TOOLS'])
if target['TYPE'] == 'main':
target['SODEPS'] = sofiles
target['NMFACTION'] = ['-o', '<@(_outputs)', '-L<(NMF_PATH1)',
'-L<(NMF_PATH2)', '-D', '<(OBJDUMP)',
'<@(_inputs)']
target['NMFACTION'] += soremap
if 'newlib' in desc['TOOLS']:
target['TOOLCHAIN'] = 'newlib'
output.write(NMF_TARGET % target)
if 'glibc' in desc['TOOLS']:
target['TOOLCHAIN'] = 'glibc'
output.write(NMF_TARGET % target)
if win32 or getos.GetPlatform() in desc['TOOLS']:
target['ARCH'] = 'x86_32'
target['INCLUDES'].append('../../include')
if win32:
target['HOST'] = 'win'
target['CONFIGS'] = ''
target['CFLAGS'] = []
else:
target['CONFIGS'] = ''
target['HOST'] = 'linux'
target['CFLAGS'].append('-fPIC')
if target['TYPE'] == 'main':
target['GYP_TYPE'] = 'shared_library'
if win32:
target['EXT'] = ''
else:
target['EXT'] = '.so'
output.write(HOST_EXE_TARGET % target)
else:
output.write(HOST_LIB_TARGET % target)
output.write(' ],\n}\n')
print('Writing: ' + outfile)
open(outfile, 'w').write(output.getvalue())
def main(args):
parser = argparse.ArgumentParser()
parser.add_argument('-o', help='Set output filename.', dest='output')
parser.add_argument('dsc', help='dsc to convert')
options = parser.parse_args(args)
if options.output:
outdir = os.path.dirname(options.output)
if not os.path.exists(outdir):
os.makedirs(outdir)
ProcessDSC(options.dsc, options.output)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))