Skip to content

Commit

Permalink
Detect compiler architecture at configure time
Browse files Browse the repository at this point in the history
Avoids build confusions like #1442
  • Loading branch information
randombit committed Feb 5, 2018
1 parent 0d63e98 commit 5f55f0e
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 19 deletions.
69 changes: 50 additions & 19 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -2793,49 +2793,75 @@ def validate_options(options, info_os, info_cc, available_module_policies):
if options.os == 'windows' and options.compiler != 'msvc':
logging.warning('The windows target is oriented towards MSVC; maybe you want cygwin or mingw')

def calculate_cc_min_version(options, ccinfo, source_paths):
version_patterns = {
'msvc': r'^ *MSVC ([0-9]{2})([0-9]{2})$',
'gcc': r'^ *GCC ([0-9]+) ([0-9]+)$',
'clang': r'^ *CLANG ([0-9]+) ([0-9]+)$',
'xlc': r'^ *XLC (0x[0-9a-fA-F]{2})([0-9a-fA-F]{2})$'
}

if ccinfo.basename not in version_patterns:
logging.info("No compiler version detection available for %s" % (ccinfo.basename))
return "0.0"

detect_version_source = os.path.join(source_paths.build_data_dir, "detect_version.cpp")
def run_compiler_preproc(options, ccinfo, source_file, default_return, extra_flags=None):
if extra_flags is None:
extra_flags = []

cc_bin = options.compiler_binary or ccinfo.binary_name

cmd = cc_bin.split(' ') + ccinfo.preproc_flags.split(' ') + [detect_version_source]
cmd = cc_bin.split(' ') + ccinfo.preproc_flags.split(' ') + extra_flags + [source_file]

try:
logging.debug("Running '%s'", ' '.join(cmd))
stdout, stderr = subprocess.Popen(
stdout, _ = subprocess.Popen(
cmd,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True).communicate()
cc_output = stdout + "\n" + stderr
cc_output = stdout
except OSError as e:
logging.warning('Could not execute %s for version check: %s' % (cmd, e))
return "0.0"
logging.warning('Could not execute %s: %s' % (cmd, e))
return default_return

def cleanup_output(output):
return ('\n'.join([l for l in output.splitlines() if l.startswith('#') is False])).strip()

return cleanup_output(cc_output)

def calculate_cc_min_version(options, ccinfo, source_paths):
version_patterns = {
'msvc': r'^ *MSVC ([0-9]{2})([0-9]{2})$',
'gcc': r'^ *GCC ([0-9]+) ([0-9]+)$',
'clang': r'^ *CLANG ([0-9]+) ([0-9]+)$',
'xlc': r'^ *XLC (0x[0-9a-fA-F]{2})([0-9a-fA-F]{2})$'
}

if ccinfo.basename not in version_patterns:
logging.info("No compiler version detection available for %s" % (ccinfo.basename))
return "0.0"

detect_version_source = os.path.join(source_paths.build_data_dir, "detect_version.cpp")

cc_output = run_compiler_preproc(options, ccinfo, detect_version_source, "0.0")

match = re.search(version_patterns[ccinfo.basename], cc_output, flags=re.MULTILINE)
if match is None:
logging.warning("Tried to get %s version, but output '%s' does not match expected version format" % (
ccinfo.basename, cleanup_output(cc_output)))
ccinfo.basename, cc_output))
return "0.0"

cc_version = "%d.%d" % (int(match.group(1), 0), int(match.group(2), 0))
logging.info('Auto-detected compiler version %s' % (cc_version))
return cc_version

def check_compiler_arch(options, ccinfo, archinfo, source_paths):
detect_version_source = os.path.join(source_paths.build_data_dir, 'detect_arch.cpp')

abi_flags = ccinfo.mach_abi_link_flags(options).split(' ')
cc_output = run_compiler_preproc(options, ccinfo, detect_version_source, 'UNKNOWN', abi_flags).lower()

if cc_output in ['', 'unknown']:
logging.warning('Unable to detect target architecture via compiler macro checks')
return None

if cc_output not in archinfo:
# Should not happen
logging.warning("Error detecting compiler target arch: '%s'", cc_output)
return None

logging.info('Auto-detected compiler arch %s' % (cc_output))
return cc_output

def do_io_for_build(cc, arch, osinfo, using_mods, build_paths, source_paths, template_vars, options):
# pylint: disable=too-many-locals,too-many-branches

Expand Down Expand Up @@ -3011,6 +3037,11 @@ def main(argv):
module_policy = info_module_policies[options.module_policy] if options.module_policy else None
cc_min_version = options.cc_min_version or calculate_cc_min_version(options, cc, source_paths)

cc_arch = check_compiler_arch(options, cc, info_arch, source_paths)

if cc_arch is not None and cc_arch != options.arch:
logging.error("Configured target is %s but compiler probe indicates %s", options.arch, cc_arch)

logging.info('Target is %s:%s-%s-%s' % (
options.compiler, cc_min_version, options.os, options.arch))

Expand Down
50 changes: 50 additions & 0 deletions src/build-data/detect_arch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

#if defined(__x86_64__) || defined(_M_X64)
X86_64

#elif defined(__i386__) || defined(__i386) || defined(_M_IX86)
X86_32

#elif defined(__aarch64__) || defined(__ARM_ARCH_ISA_A64)
ARM64

#elif defined(__arm__) || defined(_M_ARM) || defined(__ARM_ARCH_7A__)
ARM32

#elif defined(__powerpc64__) || defined(__ppc64__) || defined(_ARCH_PPC64)
PPC64

#elif defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC)
PPC32

#elif defined(__mips__) || defined(__mips)
MIPS32

#elif defined(__sparc__)
SPARC32

#elif defined(__alpha__)
ALPHA

#elif defined(__hppa__) || defined(__hppa)
HPPA

#elif defined(__ia64__)
IA64

#elif defined(__m68k__)
M68K

#elif defined(__sh__)
SH

#elif defined(__s390x__)
S390X

#elif defined(__s390__)
S390

#else
UNKNOWN

#endif

0 comments on commit 5f55f0e

Please sign in to comment.