aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2017-05-19 10:43:22 -0400
committerJack Lloyd <[email protected]>2017-05-19 10:43:22 -0400
commitd0ed211552b3b4934974246af0aa7d555a0bd2ba (patch)
tree10b264087b615d5095b435cbe357ca42ae981c12
parent08ea995eb6f55ae52ec74c5c76ea8a114c72ccf8 (diff)
parent611f192f8f6bdf7e9c98865e949d798e3b131676 (diff)
Merge GH #1052 Add build-time compiler detection
-rw-r--r--.pylintrc2
-rwxr-xr-xconfigure.py121
-rw-r--r--src/lib/entropy/rdseed/info.txt6
3 files changed, 108 insertions, 21 deletions
diff --git a/.pylintrc b/.pylintrc
index e2ff76212..319d8591e 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -340,7 +340,7 @@ exclude-protected=_asdict,_fields,_replace,_source,_make
[DESIGN]
# Maximum number of arguments for function / method
-max-args=7
+max-args=8
# Argument names that match this expression will be ignored. Default to name
# with leading underscore
diff --git a/configure.py b/configure.py
index 43f5ec94d..ad055aa23 100755
--- a/configure.py
+++ b/configure.py
@@ -772,7 +772,12 @@ class ModuleInfo(InfoObject):
raise InternalError('Module %s mentions unknown OS %s' % (self.infofile, supp_os))
for supp_cc in self.cc:
if supp_cc not in cc_info:
- raise InternalError('Module %s mentions unknown compiler %s' % (self.infofile, supp_cc))
+ colon_idx = supp_cc.find(':')
+ # a versioned compiler dependency
+ if colon_idx > 0 and supp_cc[0:colon_idx] in cc_info:
+ pass
+ else:
+ raise InternalError('Module %s mentions unknown compiler %s' % (self.infofile, supp_cc))
for supp_arch in self.arch:
if supp_arch not in arch_info:
raise InternalError('Module %s mentions unknown arch %s' % (self.infofile, supp_arch))
@@ -812,15 +817,32 @@ class ModuleInfo(InfoObject):
def compatible_os(self, os_name):
return self.os == [] or os_name in self.os
- def compatible_compiler(self, cc, arch):
- if self.cc != [] and cc.basename not in self.cc:
- return False
+ def compatible_compiler(self, ccinfo, cc_version, arch):
+ # Check if this compiler supports the flags we need
+ def supported_isa_flags(ccinfo, arch):
+ for isa in self.need_isa:
+ if ccinfo.isa_flags_for(isa, arch) is None:
+ return False
+ return True
- for isa in self.need_isa:
- if cc.isa_flags_for(isa, arch) is None:
- return False
+ # Check if module gives explicit compiler dependencies
+ def supported_compiler(ccinfo, cc_version):
- return True
+ if self.cc == [] or ccinfo.basename in self.cc:
+ return True
+
+ # Maybe a versioned compiler dep
+ if cc_version != None:
+ for cc in self.cc:
+ with_version = cc.find(':')
+ if with_version > 0:
+ if cc[0:with_version] == ccinfo.basename:
+ min_cc_version = [int(v) for v in cc[with_version+1:].split('.')]
+ cur_cc_version = [int(v) for v in cc_version.split('.')]
+ # With lists of ints, this does what we want
+ return cur_cc_version >= min_cc_version
+
+ return supported_isa_flags(ccinfo, arch) and supported_compiler(ccinfo, cc_version)
def dependencies(self):
# base is an implicit dep for all submodules
@@ -1978,11 +2000,12 @@ class ModulesChooser(object):
Determine which modules to load based on options, target, etc
"""
- def __init__(self, modules, module_policy, archinfo, ccinfo, options):
+ def __init__(self, modules, module_policy, archinfo, ccinfo, cc_version, options):
self._modules = modules
self._module_policy = module_policy
self._archinfo = archinfo
self._ccinfo = ccinfo
+ self._cc_version = cc_version
self._options = options
self._maybe_dep = set()
@@ -1998,7 +2021,7 @@ class ModulesChooser(object):
if not module.compatible_os(self._options.os):
self._not_using_because['incompatible OS'].add(modname)
return False
- elif not module.compatible_compiler(self._ccinfo, self._archinfo.basename):
+ elif not module.compatible_compiler(self._ccinfo, self._cc_version, self._archinfo.basename):
self._not_using_because['incompatible compiler'].add(modname)
return False
elif not module.compatible_cpu(self._archinfo, self._options):
@@ -2515,6 +2538,67 @@ class AmalgamationGenerator(object):
return amalgamation_sources
+def detect_compiler_version(ccinfo, cc_bin, os_name):
+
+ cc_version_flag = {
+ 'msvc': ([], r'Compiler Version ([0-9]+).[0-9\.]+ for'),
+ 'gcc': (['-v'], r'gcc version ([0-9]+.[0-9])+.[0-9]+'),
+ 'clang': (['-v'], r'clang version ([0-9]+.[0-9])+.[0-9]+')
+ }
+
+ if ccinfo.basename not in cc_version_flag.keys():
+ logging.info("No compiler version detection available for %s" % (ccinfo.basename))
+ return None
+
+ (flags, version_re_str) = cc_version_flag[ccinfo.basename]
+ cc_cmd = cc_bin.split(' ') + flags
+
+ try:
+ cc_version = None
+
+ version = re.compile(version_re_str)
+ cc_output = subprocess.Popen(cc_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True).communicate()
+
+ cc_output = str(cc_output)
+
+ match = version.search(cc_output)
+
+ if match:
+ cc_version = match.group(1)
+ elif match is None and ccinfo.basename == 'clang' and os_name in ['darwin', 'ios']:
+ xcode_version_to_clang = {
+ '703': '3.8',
+ '800': '3.9',
+ '802': '4.0'
+ }
+
+ version = re.compile(r'Apple LLVM version [0-9.]+ \(clang-([0-9]{3})\.')
+ match = version.search(cc_output)
+
+ if match:
+ apple_clang_version = match.group(1)
+ if apple_clang_version in xcode_version_to_clang:
+ cc_version = xcode_version_to_clang[apple_clang_version]
+ logging.info('Mapping Apple Clang version %s to LLVM version %s' % (
+ apple_clang_version, cc_version))
+ else:
+ logging.warning('Unable to determine LLVM Clang version cooresponding to Apple Clang %s' %
+ (apple_clang_version))
+ return '3.8' # safe default
+
+ if cc_version is None:
+ logging.error("Ran '%s' to get %s compiler version, but no %s version found in %s" % (
+ ' '.join(cc_cmd), ccinfo.basename, ccinfo.basename, cc_output))
+
+ logging.info('Detected %s compiler version %s' % (ccinfo.basename, cc_version))
+ return cc_version
+ except OSError as e:
+ logging.warning('Could not execute %s for version check: %s' % (cc_cmd, e))
+ return None
+
def have_program(program):
"""
Test for the existence of a program
@@ -2721,15 +2805,14 @@ def validate_options(options, info_os, info_cc, available_module_policies):
if options.os == 'windows' and options.compiler == 'gcc':
logging.warning('Detected GCC on Windows; use --os=cygwin or --os=mingw?')
-
-
def main_action_list_available_modules(info_modules):
for modname in sorted(info_modules.keys()):
print(modname)
-def prepare_configure_build(info_modules, source_paths, options, cc, arch, osinfo, module_policy):
- loaded_module_names = ModulesChooser(info_modules, module_policy, arch, cc, options).choose()
+def prepare_configure_build(info_modules, source_paths, options,
+ cc, cc_version, arch, osinfo, module_policy):
+ loaded_module_names = ModulesChooser(info_modules, module_policy, arch, cc, cc_version, options).choose()
using_mods = [info_modules[modname] for modname in loaded_module_names]
build_config = BuildPaths(source_paths, options, using_mods)
@@ -2743,10 +2826,12 @@ def prepare_configure_build(info_modules, source_paths, options, cc, arch, osinf
return using_mods, build_config, template_vars, makefile_template
-def main_action_configure_build(info_modules, source_paths, options, cc, arch, osinfo, module_policy): # pylint: disable=too-many-locals
+def main_action_configure_build(info_modules, source_paths, options,
+ cc, cc_version, arch, osinfo, module_policy):
+ # pylint: disable=too-many-locals
using_mods, build_config, template_vars, makefile_template = prepare_configure_build(
- info_modules, source_paths, options, cc, arch, osinfo, module_policy)
+ info_modules, source_paths, options, cc, cc_version, arch, osinfo, module_policy)
# Now we start writing to disk
@@ -2879,6 +2964,8 @@ def main(argv):
osinfo = info_os[options.os]
module_policy = info_module_policies[options.module_policy] if options.module_policy else None
+ cc_version = detect_compiler_version(cc, options.compiler_binary or cc.binary_name, osinfo.basename)
+
if options.build_shared_lib and not osinfo.building_shared_supported:
logging.warning('Shared libs not supported on %s, disabling shared lib support' % (osinfo.basename))
options.build_shared_lib = False
@@ -2887,7 +2974,7 @@ def main(argv):
main_action_list_available_modules(info_modules)
return 0
else:
- main_action_configure_build(info_modules, source_paths, options, cc, arch, osinfo, module_policy)
+ main_action_configure_build(info_modules, source_paths, options, cc, cc_version, arch, osinfo, module_policy)
return 0
diff --git a/src/lib/entropy/rdseed/info.txt b/src/lib/entropy/rdseed/info.txt
index 13ea33175..8e37f808c 100644
--- a/src/lib/entropy/rdseed/info.txt
+++ b/src/lib/entropy/rdseed/info.txt
@@ -14,8 +14,8 @@ x86_64
</arch>
<cc>
-gcc
-clang
+gcc:4.8
+clang:3.2
icc
-msvc
+msvc:18
</cc>