| #!/usr/bin/python |
| # Copyright (c) 2014 The Native Client 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 subprocess |
| import sys |
| |
| import lib |
| |
| # Define a list of supported operating systems here. The OS is based on the |
| # "sys.platform" variable. The list and variable names need to be kept in sync, |
| # it is written so there will be a syntax error if an item was added to 1 list |
| # but not the other, although there is no check in place to be sure the order |
| # is kept. |
| OS_LIST = [ |
| 'win', |
| 'mac', |
| 'linux', |
| ] |
| |
| ( |
| OS_WIN, |
| OS_MAC, |
| OS_LINUX, |
| ) = OS_LIST |
| |
| OS_MAP = { |
| OS_WIN: ('win', 'win32', 'cygwin'), |
| OS_MAC: ('mac', 'darwin'), |
| OS_LINUX: ('linux', 'linux2', 'linux3', 'netbsd7'), |
| } |
| |
| OS_DICT = dict([(platform, os_name) |
| for os_name, platforms in OS_MAP.iteritems() |
| for platform in platforms]) |
| |
| def GetOS(platform=None): |
| if platform is None: |
| platform = sys.platform |
| |
| platform = platform.lower() |
| assert platform in OS_DICT, "Unrecognized OS platform: %s" % platform |
| return OS_DICT[platform] |
| |
| |
| def IsCygWin(platform=None): |
| if platform is None: |
| platform = sys.platform |
| |
| platform = platform.lower() |
| return platform == 'cygwin' |
| |
| # Define a list of supported architectures here. Our architecture definition |
| # comes in 2 flavors, ones that care about 32/64 bit differences, and ones that |
| # do not (a flattened list). The architecture is based on the |
| # "lib.platform.machine()" variable which can return many variations even on |
| # the same architecture (see variations of x86-32). The list and variable names |
| # needs to be kept in sync, it is written so there will be a syntax error if |
| # an item was added to 1 list but not the other, although there is no check |
| # in place to be sure the order is kept. |
| ARCH3264_LIST = [ |
| 'x86-32', |
| 'x86-32-nonsfi', |
| 'x86-64', |
| 'arm', |
| 'arm-nonsfi', |
| 'mips32', |
| ] |
| |
| ( |
| ARCH3264_X86_32, |
| ARCH3264_X86_32_NONSFI, |
| ARCH3264_X86_64, |
| ARCH3264_ARM, |
| ARCH3264_ARM_NONSFI, |
| ARCH3264_MIPS32, |
| ) = ARCH3264_LIST |
| |
| ARCH64_SET = set([ARCH3264_X86_64]) |
| |
| ARCH3264_MAP = { |
| ARCH3264_X86_32: ('x86', 'x86-32', 'x86_32', 'x8632', 'i386', |
| 'i686', 'ia32', '32'), |
| ARCH3264_X86_32_NONSFI: ('x86-32-nonsfi',), |
| ARCH3264_X86_64: ('x86-64', 'amd64', 'x86_64', 'x8664', '64'), |
| ARCH3264_ARM: ('arm', 'armv7', 'armv7l'), |
| ARCH3264_ARM_NONSFI: ('arm-nonsfi',), |
| ARCH3264_MIPS32: ('mips32', 'mips', 'mipsel'), |
| } |
| |
| ARCH3264_DICT = dict([(machine, arch_name) |
| for arch_name, machinelist in ARCH3264_MAP.iteritems() |
| for machine in machinelist]) |
| |
| ARCH_LIST = [ |
| 'x86', |
| 'arm', |
| 'mips' |
| ] |
| |
| ( |
| ARCH_X86, |
| ARCH_ARM, |
| ARCH_MIPS, |
| ) = ARCH_LIST |
| |
| # ARCH_MAP should be a strict flattening of ARCH3264_MAP, use that list to be |
| # sure both of them contain all the variations of machine names. |
| ARCH_MAP = { |
| ARCH_X86: (ARCH3264_X86_32, ARCH3264_X86_64), |
| ARCH_ARM: (ARCH3264_ARM,), |
| ARCH_MIPS: (ARCH3264_MIPS32,), |
| } |
| |
| ARCH_DICT = dict([(arch3264_name, arch_name) |
| for arch_name, arch3264_list in ARCH_MAP.iteritems() |
| for arch3264_name in arch3264_list]) |
| |
| def GetArch3264(machine=None): |
| if machine is None: |
| machine = lib.platform.machine() |
| # platform.machine is based on running kernel. It's possible to use 64-bit |
| # kernel with 32-bit userland, e.g. to give linker slightly more memory. |
| # Distinguish between different userland bitness by querying |
| # the python binary. |
| if (ARCH3264_DICT.get(machine) == ARCH3264_X86_64 and |
| lib.platform.architecture()[0] == '32bit'): |
| machine = 'ia32' |
| |
| machine = machine.lower() |
| assert machine in ARCH3264_DICT, "Unrecognized arch machine: %s" % machine |
| return ARCH3264_DICT[machine] |
| |
| def IsArch64Bit(machine=None): |
| return GetArch3264(machine) in ARCH64_SET |
| |
| def GetArch(machine=None): |
| arch3264 = GetArch3264(machine) |
| return ARCH_DICT[arch3264] |
| |
| # Here are some helper function for common checks, these should be based |
| # on the generic functions above. |
| def IsWindows(platform=None): |
| return GetOS(platform) == OS_WIN |
| |
| def IsMac(platform=None): |
| return GetOS(platform) == OS_MAC |
| |
| def IsLinux(platform=None): |
| return GetOS(platform) == OS_LINUX |
| |
| def IsLinux64(platform=None, machine=None): |
| return IsLinux(platform) and IsArch64Bit(machine) |
| |
| # If we are on cygwin convert a (possibly) Windows path to one we can use |
| # with Python APIs |
| def CygPath(path): |
| if IsCygWin(): |
| return subprocess.check_output(['cygpath', path]).strip() |
| return path |
| |
| # Some of our tools utilize a unique platform string which is used to |
| # distinguish between platform and architectures. |
| def PlatformTriple(platform=None, machine=None): |
| os = GetOS(platform) |
| arch3264 = GetArch3264(machine) |
| |
| if os == OS_WIN: |
| if IsCygWin(platform): |
| return 'i686-pc-cygwin' |
| else: |
| return 'i686-w64-mingw32' |
| elif os == OS_MAC: |
| return 'x86_64-apple-darwin' |
| elif os == OS_LINUX: |
| if arch3264 == ARCH3264_ARM: |
| # TODO(mcgrathr): How to distinguish gnueabi vs gnueabihf? |
| return 'arm-linux-gnueabihf' |
| elif arch3264 == ARCH3264_X86_32: |
| return 'i686-linux' |
| elif arch3264 == ARCH3264_X86_64: |
| return 'x86_64-linux' |
| |
| raise Exception('Unknown platform and machine') |
| |
| |
| def KillSubprocessAndChildren(proc): |
| """Kill a subprocess and all children. |
| |
| While this is trivial on Posix platforms, on Windows this requires some |
| method for walking the process tree. Relying on this functionality in |
| the taskkill.exe utility for now. |
| |
| Args: |
| proc: A subprocess.Popen process. |
| """ |
| if IsWindows(): |
| # Do subprocess call as the process may terminate before we manage |
| # to invoke taskkill. |
| subprocess.call( |
| [os.path.join(os.environ['SYSTEMROOT'], 'System32', 'taskkill.exe'), |
| '/F', '/T', '/PID', str(proc.pid)]) |
| else: |
| proc.kill() |