1 #!/usr/bin/env python 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 3 # Use of this source code is governed by a BSD-style license that can be 4 # found in the LICENSE file. 5 6 """Determine OS and various other system properties. 7 8 Determine the name of the platform used and other system properties such as 9 the location of Chrome. This is used, for example, to determine the correct 10 Toolchain to invoke. 11 """ 12 13 import optparse 14 import os 15 import re 16 import subprocess 17 import sys 18 19 import oshelpers 20 21 22 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) 23 CHROME_DEFAULT_PATH = { 24 'win': r'c:\Program Files (x86)\Google\Chrome\Application\chrome.exe', 25 'mac': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome', 26 'linux': '/usr/bin/google-chrome', 27 } 28 29 30 if sys.version_info < (2, 6, 0): 31 sys.stderr.write("python 2.6 or later is required run this script\n") 32 sys.exit(1) 33 34 35 class Error(Exception): 36 pass 37 38 39 def GetSDKPath(): 40 return os.getenv('NACL_SDK_ROOT', os.path.dirname(SCRIPT_DIR)) 41 42 43 def GetPlatform(): 44 if sys.platform.startswith('cygwin') or sys.platform.startswith('win'): 45 return 'win' 46 elif sys.platform.startswith('darwin'): 47 return 'mac' 48 elif sys.platform.startswith('linux'): 49 return 'linux' 50 else: 51 raise Error("Unknown platform: %s" % sys.platform) 52 53 54 def UseWin64(): 55 arch32 = os.environ.get('PROCESSOR_ARCHITECTURE') 56 arch64 = os.environ.get('PROCESSOR_ARCHITEW6432') 57 58 if arch32 == 'AMD64' or arch64 == 'AMD64': 59 return True 60 return False 61 62 63 def GetSDKVersion(): 64 root = GetSDKPath() 65 readme = os.path.join(root, "README") 66 if not os.path.exists(readme): 67 raise Error("README not found in SDK root: %s" % root) 68 69 version = None 70 revision = None 71 for line in open(readme): 72 if ':' in line: 73 name, value = line.split(':', 1) 74 if name == "Version": 75 version = value.strip() 76 if name == "Chrome Revision": 77 revision = value.strip() 78 79 if revision == None or version == None: 80 raise Error("error parsing SDK README: %s" % readme) 81 82 try: 83 revision = int(revision) 84 version = int(version) 85 except ValueError: 86 raise Error("error parsing SDK README: %s" % readme) 87 88 return (version, revision) 89 90 91 def GetSystemArch(platform): 92 if platform == 'win': 93 if UseWin64(): 94 return 'x86_64' 95 return 'x86_32' 96 97 if platform in ['mac', 'linux']: 98 try: 99 pobj = subprocess.Popen(['uname', '-m'], stdout= subprocess.PIPE) 100 arch = pobj.communicate()[0] 101 arch = arch.split()[0] 102 if arch.startswith('arm'): 103 arch = 'arm' 104 except Exception: 105 arch = None 106 return arch 107 108 109 def GetChromePath(platform): 110 # If CHROME_PATH is defined and exists, use that. 111 chrome_path = os.environ.get('CHROME_PATH') 112 if chrome_path: 113 if not os.path.exists(chrome_path): 114 raise Error('Invalid CHROME_PATH: %s' % chrome_path) 115 return os.path.realpath(chrome_path) 116 117 # Otherwise look in the PATH environment variable. 118 basename = os.path.basename(CHROME_DEFAULT_PATH[platform]) 119 chrome_path = oshelpers.FindExeInPath(basename) 120 if chrome_path: 121 return os.path.realpath(chrome_path) 122 123 # Finally, try the default paths to Chrome. 124 chrome_path = CHROME_DEFAULT_PATH[platform] 125 if os.path.exists(chrome_path): 126 return os.path.realpath(chrome_path) 127 128 raise Error('CHROME_PATH is undefined, and %s not found in PATH, nor %s.' % ( 129 basename, chrome_path)) 130 131 132 def GetNaClArch(platform): 133 if platform == 'win': 134 # On windows the nacl arch always matches to system arch 135 return GetSystemArch(platform) 136 elif platform == 'mac': 137 # On Mac the nacl arch is currently always 32-bit. 138 return 'x86_32' 139 140 # On linux the nacl arch matches to chrome arch, so we inspect the chrome 141 # binary using objdump 142 chrome_path = GetChromePath(platform) 143 144 # If CHROME_PATH is set to point to google-chrome or google-chrome 145 # was found in the PATH and we are running on UNIX then google-chrome 146 # is a bash script that points to 'chrome' in the same folder. 147 if os.path.basename(chrome_path) == 'google-chrome': 148 chrome_path = os.path.join(os.path.dirname(chrome_path), 'chrome') 149 150 try: 151 pobj = subprocess.Popen(['objdump', '-f', chrome_path], 152 stdout=subprocess.PIPE, 153 stderr=subprocess.PIPE) 154 output, stderr = pobj.communicate() 155 # error out here if objdump failed 156 if pobj.returncode: 157 raise Error(output + stderr.strip()) 158 except OSError as e: 159 # This will happen if objdump is not installed 160 raise Error("Error running objdump: %s" % e) 161 162 pattern = r'(file format) ([a-zA-Z0-9_\-]+)' 163 match = re.search(pattern, output) 164 if not match: 165 raise Error("Error running objdump on: %s" % chrome_path) 166 167 arch = match.group(2) 168 if 'arm' in arch: 169 return 'arm' 170 if '64' in arch: 171 return 'x86_64' 172 return 'x86_32' 173 174 175 def ParseVersion(version): 176 if '.' in version: 177 version = version.split('.') 178 else: 179 version = (version, '0') 180 181 try: 182 return tuple(int(x) for x in version) 183 except ValueError: 184 raise Error('error parsing SDK version: %s' % version) 185 186 187 def main(args): 188 parser = optparse.OptionParser() 189 parser.add_option('--arch', action='store_true', 190 help='Print architecture of current machine (x86_32, x86_64 or arm).') 191 parser.add_option('--chrome', action='store_true', 192 help='Print the path chrome (by first looking in $CHROME_PATH and ' 193 'then $PATH).') 194 parser.add_option('--nacl-arch', action='store_true', 195 help='Print architecture used by NaCl on the current machine.') 196 parser.add_option('--sdk-version', action='store_true', 197 help='Print major version of the NaCl SDK.') 198 parser.add_option('--sdk-revision', action='store_true', 199 help='Print revision number of the NaCl SDK.') 200 parser.add_option('--check-version', 201 help='Check that the SDK version is at least as great as the ' 202 'version passed in.') 203 204 options, _ = parser.parse_args(args) 205 206 platform = GetPlatform() 207 208 if len(args) > 1: 209 parser.error('Only one option can be specified at a time.') 210 211 if not args: 212 print platform 213 return 0 214 215 if options.arch: 216 out = GetSystemArch(platform) 217 elif options.nacl_arch: 218 out = GetNaClArch(platform) 219 elif options.chrome: 220 out = GetChromePath(platform) 221 elif options.sdk_version: 222 out = GetSDKVersion()[0] 223 elif options.sdk_revision: 224 out = GetSDKVersion()[1] 225 elif options.check_version: 226 required_version = ParseVersion(options.check_version) 227 version = GetSDKVersion() 228 if version < required_version: 229 raise Error("SDK version too old (current: %s.%s, required: %s.%s)" 230 % (version[0], version[1], 231 required_version[0], required_version[1])) 232 out = None 233 234 if out: 235 print out 236 return 0 237 238 239 if __name__ == '__main__': 240 try: 241 sys.exit(main(sys.argv[1:])) 242 except Error as e: 243 sys.stderr.write(str(e) + '\n') 244 sys.exit(1) 245