| #!/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:])) |