summaryrefslogtreecommitdiffstats
path: root/native_client_sdk
diff options
context:
space:
mode:
authorbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 23:29:06 +0000
committerbinji@chromium.org <binji@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-19 23:29:06 +0000
commit428ca1705769e1f1d48b7e67dcea82e9d4f7bf7e (patch)
tree708365d121c89ad214d481466686f6aed02844be /native_client_sdk
parent627a16dfd7118548ba7dcdb00a2ffc85f55315b5 (diff)
downloadchromium_src-428ca1705769e1f1d48b7e67dcea82e9d4f7bf7e.zip
chromium_src-428ca1705769e1f1d48b7e67dcea82e9d4f7bf7e.tar.gz
chromium_src-428ca1705769e1f1d48b7e67dcea82e9d4f7bf7e.tar.bz2
[NaCl SDK] Add tools/nacl_config.py, for getting SDK path information.
BUG=none R=sbc@chromium.org Review URL: https://codereview.chromium.org/111253005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241976 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'native_client_sdk')
-rw-r--r--native_client_sdk/src/build_tools/sdk_files.list1
-rwxr-xr-xnative_client_sdk/src/test_all.py1
-rwxr-xr-xnative_client_sdk/src/tools/nacl_config.py257
-rwxr-xr-xnative_client_sdk/src/tools/tests/nacl_config_test.py118
4 files changed, 377 insertions, 0 deletions
diff --git a/native_client_sdk/src/build_tools/sdk_files.list b/native_client_sdk/src/build_tools/sdk_files.list
index da1b7c4..56c5409 100644
--- a/native_client_sdk/src/build_tools/sdk_files.list
+++ b/native_client_sdk/src/build_tools/sdk_files.list
@@ -423,6 +423,7 @@ tools/irt_core_x86_64.nexe
[win]tools/make.exe
[linux,mac]tools/minidump_dump
[linux,mac]tools/minidump_stackwalk
+tools/nacl_config.py
tools/nacl_gcc.mk
[linux]tools/nacl_helper_bootstrap_x86_32
[linux]tools/nacl_helper_bootstrap_x86_64
diff --git a/native_client_sdk/src/test_all.py b/native_client_sdk/src/test_all.py
index a13bf80..6e433e7 100755
--- a/native_client_sdk/src/test_all.py
+++ b/native_client_sdk/src/test_all.py
@@ -19,6 +19,7 @@ TEST_MODULES = [
'fix_deps_test',
'getos_test',
'httpd_test',
+ 'nacl_config_test',
'oshelpers_test',
'parse_dsc_test',
'quote_test',
diff --git a/native_client_sdk/src/tools/nacl_config.py b/native_client_sdk/src/tools/nacl_config.py
new file mode 100755
index 0000000..1a9b469
--- /dev/null
+++ b/native_client_sdk/src/tools/nacl_config.py
@@ -0,0 +1,257 @@
+#!/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 optparse
+import os
+import posixpath
+import sys
+
+import getos
+
+
+if sys.version_info < (2, 6, 0):
+ sys.stderr.write("python 2.6 or later is required run this script\n")
+ sys.exit(1)
+
+
+VALID_ARCHES = ('arm', 'x86_32', 'x86_64', 'i686')
+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')
+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.
+PNACL_TOOLS = {
+ 'cc': 'clang',
+ 'c++': 'clang++',
+ 'gcc': 'clang',
+ 'g++': 'clang++',
+ 'ld': 'clang++'
+}
+
+NACL_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(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,
+ '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:
+ ExpectArch(arch, VALID_ARCHES)
+ if arch == 'arm':
+ Expect(toolchain == '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 == 'pnacl':
+ assert arch is None
+ 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')
+ 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':
+ tool = PNACL_TOOLS.get(tool, tool)
+ full_tool_name = 'pnacl-%s' % tool
+ else:
+ ExpectArch(arch, VALID_ARCHES)
+ tool = NACL_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 GetLDFlags():
+ return '-L%s' % GetSDKLibDir()
+
+
+def main(args):
+ usage = 'Usage: %prog [options] <command>'
+ parser = optparse.OptionParser(usage=usage, description=__doc__)
+ parser.add_option('-t', '--toolchain', help='toolchain name. This can also '
+ 'be specified with the NACL_TOOLCHAIN environment '
+ 'variable.')
+ parser.add_option('-a', '--arch', help='architecture name. This can also be '
+ 'specified with the NACL_ARCH environment variable.')
+
+ group = optparse.OptionGroup(parser, 'Commands')
+ group.add_option('--tool', help='get tool path')
+ group.add_option('--cflags',
+ help='output all preprocessor and compiler flags',
+ action='store_true')
+ group.add_option('--libs', '--ldflags', help='output all linker flags',
+ action='store_true')
+ parser.add_option_group(group)
+
+ 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.libs:
+ print GetLDFlags()
+ elif options.tool:
+ CheckValidToolchainArch(options.toolchain, options.arch, True)
+ 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)
diff --git a/native_client_sdk/src/tools/tests/nacl_config_test.py b/native_client_sdk/src/tools/tests/nacl_config_test.py
new file mode 100755
index 0000000..1d3489a
--- /dev/null
+++ b/native_client_sdk/src/tools/tests/nacl_config_test.py
@@ -0,0 +1,118 @@
+#!/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.
+
+import os
+import sys
+import unittest
+
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+TOOLS_DIR = os.path.dirname(SCRIPT_DIR)
+CHROME_SRC = os.path.dirname(os.path.dirname(os.path.dirname(TOOLS_DIR)))
+MOCK_DIR = os.path.join(CHROME_SRC, "third_party", "pymock")
+
+# For the mock library
+sys.path.append(MOCK_DIR)
+import mock
+
+# For nacl_config, the module under test
+sys.path.append(TOOLS_DIR)
+import nacl_config
+
+
+class TestNaclConfig(unittest.TestCase):
+ def setUp(self):
+ self.patches = []
+
+ get_sdk_path = self.AddAndStartPatch('getos.GetSDKPath')
+ get_sdk_path.return_value = '/sdk_root'
+
+ get_platform = self.AddAndStartPatch('getos.GetPlatform')
+ get_platform.return_value = 'mac'
+
+ def tearDown(self):
+ for patch in self.patches:
+ patch.stop()
+
+ def AddAndStartPatch(self, name):
+ patch = mock.patch(name)
+ self.patches.append(patch)
+ return patch.start()
+
+ def testCFlags(self):
+ cases = {
+ 'newlib': '-I/sdk_root/include -I/sdk_root/include/newlib',
+ 'glibc': '-I/sdk_root/include -I/sdk_root/include/glibc',
+ 'pnacl': '-I/sdk_root/include -I/sdk_root/include/pnacl',
+ 'win': '-I/sdk_root/include -I/sdk_root/include/win',
+ 'mac': '-I/sdk_root/include -I/sdk_root/include/mac',
+ 'linux': '-I/sdk_root/include -I/sdk_root/include/linux'
+ }
+ for toolchain, expected in cases.iteritems():
+ self.assertEqual(expected, nacl_config.GetCFlags(toolchain))
+ self.assertRaises(nacl_config.Error, nacl_config.GetCFlags, 'foo')
+
+ def testLDFlags(self):
+ self.assertEqual('-L/sdk_root/lib', nacl_config.GetLDFlags())
+
+ def _TestTool(self, tool, nacl_tool=None, pnacl_tool=None):
+ nacl_tool = nacl_tool or tool
+ pnacl_tool = pnacl_tool or tool
+
+ cases = {
+ ('newlib', 'x86_32'):
+ '/sdk_root/toolchain/mac_x86_newlib/bin/i686-nacl-%s' % nacl_tool,
+ ('newlib', 'x86_64'):
+ '/sdk_root/toolchain/mac_x86_newlib/bin/x86_64-nacl-%s' % nacl_tool,
+ ('newlib', 'arm'):
+ '/sdk_root/toolchain/mac_arm_newlib/bin/arm-nacl-%s' % nacl_tool,
+
+ ('glibc', 'x86_32'):
+ '/sdk_root/toolchain/mac_x86_glibc/bin/i686-nacl-%s' % nacl_tool,
+ ('glibc', 'x86_64'):
+ '/sdk_root/toolchain/mac_x86_glibc/bin/x86_64-nacl-%s' % nacl_tool,
+ ('glibc', 'arm'):
+ '/sdk_root/toolchain/mac_arm_glibc/bin/arm-nacl-%s' % nacl_tool,
+
+ 'pnacl': '/sdk_root/toolchain/mac_pnacl/bin/pnacl-%s' % pnacl_tool,
+ }
+
+ for tc_arch, expected in cases.iteritems():
+ if isinstance(tc_arch, tuple):
+ toolchain = tc_arch[0]
+ arch = tc_arch[1]
+ else:
+ toolchain = tc_arch
+ arch = None
+ self.assertEqual(expected, nacl_config.GetToolPath(toolchain, arch, tool))
+
+ for toolchain in ('host', 'mac', 'win', 'linux'):
+ self.assertRaises(nacl_config.Error,
+ nacl_config.GetToolPath, toolchain, None, tool)
+
+ def testCC(self):
+ self._TestTool('cc', 'gcc', 'clang')
+
+ def testCXX(self):
+ self._TestTool('c++', 'g++', 'clang++')
+
+ def testLD(self):
+ self._TestTool('ld', 'g++', 'clang++')
+
+ def testStandardTool(self):
+ for tool in ('nm', 'strip', 'ar', 'ranlib'):
+ self._TestTool(tool)
+
+ def testGDB(self):
+ # We always use the same gdb (it supports multiple toolchains/architectures)
+ expected = '/sdk_root/toolchain/mac_x86_newlib/bin/x86_64-nacl-gdb'
+ for toolchain in ('newlib', 'glibc', 'pnacl'):
+ for arch in ('x86_32', 'x86_64', 'arm'):
+ self.assertEqual(expected,
+ nacl_config.GetToolPath(toolchain, arch, 'gdb'))
+
+
+
+if __name__ == '__main__':
+ unittest.main()