configure: print warning for old compilers
authorBen Noordhuis <info@bnoordhuis.nl>
Thu, 15 Jan 2015 21:36:38 +0000 (22:36 +0100)
committerBen Noordhuis <info@bnoordhuis.nl>
Fri, 16 Jan 2015 18:02:05 +0000 (19:02 +0100)
Try to autodetect the C and C++ compiler and issue a warning when it's
too old to plausibly build io.js.  Emit warnings only because there is
much that can go wrong when trying to invoke a compiler.

PR-URL: https://github.com/iojs/io.js/pull/455
Reviewed-By: Chris Dickinson <christopher.s.dickinson@gmail.com>
Reviewed-By: Rod Vagg <rod@vagg.org>
configure

index 4b1fdb5..f3698bd 100755 (executable)
--- a/configure
+++ b/configure
@@ -10,6 +10,7 @@ import shutil
 import string
 
 CC = os.environ.get('CC', 'cc')
+CXX = os.environ.get('CXX', 'c++')
 
 root_dir = os.path.dirname(__file__)
 sys.path.insert(0, os.path.join(root_dir, 'tools', 'gyp', 'pylib'))
@@ -315,6 +316,52 @@ def pkg_config(pkg):
   return (libs, cflags)
 
 
+def try_check_compiler(cc, lang):
+  try:
+    proc = subprocess.Popen(shlex.split(cc) + ['-E', '-P', '-x', lang, '-'],
+                            stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+  except OSError:
+    return (False, False, '', '')
+
+  proc.stdin.write('__clang__ __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ '
+                   '__clang_major__ __clang_minor__ __clang_patchlevel__')
+
+  values = (proc.communicate()[0].split() + ['0'] * 7)[0:7]
+  is_clang = values[0] == '1'
+  gcc_version = '%s.%s.%s' % tuple(values[1:1+3])
+  clang_version = '%s.%s.%s' % tuple(values[4:4+3])
+
+  return (True, is_clang, clang_version, gcc_version)
+
+
+# Note: Apple clang self-reports as clang 4.2.0 and gcc 4.2.1.  It passes
+# the version check more by accident than anything else but a more rigorous
+# check involves checking the build number against a whitelist.  I'm not
+# quite prepared to go that far yet.
+def check_compiler():
+  if sys.platform == 'win32':
+    return
+
+  def warn(msg):
+    prefix = '\033[1m\033[91mWARNING\033[0m' if os.isatty(1) else 'WARNING'
+    print('%s: %s' % (prefix, msg))
+
+  ok, is_clang, clang_version, gcc_version = try_check_compiler(CXX, 'c++')
+  if not ok:
+    warn('failed to autodetect C++ compiler version (CXX=%s)' % CXX)
+  elif clang_version < '3.4.0' if is_clang else gcc_version < '4.8.0':
+    warn('C++ compiler too old, need g++ 4.8 or clang++ 3.4 (CXX=%s)' % CXX)
+
+  ok, is_clang, clang_version, gcc_version = try_check_compiler(CC, 'c')
+  if not ok:
+    warn('failed to autodetect C compiler version (CC=%s)' % CC)
+  elif not is_clang and gcc_version < '4.2.0':
+    # clang 3.2 is a little white lie because any clang version will probably
+    # do for the C bits.  However, we might as well encourage people to upgrade
+    # to a version that is not completely ancient.
+    warn('C compiler too old, need gcc 4.2 or clang 3.2 (CC=%s)' % CC)
+
+
 def cc_macros():
   """Checks predefined macros using the CC command."""
 
@@ -882,6 +929,9 @@ def configure_intl(o):
         pprint.pformat(icu_config, indent=2) + '\n')
   return  # end of configure_intl
 
+# Print a warning when the compiler is too old.
+check_compiler()
+
 # determine the "flavor" (operating system) we're building for,
 # leveraging gyp's GetFlavor function
 flavor_params = {}