160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson#! /usr/bin/env python 260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson# encoding: utf-8 360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport argparse 560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport errno 660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport logging 760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport os 860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport platform 960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport re 1060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport sys 1160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport subprocess 1260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonimport tempfile 1360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 1460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksontry: 1560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import winreg 1660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonexcept ImportError: 1760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import _winreg as winreg 1860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksontry: 1960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import urllib.request as request 2060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonexcept ImportError: 2160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import urllib as request 2260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksontry: 2360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import urllib.parse as parse 2460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonexcept ImportError: 2560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson import urlparse as parse 2660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 2760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonclass EmptyLogger(object): 2860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 2960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Provides an implementation that performs no logging 3060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 3160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def debug(self, *k, **kw): 3260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 3360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def info(self, *k, **kw): 3460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 3560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def warn(self, *k, **kw): 3660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 3760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def error(self, *k, **kw): 3860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 3960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def critical(self, *k, **kw): 4060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 4160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson def setLevel(self, *k, **kw): 4260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 4360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 4460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonurls = ( 4560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'http://downloads.sourceforge.net/project/mingw-w64/Toolchains%20' 4660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'targetting%20Win32/Personal%20Builds/mingw-builds/installer/' 4760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'repository.txt', 4860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'http://downloads.sourceforge.net/project/mingwbuilds/host-windows/' 4960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'repository.txt' 5060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson) 5160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson''' 5260910b3de7aa85ff28da14f34c7084711f99ac74Matt ClarksonA list of mingw-build repositories 5360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson''' 5460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 5560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef repository(urls = urls, log = EmptyLogger()): 5660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 5760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Downloads and parse mingw-build repository files and parses them 5860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 5960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.info('getting mingw-builds repository') 6060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson versions = {} 6160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson re_sourceforge = re.compile(r'http://sourceforge.net/projects/([^/]+)/files') 6260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson re_sub = r'http://downloads.sourceforge.net/project/\1' 6360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson for url in urls: 6460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - requesting: %s', url) 6560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson socket = request.urlopen(url) 6660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson repo = socket.read() 6760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not isinstance(repo, str): 6860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson repo = repo.decode(); 6960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson socket.close() 7060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson for entry in repo.split('\n')[:-1]: 7160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson value = entry.split('|') 7260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = tuple([int(n) for n in value[0].strip().split('.')]) 7360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = versions.setdefault(version, {}) 7460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = value[1].strip() 7560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if arch == 'x32': 7660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = 'i686' 7760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson elif arch == 'x64': 7860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = 'x86_64' 7960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = version.setdefault(arch, {}) 8060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson threading = arch.setdefault(value[2].strip(), {}) 8160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = threading.setdefault(value[3].strip(), {}) 8260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson revision = exceptions.setdefault(int(value[4].strip()[3:]), 8360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson re_sourceforge.sub(re_sub, value[5].strip())) 8460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return versions 8560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 8660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef find_in_path(file, path=None): 8760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 8860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Attempts to find an executable in the path 8960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 9060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if platform.system() == 'Windows': 9160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson file += '.exe' 9260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if path is None: 9360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson path = os.environ.get('PATH', '') 9460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if type(path) is type(''): 9560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson path = path.split(os.pathsep) 9660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return list(filter(os.path.exists, 9760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson map(lambda dir, file=file: os.path.join(dir, file), path))) 9860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 9960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef find_7zip(log = EmptyLogger()): 10060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 10160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Attempts to find 7zip for unpacking the mingw-build archives 10260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 10360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.info('finding 7zip') 10460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson path = find_in_path('7z') 10560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not path: 10660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r'SOFTWARE\7-Zip') 10760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson path, _ = winreg.QueryValueEx(key, 'Path') 10860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson path = [os.path.join(path, '7z.exe')] 10960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug('found \'%s\'', path[0]) 11060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return path[0] 11160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 11260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonfind_7zip() 11360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 11460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef unpack(archive, location, log = EmptyLogger()): 11560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 11660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Unpacks a mingw-builds archive 11760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 11860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sevenzip = find_7zip(log) 11960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.info('unpacking %s', os.path.basename(archive)) 12060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson cmd = [sevenzip, 'x', archive, '-o' + location, '-y'] 12160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - %r', cmd) 12260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson with open(os.devnull, 'w') as devnull: 12360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson subprocess.check_call(cmd, stdout = devnull) 12460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 12560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef download(url, location, log = EmptyLogger()): 12660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 12760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Downloads and unpacks a mingw-builds archive 12860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 12960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.info('downloading MinGW') 13060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - url: %s', url) 13160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - location: %s', location) 13260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 13360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson re_content = re.compile(r'attachment;[ \t]*filename=(")?([^"]*)(")?[\r\n]*') 13460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 13560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson stream = request.urlopen(url) 13660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson try: 13760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson content = stream.getheader('Content-Disposition') or '' 13860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except AttributeError: 13960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson content = stream.headers.getheader('Content-Disposition') or '' 14060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson matches = re_content.match(content) 14160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if matches: 14260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson filename = matches.group(2) 14360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson else: 14460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parsed = parse.urlparse(stream.geturl()) 14560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson filename = os.path.basename(parsed.path) 14660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 14760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson try: 14860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson os.makedirs(location) 14960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except OSError as e: 15060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if e.errno == errno.EEXIST and os.path.isdir(location): 15160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson pass 15260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson else: 15360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise 15460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 15560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson archive = os.path.join(location, filename) 15660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson with open(archive, 'wb') as out: 15760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson while True: 15860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson buf = stream.read(1024) 15960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not buf: 16060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson break 16160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson out.write(buf) 16260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson unpack(archive, location, log = log) 16360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson os.remove(archive) 16460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 16560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson possible = os.path.join(location, 'mingw64') 16660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not os.path.exists(possible): 16760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson possible = os.path.join(location, 'mingw32') 16860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not os.path.exists(possible): 16960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise ValueError('Failed to find unpacked MinGW: ' + possible) 17060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return possible 17160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 17260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef root(location = None, arch = None, version = None, threading = None, 17360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = None, revision = None, log = EmptyLogger()): 17460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 17560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Returns the root folder of a specific version of the mingw-builds variant 17660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson of gcc. Will download the compiler if needed 17760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 17860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 17960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Get the repository if we don't have all the information 18060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not (arch and version and threading and exceptions and revision): 18160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson versions = repository(log = log) 18260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 18360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Determine some defaults 18460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = version or max(versions.keys()) 18560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not arch: 18660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = platform.machine().lower() 18760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if arch == 'x86': 18860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = 'i686' 18960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson elif arch == 'amd64': 19060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = 'x86_64' 19160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not threading: 19260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson keys = versions[version][arch].keys() 19360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if 'posix' in keys: 19460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson threading = 'posix' 19560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson elif 'win32' in keys: 19660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson threading = 'win32' 19760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson else: 19860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson threading = keys[0] 19960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not exceptions: 20060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson keys = versions[version][arch][threading].keys() 20160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if 'seh' in keys: 20260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = 'seh' 20360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson elif 'sjlj' in keys: 20460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = 'sjlj' 20560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson else: 20660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = keys[0] 20760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if revision == None: 20860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson revision = max(versions[version][arch][threading][exceptions].keys()) 20960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not location: 21060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson location = os.path.join(tempfile.gettempdir(), 'mingw-builds') 21160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 21260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Get the download url 21360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson url = versions[version][arch][threading][exceptions][revision] 21460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 21560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Tell the user whatzzup 21660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.info('finding MinGW %s', '.'.join(str(v) for v in version)) 21760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - arch: %s', arch) 21860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - threading: %s', threading) 21960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - exceptions: %s', exceptions) 22060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - revision: %s', revision) 22160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log.debug(' - url: %s', url) 22260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 22360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Store each specific revision differently 22460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson slug = '{version}-{arch}-{threading}-{exceptions}-rev{revision}' 22560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson slug = slug.format( 22660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = '.'.join(str(v) for v in version), 22760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson arch = arch, 22860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson threading = threading, 22960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = exceptions, 23060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson revision = revision 23160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ) 23260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if arch == 'x86_64': 23360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson root_dir = os.path.join(location, slug, 'mingw64') 23460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson elif arch == 'i686': 23560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson root_dir = os.path.join(location, slug, 'mingw32') 23660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson else: 23760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise ValueError('Unknown MinGW arch: ' + arch) 23860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 23960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Download if needed 24060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if not os.path.exists(root_dir): 24160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson downloaded = download(url, os.path.join(location, slug), log = log) 24260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if downloaded != root_dir: 24360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise ValueError('The location of mingw did not match\n%s\n%s' 24460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson % (downloaded, root_dir)) 24560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 24660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return root_dir 24760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 24860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef str2ver(string): 24960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 25060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Converts a version string into a tuple 25160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 25260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson try: 25360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = tuple(int(v) for v in string.split('.')) 25460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if len(version) is not 3: 25560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise ValueError() 25660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except ValueError: 25760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson raise argparse.ArgumentTypeError( 25860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 'please provide a three digit version string') 25960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson return version 26060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 26160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksondef main(): 26260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 26360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson Invoked when the script is run directly by the python interpreter 26460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ''' 26560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser = argparse.ArgumentParser( 26660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson description = 'Downloads a specific version of MinGW', 26760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson formatter_class = argparse.ArgumentDefaultsHelpFormatter 26860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson ) 26960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--location', 27060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the location to download the compiler to', 27160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson default = os.path.join(tempfile.gettempdir(), 'mingw-builds')) 27260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--arch', required = True, choices = ['i686', 'x86_64'], 27360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the target MinGW architecture string') 27460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--version', type = str2ver, 27560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the version of GCC to download') 27660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--threading', choices = ['posix', 'win32'], 27760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the threading type of the compiler') 27860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--exceptions', choices = ['sjlj', 'seh', 'dwarf'], 27960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the method to throw exceptions') 28060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson parser.add_argument('--revision', type=int, 28160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help = 'the revision of the MinGW release') 28260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson group = parser.add_mutually_exclusive_group() 28360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson group.add_argument('-v', '--verbose', action='store_true', 28460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help='increase the script output verbosity') 28560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson group.add_argument('-q', '--quiet', action='store_true', 28660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson help='only print errors and warning') 28760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson args = parser.parse_args() 28860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 28960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Create the logger 29060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson logger = logging.getLogger('mingw') 29160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson handler = logging.StreamHandler() 29260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson formatter = logging.Formatter('%(message)s') 29360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson handler.setFormatter(formatter) 29460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson logger.addHandler(handler) 29560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson logger.setLevel(logging.INFO) 29660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if args.quiet: 29760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson logger.setLevel(logging.WARN) 29860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson if args.verbose: 29960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson logger.setLevel(logging.DEBUG) 30060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 30160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson # Get MinGW 30260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson root_dir = root(location = args.location, arch = args.arch, 30360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson version = args.version, threading = args.threading, 30460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson exceptions = args.exceptions, revision = args.revision, 30560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson log = logger) 30660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 30760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.stdout.write('%s\n' % os.path.join(root_dir, 'bin')) 30860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson 30960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarksonif __name__ == '__main__': 31060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson try: 31160910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson main() 31260910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except IOError as e: 31360910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.stderr.write('IO error: %s\n' % e) 31460910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.exit(1) 31560910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except OSError as e: 31660910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.stderr.write('OS error: %s\n' % e) 31760910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.exit(1) 31860910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson except KeyboardInterrupt as e: 31960910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.stderr.write('Killed\n') 32060910b3de7aa85ff28da14f34c7084711f99ac74Matt Clarkson sys.exit(1) 321