1342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch#!/usr/bin/env python 2342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch# Copyright (c) 2012 The Chromium Authors. All rights reserved. 3342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch# Use of this source code is governed by a BSD-style license that can be 4342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch# found in the LICENSE file. 5342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 6342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch"""Compiler version checking tool for gcc 7342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 8342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochPrint gcc version as XY if you are running gcc X.Y.*. 9342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen MurdochThis is used to tweak build flags for gcc 4.4. 10342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch""" 11342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 12342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochimport os 13342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochimport re 14342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochimport subprocess 15342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochimport sys 16342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 17342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 18342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochcompiler_version_cache = {} # Map from (compiler, tool) -> version. 19342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 20342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 21342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef Usage(program_name): 22342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print '%s MODE TOOL' % os.path.basename(program_name) 23342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print 'MODE: host or target.' 24342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print 'TOOL: assembler or compiler or linker.' 25342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return 1 26342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 27342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 28342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef ParseArgs(args): 29342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if len(args) != 2: 30342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise Exception('Invalid number of arguments') 31342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch mode = args[0] 32342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch tool = args[1] 33342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if mode not in ('host', 'target'): 34342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise Exception('Invalid mode: %s' % mode) 35342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if tool not in ('assembler',): 36342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise Exception('Invalid tool: %s' % tool) 37342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return mode, tool 38342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 39342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 40342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef GetEnvironFallback(var_list, default): 41342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch """Look up an environment variable from a possible list of variable names.""" 42342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch for var in var_list: 43342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if var in os.environ: 44342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return os.environ[var] 45342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return default 46342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 47342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 48342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef GetVersion(compiler, tool): 49342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch tool_output = tool_error = None 50342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch cache_key = (compiler, tool) 51342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch cached_version = compiler_version_cache.get(cache_key) 52342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if cached_version: 53342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return cached_version 54342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch try: 55342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Note that compiler could be something tricky like "distcc g++". 56342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if tool == "assembler": 57342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch compiler = compiler + " -Xassembler --version -x assembler -c /dev/null" 58342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Unmodified: GNU assembler (GNU Binutils) 2.24 59342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Ubuntu: GNU assembler (GNU Binutils for Ubuntu) 2.22 60342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Fedora: GNU assembler version 2.23.2 61342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch version_re = re.compile(r"^GNU [^ ]+ .* (\d+).(\d+).*?$", re.M) 62342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch else: 63342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise Exception("Unknown tool %s" % tool) 64342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 65342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Force the locale to C otherwise the version string could be localized 66342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # making regex matching fail. 67342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch env = os.environ.copy() 68342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch env["LC_ALL"] = "C" 69342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch pipe = subprocess.Popen(compiler, shell=True, env=env, 70342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch stdout=subprocess.PIPE, stderr=subprocess.PIPE) 71342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch tool_output, tool_error = pipe.communicate() 72342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if pipe.returncode: 73342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise subprocess.CalledProcessError(pipe.returncode, compiler) 74342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 75342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch parsed_output = version_re.match(tool_output) 76342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch result = parsed_output.group(1) + parsed_output.group(2) 77342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch compiler_version_cache[cache_key] = result 78342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return result 79342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch except Exception, e: 80342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if tool_error: 81342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch sys.stderr.write(tool_error) 82342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print >> sys.stderr, "compiler_version.py failed to execute:", compiler 83342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print >> sys.stderr, e 84342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return "" 85342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 86342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 87342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef main(args): 88342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch try: 89342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch (mode, tool) = ParseArgs(args[1:]) 90342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch except Exception, e: 91342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch sys.stderr.write(e.message + '\n\n') 92342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return Usage(args[0]) 93342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 94342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch ret_code, result = ExtractVersion(mode, tool) 95342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if ret_code == 0: 96342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch print result 97342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return ret_code 98342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 99342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 100342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef DoMain(args): 101342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch """Hook to be called from gyp without starting a separate python 102342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch interpreter.""" 103342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch (mode, tool) = ParseArgs(args) 104342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch ret_code, result = ExtractVersion(mode, tool) 105342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if ret_code == 0: 106342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return result 107342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch raise Exception("Failed to extract compiler version for args: %s" % args) 108342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 109342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 110342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochdef ExtractVersion(mode, tool): 111342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # Check if various CXX environment variables exist and use them if they 112342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # exist. The preferences and fallback order is a close approximation of 113342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # GenerateOutputForConfig() in GYP's ninja generator. 114342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch # The main difference being not supporting GYP's make_global_settings. 115342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch environments = ['CXX_target', 'CXX'] 116342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if mode == 'host': 117342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch environments = ['CXX_host'] + environments; 118342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch compiler = GetEnvironFallback(environments, 'c++') 119342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 120342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if compiler: 121342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch compiler_version = GetVersion(compiler, tool) 122342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch if compiler_version != "": 123342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return (0, compiler_version) 124342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch return (1, None) 125342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 126342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch 127342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdochif __name__ == "__main__": 128342c50ce1624b485728b9a4fc41d8bbf37eb46cfBen Murdoch sys.exit(main(sys.argv)) 129