[llvm-commits] [zorg] r101733 - in /zorg/trunk/lnt/lnt/testing/util: ./ __init__.py commands.py compilers.py
Daniel Dunbar
daniel at zuster.org
Sun Apr 18 12:18:25 PDT 2010
Author: ddunbar
Date: Sun Apr 18 14:18:25 2010
New Revision: 101733
URL: http://llvm.org/viewvc/llvm-project?rev=101733&view=rev
Log:
LNT: Add a new testing.util module, which contains various utilities for writing
test data generators.
- testing.util.compilers has a utility for interrogating a compiler to find its
version, build information, etc. It is fairly Apple specific at the moment
but feel free to generalize.
- testing.util.commands has a few utilities for doing shell scripty tasks.
Neither of these have a particularly well thought out failure model yet.
Added:
zorg/trunk/lnt/lnt/testing/util/
zorg/trunk/lnt/lnt/testing/util/__init__.py
zorg/trunk/lnt/lnt/testing/util/commands.py
zorg/trunk/lnt/lnt/testing/util/compilers.py
Added: zorg/trunk/lnt/lnt/testing/util/__init__.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/lnt/lnt/testing/util/__init__.py?rev=101733&view=auto
==============================================================================
--- zorg/trunk/lnt/lnt/testing/util/__init__.py (added)
+++ zorg/trunk/lnt/lnt/testing/util/__init__.py Sun Apr 18 14:18:25 2010
@@ -0,0 +1,5 @@
+"""
+Miscellaneous utilities for generating test data.
+"""
+
+__all__ = []
Added: zorg/trunk/lnt/lnt/testing/util/commands.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/lnt/lnt/testing/util/commands.py?rev=101733&view=auto
==============================================================================
--- zorg/trunk/lnt/lnt/testing/util/commands.py (added)
+++ zorg/trunk/lnt/lnt/testing/util/commands.py Sun Apr 18 14:18:25 2010
@@ -0,0 +1,69 @@
+"""
+Miscellaneous utilities for running "scripts".
+"""
+
+import inspect
+import os
+import sys
+
+# FIXME: Find a better place for this code.
+
+def _write_message(kind, message):
+ # Get the file/line where this message was generated.
+ f = inspect.currentframe()
+ # Step out of _write_message, and then out of wrapper.
+ f = f.f_back.f_back
+ file,line,_,_,_ = inspect.getframeinfo(f)
+ location = '%s:%d' % (os.path.basename(file), line)
+
+ print >>sys.stderr, '%s: %s: %s' % (location, kind, message)
+
+note = lambda message: _write_message('note', message)
+warning = lambda message: _write_message('warning', message)
+error = lambda message: _write_message('error', message)
+fatal = lambda message: (_write_message('fatal error', message), sys.exit(1))
+
+def rm_f(path):
+ try:
+ os.remove(path)
+ except OSError,e:
+ if e.errno != errno.ENOENT:
+ raise
+
+def capture(args, include_stderr=False):
+ import subprocess
+ """capture(command) - Run the given command (or argv list) in a shell and
+ return the standard output."""
+ stderr = subprocess.PIPE
+ if include_stderr:
+ stderr = subprocess.STDOUT
+ p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=stderr)
+ out,_ = p.communicate()
+ return out
+
+def which(command, paths = None):
+ """which(command, [paths]) - Look up the given command in the paths string
+ (or the PATH environment variable, if unspecified)."""
+
+ if paths is None:
+ paths = os.environ.get('PATH','')
+
+ # Check for absolute match first.
+ if os.path.exists(command):
+ return command
+
+ # Would be nice if Python had a lib function for this.
+ if not paths:
+ paths = os.defpath
+
+ # Get suffixes to search.
+ pathext = os.environ.get('PATHEXT', '').split(os.pathsep)
+
+ # Search the paths...
+ for path in paths.split(os.pathsep):
+ for ext in pathext:
+ p = os.path.join(path, command + ext)
+ if os.path.exists(p):
+ return p
+
+ return None
Added: zorg/trunk/lnt/lnt/testing/util/compilers.py
URL: http://llvm.org/viewvc/llvm-project/zorg/trunk/lnt/lnt/testing/util/compilers.py?rev=101733&view=auto
==============================================================================
--- zorg/trunk/lnt/lnt/testing/util/compilers.py (added)
+++ zorg/trunk/lnt/lnt/testing/util/compilers.py Sun Apr 18 14:18:25 2010
@@ -0,0 +1,115 @@
+import hashlib
+import re
+
+from commands import error
+from commands import capture
+
+def get_cc_info(path, cc_flags=[]):
+ """get_cc_info(path) -> { ... }
+
+ Extract various information on the given compiler and return a dictionary of
+ the results."""
+
+ cc = path
+
+ # Interrogate the compiler.
+ cc_version = capture([cc, '-v', '-E'] + cc_flags +
+ ['-x', 'c', '/dev/null', '-###'],
+ include_stderr=True).strip()
+ version_ln = None
+ cc_target = None
+ cc1_binary = None
+ for ln in cc_version.split('\n'):
+ if ' version ' in ln:
+ version_ln = ln
+ elif ln.startswith('Target:'):
+ cc_target = ln.split(':',1)[1].strip()
+ elif 'cc1' in ln or 'clang-cc' in ln:
+ m = re.match(r' "([^"]*)".*"-E".*', ln)
+ if not m:
+ error("unable to determine cc1 binary: %r: %r" % (cc, ln))
+ cc1_binary, = m.groups()
+ if version_ln is None:
+ error("unable to find compiler version: %r: %r" % (cc, cc_version))
+ if cc_target is None:
+ error("unable to find compiler target: %r: %r" % (cc, cc_version))
+ if cc1_binary is None:
+ error("unable to find compiler cc1 binary: %r: %r" % (cc, cc_version))
+ m = re.match(r'(.*) version ([^ ]*) (\([^(]*\))(.*)', version_ln)
+ if not m:
+ error("unable to determine compiler version: %r: %r" % (cc, version_ln))
+ cc_name,cc_version_num,cc_build_string,cc_extra = m.groups()
+
+ # Compute normalized compiler name and type.
+ cc_build = None
+ llvm_capable = False
+ if (cc_name, cc_extra) == ('gcc',''):
+ cc_norm_name = 'gcc'
+ m = re.match(r'\(Apple Inc. build [0-9]*\)', cc_build_string)
+ if m:
+ cc_build = 'PROD'
+ else:
+ error('unable to determine gcc build version: %r' % cc_build_string)
+ elif (cc_name, cc_extra) == ('clang',''):
+ llvm_capable = True
+ cc_norm_name = 'clang'
+ m = re.search('clang-([0-9]*)', cc_build_string)
+ if m:
+ cc_build = 'PROD'
+ else:
+ # FIXME: Make this stricter.
+ # FIXME: Detect source versions.
+ cc_build = 'DEV'
+ elif (cc_name, cc_extra) == ('Apple clang',''):
+ llvm_capable = True
+ cc_norm_name = 'apple_clang'
+ m = re.search('clang-([0-9]*)', cc_build_string)
+ if m:
+ cc_build = 'PROD'
+ else:
+ # FIXME: Make this stricter.
+ # FIXME: Detect source versions.
+ cc_build = 'DEV'
+ elif cc_name == 'gcc' and 'LLVM build' in cc_extra:
+ llvm_capable = True
+ cc_norm_name = 'llvm-gcc'
+ m = re.match(r' \(LLVM build( [0-9]+)?\)', cc_extra)
+ if m:
+ llvm_build, = m.groups()
+ cc_build = 'PROD'
+ else:
+ cc_build = 'DEV'
+ else:
+ error("unable to determine compiler name: %r" % ((cc_name,
+ cc_build_string),))
+
+ if cc_build is None:
+ error("unable to determine compiler build: %r" % cc_version)
+
+ # If LLVM capable, fetch the llvm target instead.
+ if llvm_capable:
+ target_cc_ll = capture([cc, '-S', '-flto', '-o', '-'] + cc_flags +
+ ['-x', 'c', '/dev/null'],
+ include_stderr=True).strip()
+ m = re.search('target triple = "(.*)"', target_cc_ll)
+ if not m:
+ error("unable to determine LLVM compiler target: %r: %r" %
+ (ll_cmd, target_cc_ll))
+ cc_target, = m.groups()
+
+ cc_exec_hash = hashlib.sha1()
+ cc_exec_hash.update(open(cc,'rb').read())
+
+ cc1_exec_hash = hashlib.sha1()
+ cc1_exec_hash.update(open(cc1_binary,'rb').read())
+
+ return { 'cc_build' : cc_build,
+ 'cc_name' : cc_norm_name,
+ 'cc_version_number' : cc_version_num,
+ 'cc_target' : cc_target,
+ 'cc_version' :cc_version,
+ 'cc_exec_hash' : cc_exec_hash.hexdigest(),
+ 'cc1_exec_hash' : cc1_exec_hash.hexdigest(),
+ }
+
+__all__ = [get_cc_info]
More information about the llvm-commits
mailing list