[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