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.
6 """Determine OS and various other system properties.
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
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',
30 if sys.version_info < (2, 6, 0):
31 sys.stderr.write("python 2.6 or later is required run this script\n")
35 class Error(Exception):
40 return os.getenv('NACL_SDK_ROOT', os.path.dirname(SCRIPT_DIR))
44 if sys.platform.startswith('cygwin') or sys.platform.startswith('win'):
46 elif sys.platform.startswith('darwin'):
48 elif sys.platform.startswith('linux'):
51 raise Error("Unknown platform: %s" % sys.platform)
55 arch32 = os.environ.get('PROCESSOR_ARCHITECTURE')
56 arch64 = os.environ.get('PROCESSOR_ARCHITEW6432')
58 if arch32 == 'AMD64' or arch64 == 'AMD64':
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)
71 commit_position = None
72 for line in open(readme):
74 name, value = line.split(':', 1)
76 version = value.strip()
77 if name == "Chrome Revision":
78 revision = value.strip()
79 if name == "Chrome Commit Position":
80 commit_position = value.strip()
82 if revision is None or version is None or commit_position is None:
83 raise Error("error parsing SDK README: %s" % readme)
86 version = int(version)
87 revision = int(revision)
89 raise Error("error parsing SDK README: %s" % readme)
91 return (version, revision, commit_position)
94 def GetSystemArch(platform):
100 if platform in ['mac', 'linux']:
102 pobj = subprocess.Popen(['uname', '-m'], stdout= subprocess.PIPE)
103 arch = pobj.communicate()[0]
104 arch = arch.split()[0]
105 if arch.startswith('arm'):
112 def GetChromePath(platform):
113 # If CHROME_PATH is defined and exists, use that.
114 chrome_path = os.environ.get('CHROME_PATH')
116 if not os.path.exists(chrome_path):
117 raise Error('Invalid CHROME_PATH: %s' % chrome_path)
118 return os.path.realpath(chrome_path)
120 # Otherwise look in the PATH environment variable.
121 basename = os.path.basename(CHROME_DEFAULT_PATH[platform])
122 chrome_path = oshelpers.FindExeInPath(basename)
124 return os.path.realpath(chrome_path)
126 # Finally, try the default paths to Chrome.
127 chrome_path = CHROME_DEFAULT_PATH[platform]
128 if os.path.exists(chrome_path):
129 return os.path.realpath(chrome_path)
131 raise Error('CHROME_PATH is undefined, and %s not found in PATH, nor %s.' % (
132 basename, chrome_path))
135 def GetNaClArch(platform):
136 if platform == 'win':
137 # On windows the nacl arch always matches to system arch
138 return GetSystemArch(platform)
139 elif platform == 'mac':
140 # On Mac the nacl arch is currently always 32-bit.
143 # On linux the nacl arch matches to chrome arch, so we inspect the chrome
144 # binary using objdump
145 chrome_path = GetChromePath(platform)
147 # If CHROME_PATH is set to point to google-chrome or google-chrome
148 # was found in the PATH and we are running on UNIX then google-chrome
149 # is a bash script that points to 'chrome' in the same folder.
151 # When running beta or dev branch, the name is google-chrome-{beta,dev}.
152 if os.path.basename(chrome_path).startswith('google-chrome'):
153 chrome_path = os.path.join(os.path.dirname(chrome_path), 'chrome')
155 if not os.path.exists(chrome_path):
156 raise Error("File %s does not exist." % chrome_path)
158 if not os.access(chrome_path, os.X_OK):
159 raise Error("File %s is not executable" % chrome_path)
162 pobj = subprocess.Popen(['objdump', '-f', chrome_path],
163 stdout=subprocess.PIPE,
164 stderr=subprocess.PIPE)
165 output, stderr = pobj.communicate()
166 # error out here if objdump failed
168 raise Error(output + stderr.strip())
170 # This will happen if objdump is not installed
171 raise Error("Error running objdump: %s" % e)
173 pattern = r'(file format) ([a-zA-Z0-9_\-]+)'
174 match = re.search(pattern, output)
176 raise Error("Error running objdump on: %s" % chrome_path)
178 arch = match.group(2)
186 def ParseVersion(version):
187 """Parses a version number of the form '<major>.<position>'.
189 <position> is the Cr-Commit-Position number.
192 version = version.split('.')
194 version = (version, '0')
197 return tuple(int(x) for x in version)
199 raise Error('error parsing SDK version: %s' % version)
202 def CheckVersion(required_version):
203 """Determines whether the current SDK version meets the required version.
206 required_version: (major, position) pair, where position is the
207 Cr-Commit-Position number.
210 Error: The SDK version is older than required_version.
212 version = GetSDKVersion()[:2]
213 if version < required_version:
214 raise Error("SDK version too old (current: %d.%d, required: %d.%d)"
215 % (version[0], version[1], required_version[0], required_version[1]))
219 parser = optparse.OptionParser()
220 parser.add_option('--arch', action='store_true',
221 help='Print architecture of current machine (x86_32, x86_64 or arm).')
222 parser.add_option('--chrome', action='store_true',
223 help='Print the path chrome (by first looking in $CHROME_PATH and '
225 parser.add_option('--nacl-arch', action='store_true',
226 help='Print architecture used by NaCl on the current machine.')
227 parser.add_option('--sdk-version', action='store_true',
228 help='Print major version of the NaCl SDK.')
229 parser.add_option('--sdk-revision', action='store_true',
230 help='Print revision number of the NaCl SDK.')
231 parser.add_option('--sdk-commit-position', action='store_true',
232 help='Print commit position of the NaCl SDK.')
233 parser.add_option('--check-version',
234 metavar='MAJOR.POSITION',
235 help='Check that the SDK version is at least as great as the '
236 'version passed in. MAJOR is the major version number and POSITION '
237 'is the Cr-Commit-Position number.')
239 options, _ = parser.parse_args(args)
241 platform = GetPlatform()
244 parser.error('Only one option can be specified at a time.')
251 out = GetSystemArch(platform)
252 elif options.nacl_arch:
253 out = GetNaClArch(platform)
255 out = GetChromePath(platform)
256 elif options.sdk_version:
257 out = GetSDKVersion()[0]
258 elif options.sdk_revision:
259 out = GetSDKVersion()[1]
260 elif options.sdk_commit_position:
261 out = GetSDKVersion()[2]
262 elif options.check_version:
263 required_version = ParseVersion(options.check_version)
264 CheckVersion(required_version)
272 if __name__ == '__main__':
274 sys.exit(main(sys.argv[1:]))
276 sys.stderr.write(str(e) + '\n')