Commits

Anonymous committed 175431f

Respect preset CC/CXX values detecting cc/c++/gcc/g++ Tools.

As the user-preset values for CC/CXX should rule always, also respect them in
exists() and generate() methods of these Tools. As a result, the value for
CCVERSION/CXXVERSION does match the CC/CXX compiler used (issue#1723).

Comments (0)

Files changed (8)

src/engine/SCons/Environment.py

                 pass
         elif SCons.Util.is_String(pathext):
             pathext = self.subst(pathext)
-        prog = self.subst(prog)
-        path = SCons.Util.WhereIs(prog, path, pathext, reject)
+        prog = SCons.Util.CLVar(self.subst(prog)) # support "program --with-args"
+        path = SCons.Util.WhereIs(prog[0], path, pathext, reject)
         if path: return path
         return None
 

src/engine/SCons/Tool/ToolTests.py

                 return self.dict.__contains__(key)
             def has_key(self, key):
                 return key in self.dict
+            def subst(self, string, *args, **kwargs):
+                return string
         env = Environment()
         env['BUILDERS'] = {}
         env['ENV'] = {}

src/engine/SCons/Tool/c++.py

 
     SCons.Tool.cc.add_common_cc_variables(env)
 
-    env['CXX']        = 'c++'
+    if 'CXX' not in env:
+        env['CXX']    = env.Detect(compilers) or compilers[0]
     env['CXXFLAGS']   = SCons.Util.CLVar('')
     env['CXXCOM']     = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
     env['SHCXX']      = '$CXX'
     env['CXXFILESUFFIX'] = '.cc'
 
 def exists(env):
-    return env.Detect(compilers)
+    return env.Detect(env.get('CXX', compilers))
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/cc.py

     if 'SHCCFLAGS' not in env:
         env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
 
+compilers = ['cc']
+
 def generate(env):
     """
     Add Builders and construction variables for C compilers to an Environment.
 
     add_common_cc_variables(env)
 
-    env['CC']        = 'cc'
+    if 'CC' not in env:
+        env['CC']    = env.Detect(compilers) or compilers[0]
     env['CFLAGS']    = SCons.Util.CLVar('')
     env['CCCOM']     = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES'
     env['SHCC']      = '$CC'
     env['CFILESUFFIX'] = '.c'
 
 def exists(env):
-    return env.Detect('cc')
+    return env.Detect(env.get('CC', compilers))
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/g++.py

 import SCons.Tool
 import SCons.Util
 
+import gcc
+
 cplusplus = __import__('c++', globals(), locals(), [])
 
 compilers = ['g++']
     """Add Builders and construction variables for g++ to an Environment."""
     static_obj, shared_obj = SCons.Tool.createObjBuilders(env)
 
+    if 'CXX' not in env:
+        env['CXX']    = env.Detect(compilers) or compilers[0]
+
     cplusplus.generate(env)
 
-    env['CXX']        = env.Detect(compilers)
-
     # platform specific settings
     if env['PLATFORM'] == 'aix':
         env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc')
     elif env['PLATFORM'] == 'sunos':
         env['SHOBJSUFFIX'] = '.pic.o'
     # determine compiler version
-    if env['CXX']:
-        #pipe = SCons.Action._subproc(env, [env['CXX'], '-dumpversion'],
-        pipe = SCons.Action._subproc(env, [env['CXX'], '--version'],
-                                     stdin = 'devnull',
-                                     stderr = 'devnull',
-                                     stdout = subprocess.PIPE)
-        if pipe.wait() != 0: return
-        # -dumpversion was added in GCC 3.0.  As long as we're supporting
-        # GCC versions older than that, we should use --version and a
-        # regular expression.
-        #line = pipe.stdout.read().strip()
-        #if line:
-        #    env['CXXVERSION'] = line
-        line = pipe.stdout.readline()
-        match = re.search(r'[0-9]+(\.[0-9]+)+', line)
-        if match:
-            env['CXXVERSION'] = match.group(0)
+    version = gcc.detect_version(env, env['CXX'])
+    if version:
+        env['CXXVERSION'] = version
 
 def exists(env):
-    return env.Detect(compilers)
+    # is executable, and is a GNU compiler (or accepts '--version' at least)
+    return gcc.detect_version(env, env.Detect(env.get('CXX', compilers)))
 
 # Local Variables:
 # tab-width:4

src/engine/SCons/Tool/gcc.py

 
 def generate(env):
     """Add Builders and construction variables for gcc to an Environment."""
+
+    if 'CC' not in env:
+        env['CC'] = env.Detect(compilers) or compilers[0]
+
     cc.generate(env)
 
-    env['CC'] = env.Detect(compilers) or 'gcc'
     if env['PLATFORM'] in ['cygwin', 'win32']:
         env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS')
     else:
         env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC')
     # determine compiler version
-    if env['CC']:
-        #pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'],
-        pipe = SCons.Action._subproc(env, [env['CC'], '--version'],
-                                     stdin = 'devnull',
-                                     stderr = 'devnull',
-                                     stdout = subprocess.PIPE)
-        if pipe.wait() != 0: return
-        # -dumpversion was added in GCC 3.0.  As long as we're supporting
-        # GCC versions older than that, we should use --version and a
-        # regular expression.
-        #line = pipe.stdout.read().strip()
-        #if line:
-        #    env['CCVERSION'] = line
-        line = pipe.stdout.readline()
-        match = re.search(r'[0-9]+(\.[0-9]+)+', line)
-        if match:
-            env['CCVERSION'] = match.group(0)
+    version = detect_version(env, env['CC'])
+    if version:
+        env['CCVERSION'] = version
 
 def exists(env):
-    return env.Detect(compilers)
+    # is executable, and is a GNU compiler (or accepts '--version' at least)
+    return detect_version(env, env.Detect(env.get('CC', compilers)))
+
+def detect_version(env, cc):
+    """Return the version of the GNU compiler, or None if it is not a GNU compiler."""
+    cc = env.subst(cc)
+    if not cc:
+        return None
+    version = None
+    #pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'],
+    pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['--version'],
+                                 stdin = 'devnull',
+                                 stderr = 'devnull',
+                                 stdout = subprocess.PIPE)
+    # -dumpversion was added in GCC 3.0.  As long as we're supporting
+    # GCC versions older than that, we should use --version and a
+    # regular expression.
+    #line = pipe.stdout.read().strip()
+    #if line:
+    #    version = line
+    line = pipe.stdout.readline()
+    match = re.search(r'[0-9]+(\.[0-9]+)+', line)
+    if match:
+        version = match.group(0)
+    # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer:
+    # So continue with reading to let the child process actually terminate.
+    while pipe.stdout.readline():
+        pass
+    ret = pipe.wait()
+    if ret != 0:
+        return None
+    return version
 
 # Local Variables:
 # tab-width:4
 test.write("wrapper.py",
 """import os
 import sys
-open('%s', 'wb').write("wrapper.py\\n")
+if '--version' not in sys.argv and '-dumpversion' not in sys.argv:
+    open('%s', 'wb').write("wrapper.py\\n")
 os.system(" ".join(sys.argv[1:]))
 """ % test.workpath('wrapper.out').replace('\\', '\\\\'))
 
 
 test.run(arguments = 'foo' + _exe)
 
-test.fail_test(os.path.exists(test.workpath('wrapper.out')))
+test.must_not_exist(test.workpath('wrapper.out'))
 
 test.up_to_date(arguments = 'foo' + _exe)
 
 test.run(arguments = 'bar' + _exe)
 
-test.fail_test(test.read('wrapper.out') != "wrapper.py\n")
+test.must_match('wrapper.out', "wrapper.py\n")
 
 test.up_to_date(arguments = 'bar' + _exe)
 
 test.write("wrapper.py",
 """import os
 import sys
-open('%s', 'wb').write("wrapper.py\\n")
+if '--version' not in sys.argv and '-dumpversion' not in sys.argv:
+    open('%s', 'wb').write("wrapper.py\\n")
 os.system(" ".join(sys.argv[1:]))
 """ % test.workpath('wrapper.out').replace('\\', '\\\\'))