You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.5 KiB
277 lines
7.5 KiB
9 years ago
|
#!/usr/bin/env python
|
||
|
# Copyright 2013 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.
|
||
|
|
||
|
"""A helper script to print paths of NaCl binaries, includes, libs, etc.
|
||
|
|
||
|
It is similar in behavior to pkg-config or sdl-config.
|
||
|
"""
|
||
|
|
||
|
import argparse
|
||
|
import os
|
||
|
import posixpath
|
||
|
import sys
|
||
|
|
||
|
import getos
|
||
|
|
||
|
|
||
|
if sys.version_info < (2, 7, 0):
|
||
|
sys.stderr.write("python 2.7 or later is required run this script\n")
|
||
|
sys.exit(1)
|
||
|
|
||
|
|
||
|
VALID_ARCHES = ('arm', 'x86_32', 'x86_64', 'i686')
|
||
|
VALID_PNACL_ARCHES = (None, 'pnacl')
|
||
|
ARCH_NAME = {
|
||
|
'arm': 'arm',
|
||
|
'x86_32': 'i686',
|
||
|
'i686': 'i686',
|
||
|
'x86_64': 'x86_64'
|
||
|
}
|
||
|
|
||
|
ARCH_ALT_NAME = {
|
||
|
'arm': 'arm',
|
||
|
'x86_32': 'x86_32',
|
||
|
'i686': 'x86_32',
|
||
|
'x86_64': 'x86_64'
|
||
|
}
|
||
|
|
||
|
ARCH_BASE_NAME = {
|
||
|
'arm': 'arm',
|
||
|
'x86_32': 'x86',
|
||
|
'i686': 'x86',
|
||
|
'x86_64': 'x86'
|
||
|
}
|
||
|
|
||
|
NACL_TOOLCHAINS = ('newlib', 'glibc', 'pnacl', 'bionic', 'clang-newlib')
|
||
|
HOST_TOOLCHAINS = ('linux', 'mac', 'win')
|
||
|
VALID_TOOLCHAINS = list(HOST_TOOLCHAINS) + list(NACL_TOOLCHAINS) + ['host']
|
||
|
|
||
|
# This is not an exhaustive list of tools, just the ones that need to be
|
||
|
# special-cased.
|
||
|
|
||
|
# e.g. For PNaCL cc => pnacl-clang
|
||
|
# For NaCl cc => pnacl-gcc
|
||
|
#
|
||
|
# Most tools will be passed through directly.
|
||
|
# e.g. For PNaCl foo => pnacl-foo
|
||
|
# For NaCl foo => x86_64-nacl-foo.
|
||
|
CLANG_TOOLS = {
|
||
|
'cc': 'clang',
|
||
|
'c++': 'clang++',
|
||
|
'gcc': 'clang',
|
||
|
'g++': 'clang++',
|
||
|
'ld': 'clang++'
|
||
|
}
|
||
|
|
||
|
GCC_TOOLS = {
|
||
|
'cc': 'gcc',
|
||
|
'c++': 'g++',
|
||
|
'gcc': 'gcc',
|
||
|
'g++': 'g++',
|
||
|
'ld': 'g++'
|
||
|
}
|
||
|
|
||
|
|
||
|
class Error(Exception):
|
||
|
pass
|
||
|
|
||
|
|
||
|
def Expect(condition, message):
|
||
|
if not condition:
|
||
|
raise Error(message)
|
||
|
|
||
|
|
||
|
def ExpectToolchain(toolchain, expected_toolchains):
|
||
|
Expect(toolchain in expected_toolchains,
|
||
|
'Expected toolchain to be one of [%s], not %s.' % (
|
||
|
', '.join(expected_toolchains), toolchain))
|
||
|
|
||
|
|
||
|
def ExpectArch(arch, expected_arches):
|
||
|
Expect(arch in expected_arches,
|
||
|
'Expected arch to be one of [%s], not %s.' % (
|
||
|
', '.join(map(str, expected_arches)), arch))
|
||
|
|
||
|
|
||
|
def CheckValidToolchainArch(toolchain, arch, arch_required=False):
|
||
|
if toolchain or arch or arch_required:
|
||
|
ExpectToolchain(toolchain, VALID_TOOLCHAINS)
|
||
|
|
||
|
if toolchain in HOST_TOOLCHAINS:
|
||
|
Expect(arch is None,
|
||
|
'Expected no arch for host toolchain %r. Got %r.' % (
|
||
|
toolchain, arch))
|
||
|
elif toolchain == 'pnacl':
|
||
|
Expect(arch is None or arch == 'pnacl',
|
||
|
'Expected no arch for toolchain %r. Got %r.' % (toolchain, arch))
|
||
|
elif arch_required:
|
||
|
Expect(arch is not None,
|
||
|
'Expected arch to be one of [%s] for toolchain %r.\n'
|
||
|
'Use the -a or --arch flags to specify one.\n' % (
|
||
|
', '.join(VALID_ARCHES), toolchain))
|
||
|
|
||
|
if arch:
|
||
|
if toolchain == 'pnacl':
|
||
|
ExpectArch(arch, VALID_PNACL_ARCHES)
|
||
|
else:
|
||
|
ExpectArch(arch, VALID_ARCHES)
|
||
|
|
||
|
if arch == 'arm':
|
||
|
Expect(toolchain in ['newlib', 'bionic', 'clang-newlib'],
|
||
|
'The arm arch only supports newlib.')
|
||
|
|
||
|
|
||
|
def GetArchName(arch):
|
||
|
return ARCH_NAME.get(arch)
|
||
|
|
||
|
|
||
|
def GetArchAltName(arch):
|
||
|
return ARCH_ALT_NAME.get(arch)
|
||
|
|
||
|
|
||
|
def GetArchBaseName(arch):
|
||
|
return ARCH_BASE_NAME.get(arch)
|
||
|
|
||
|
|
||
|
def CanonicalizeToolchain(toolchain):
|
||
|
if toolchain == 'host':
|
||
|
return getos.GetPlatform()
|
||
|
return toolchain
|
||
|
|
||
|
|
||
|
def GetPosixSDKPath():
|
||
|
sdk_path = getos.GetSDKPath()
|
||
|
if getos.GetPlatform() == 'win':
|
||
|
return sdk_path.replace('\\', '/')
|
||
|
else:
|
||
|
return sdk_path
|
||
|
|
||
|
|
||
|
def GetToolchainDir(toolchain, arch=None):
|
||
|
ExpectToolchain(toolchain, NACL_TOOLCHAINS)
|
||
|
root = GetPosixSDKPath()
|
||
|
platform = getos.GetPlatform()
|
||
|
if toolchain in ('pnacl', 'clang-newlib'):
|
||
|
subdir = '%s_pnacl' % platform
|
||
|
else:
|
||
|
assert arch is not None
|
||
|
subdir = '%s_%s_%s' % (platform, GetArchBaseName(arch), toolchain)
|
||
|
|
||
|
return posixpath.join(root, 'toolchain', subdir)
|
||
|
|
||
|
|
||
|
def GetToolchainArchDir(toolchain, arch):
|
||
|
ExpectToolchain(toolchain, NACL_TOOLCHAINS)
|
||
|
assert arch is not None
|
||
|
toolchain_dir = GetToolchainDir(toolchain, arch)
|
||
|
arch_dir = '%s-nacl' % GetArchName(arch)
|
||
|
return posixpath.join(toolchain_dir, arch_dir)
|
||
|
|
||
|
|
||
|
def GetToolchainBinDir(toolchain, arch=None):
|
||
|
ExpectToolchain(toolchain, NACL_TOOLCHAINS)
|
||
|
return posixpath.join(GetToolchainDir(toolchain, arch), 'bin')
|
||
|
|
||
|
|
||
|
def GetSDKIncludeDirs(toolchain):
|
||
|
root = GetPosixSDKPath()
|
||
|
base_include = posixpath.join(root, 'include')
|
||
|
if toolchain == 'clang-newlib':
|
||
|
toolchain = 'newlib'
|
||
|
return [base_include, posixpath.join(base_include, toolchain)]
|
||
|
|
||
|
|
||
|
def GetSDKLibDir():
|
||
|
return posixpath.join(GetPosixSDKPath(), 'lib')
|
||
|
|
||
|
|
||
|
# Commands
|
||
|
|
||
|
def GetToolPath(toolchain, arch, tool):
|
||
|
if tool == 'gdb':
|
||
|
# Always use the same gdb; it supports multiple toolchains/architectures.
|
||
|
# NOTE: this is always a i686 executable. i686-nacl-gdb is a symlink to
|
||
|
# x86_64-nacl-gdb.
|
||
|
return posixpath.join(GetToolchainBinDir('newlib', 'x86_64'),
|
||
|
'x86_64-nacl-gdb')
|
||
|
|
||
|
if toolchain == 'pnacl':
|
||
|
CheckValidToolchainArch(toolchain, arch)
|
||
|
tool = CLANG_TOOLS.get(tool, tool)
|
||
|
full_tool_name = 'pnacl-%s' % tool
|
||
|
else:
|
||
|
CheckValidToolchainArch(toolchain, arch, arch_required=True)
|
||
|
ExpectArch(arch, VALID_ARCHES)
|
||
|
if toolchain == 'clang-newlib':
|
||
|
tool = CLANG_TOOLS.get(tool, tool)
|
||
|
else:
|
||
|
tool = GCC_TOOLS.get(tool, tool)
|
||
|
full_tool_name = '%s-nacl-%s' % (GetArchName(arch), tool)
|
||
|
return posixpath.join(GetToolchainBinDir(toolchain, arch), full_tool_name)
|
||
|
|
||
|
|
||
|
def GetCFlags(toolchain):
|
||
|
ExpectToolchain(toolchain, VALID_TOOLCHAINS)
|
||
|
return ' '.join('-I%s' % dirname for dirname in GetSDKIncludeDirs(toolchain))
|
||
|
|
||
|
|
||
|
def GetIncludeDirs(toolchain):
|
||
|
ExpectToolchain(toolchain, VALID_TOOLCHAINS)
|
||
|
return ' '.join(GetSDKIncludeDirs(toolchain))
|
||
|
|
||
|
|
||
|
def GetLDFlags():
|
||
|
return '-L%s' % GetSDKLibDir()
|
||
|
|
||
|
|
||
|
def main(args):
|
||
|
parser = argparse.ArgumentParser(description=__doc__)
|
||
|
parser.add_argument('-t', '--toolchain', help='toolchain name. This can also '
|
||
|
'be specified with the NACL_TOOLCHAIN environment '
|
||
|
'variable.')
|
||
|
parser.add_argument('-a', '--arch', help='architecture name. This can also '
|
||
|
'be specified with the NACL_ARCH environment variable.')
|
||
|
|
||
|
group = parser.add_argument_group('Commands')
|
||
|
group.add_argument('--tool', help='get tool path')
|
||
|
group.add_argument('--cflags',
|
||
|
help='output all preprocessor and compiler flags',
|
||
|
action='store_true')
|
||
|
group.add_argument('--libs', '--ldflags', help='output all linker flags',
|
||
|
action='store_true')
|
||
|
group.add_argument('--include-dirs',
|
||
|
help='output include dirs, separated by spaces',
|
||
|
action='store_true')
|
||
|
|
||
|
options = parser.parse_args(args)
|
||
|
|
||
|
# Get toolchain/arch from environment, if not specified on commandline
|
||
|
options.toolchain = options.toolchain or os.getenv('NACL_TOOLCHAIN')
|
||
|
options.arch = options.arch or os.getenv('NACL_ARCH')
|
||
|
|
||
|
options.toolchain = CanonicalizeToolchain(options.toolchain)
|
||
|
CheckValidToolchainArch(options.toolchain, options.arch)
|
||
|
|
||
|
if options.cflags:
|
||
|
print GetCFlags(options.toolchain)
|
||
|
elif options.include_dirs:
|
||
|
print GetIncludeDirs(options.toolchain)
|
||
|
elif options.libs:
|
||
|
print GetLDFlags()
|
||
|
elif options.tool:
|
||
|
print GetToolPath(options.toolchain, options.arch, options.tool)
|
||
|
else:
|
||
|
parser.error('Expected a command. Run with --help for more information.')
|
||
|
|
||
|
return 0
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
try:
|
||
|
sys.exit(main(sys.argv[1:]))
|
||
|
except Error as e:
|
||
|
sys.stderr.write(str(e) + '\n')
|
||
|
sys.exit(1)
|