-#!/usr/bin/env python
-
-## @file
-#
-# Automation of instructions from:
-# http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-doc/
-# howto-build/mingw-w64-howto-build.txt?revision=216&view=markup
-#
-# Copyright (c) 2008 - 2010, Intel Corporation
-# All rights reserved. This program and the accompanying materials
-# are licensed and made available under the terms and conditions of the BSD License
-# which accompanies this distribution. The full text of the license may be found at
-# http://opensource.org/licenses/bsd-license.php
-#
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-#
-
-
-from optparse import OptionParser
-import os
-import shutil
-import subprocess
-import sys
-import tarfile
-import urllib
-import urlparse
-try:
- from hashlib import md5
-except Exception:
- from md5 import md5
-
-if sys.version_info < (2, 5):
- #
- # This script (and edk2 BaseTools) require Python 2.5 or newer
- #
- print 'Python version 2.5 or later is required.'
- sys.exit(-1)
-
-#
-# Version and Copyright
-#
-VersionNumber = "0.01"
-__version__ = "%prog Version " + VersionNumber
-__copyright__ = "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved."
-
-class Config:
- """class Config
-
- Stores the configuration options for the rest of the script.
-
- Handles the command line options, and allows the code within
- the script to easily interact with the 'config' requested by
- the user.
- """
-
- def __init__(self):
- self.base_dir = os.getcwd()
- (self.options, self.args) = self.CheckOptions()
- self.__init_dirs__()
-
- def CheckOptions(self):
- Parser = \
- OptionParser(
- description=__copyright__,
- version=__version__,
- prog="mingw-gcc-build",
- usage="%prog [options] [target]"
- )
- Parser.add_option(
- "--arch",
- action = "store", type = "string",
- default = '',
- dest = "arch",
- help = "Processor architecture to build gcc for."
- )
- Parser.add_option(
- "--src-dir",
- action = "store", type = "string", dest = "src_dir",
- default = os.path.join(self.base_dir, 'src'),
- help = "Directory to download/extract binutils/gcc sources"
- )
- Parser.add_option(
- "--build-dir",
- action = "store", type = "string", dest = "build_dir",
- default = os.path.join(self.base_dir, 'build'),
- help = "Directory to download/extract binutils/gcc sources"
- )
- Parser.add_option(
- "--prefix",
- action = "store", type = "string", dest = "prefix",
- default = os.path.join(self.base_dir, 'install'),
- help = "Prefix to install binutils/gcc into"
- )
- Parser.add_option(
- "--skip-binutils",
- action = "store_true", dest = "skip_binutils",
- default = False,
- help = "Will skip building binutils"
- )
- Parser.add_option(
- "--skip-gcc",
- action = "store_true", dest = "skip_gcc",
- default = False,
- help = "Will skip building GCC"
- )
- Parser.add_option(
- "--symlinks",
- action = "store", type = "string", dest = "symlinks",
- default = os.path.join(self.base_dir, 'symlinks'),
- help = "Directory to create binutils/gcc symbolic links into."
- )
- Parser.add_option(
- "-v", "--verbose",
- action="store_true",
- type=None, help="Print verbose messages"
- )
-
- (Opt, Args) = Parser.parse_args()
-
- self.arch = Opt.arch.lower()
- allowedArchs = ('ia32', 'x64', 'ipf')
- if self.arch not in allowedArchs:
- Parser.error(
- 'Please use --arch to specify one of: %s' %
- ', '.join(allowedArchs)
- )
- self.target_arch = {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self.arch]
- self.target_sys = {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self.arch]
- self.target_bin = {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self.arch]
- self.target_combo = '-'.join((self.target_arch, self.target_sys, self.target_bin))
-
- return (Opt, Args)
-
- def __init_dirs__(self):
- self.src_dir = os.path.realpath(os.path.expanduser(self.options.src_dir))
- self.build_dir = os.path.realpath(os.path.expanduser(self.options.build_dir))
- self.prefix = os.path.realpath(os.path.expanduser(self.options.prefix))
- self.symlinks = os.path.realpath(os.path.expanduser(self.options.symlinks))
-
- def IsConfigOk(self):
-
- building = []
- if not self.options.skip_binutils:
- building.append('binutils')
- if not self.options.skip_gcc:
- building.append('gcc')
- if len(building) == 0:
- print "Nothing will be built!"
- print
- print "Please try using --help and then change the configuration."
- return False
-
- print "Current directory:"
- print " ", self.base_dir
- print "Sources download/extraction:", self.Relative(self.src_dir)
- print "Build directory :", self.Relative(self.build_dir)
- print "Prefix (install) directory :", self.Relative(self.prefix)
- print "Create symlinks directory :", self.Relative(self.symlinks)
- print "Building :", ', '.join(building)
- print
- answer = raw_input("Is this configuration ok? (default = no): ")
- if (answer.lower() not in ('y', 'yes')):
- print
- print "Please try using --help and then change the configuration."
- return False
-
- if self.arch.lower() == 'ipf':
- print
- print 'Please note that the IPF compiler built by this script has'
- print 'not yet been validated!'
- print
- answer = raw_input("Are you sure you want to build it? (default = no): ")
- if (answer.lower() not in ('y', 'yes')):
- print
- print "Please try using --help and then change the configuration."
- return False
-
- print
- return True
-
- def Relative(self, path):
- if path.startswith(self.base_dir):
- return '.' + path[len(self.base_dir):]
- return path
-
- def MakeDirs(self):
- for path in (self.src_dir, self.build_dir,self.prefix, self.symlinks):
- if not os.path.exists(path):
- os.makedirs(path)
-
-class SourceFiles:
- """class SourceFiles
-
- Handles the downloading of source files used by the script.
- """
-
- def __init__(self, config):
- self.config = config
- self.source_files = self.source_files[config.arch]
-
- if config.options.skip_binutils:
- del self.source_files['binutils']
-
- if config.options.skip_gcc:
- del self.source_files['gcc']
- del self.source_files['mingw_hdr']
-
- source_files_common = {
- 'binutils': {
- 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \
- 'binutils-$version.tar.bz2',
- 'version': '2.20.51.0.5',
- 'md5': '6d2de7cdf7a8389e70b124e3d73b4d37',
- },
- }
-
- source_files_x64 = {
- 'gcc': {
- 'url': 'http://ftpmirror.gnu.org/gcc/' + \
- 'gcc-$version/gcc-$version.tar.bz2',
- 'version': '4.3.0',
- 'md5': '197ed8468b38db1d3481c3111691d85b',
- },
- 'mingw_hdr': {
- 'url': 'http://sourceforge.net/projects/' + \
- 'mingw-w64/files/mingw-w64/mingw-w64-snapshot/' + \
- 'mingw-w64-v1.0-snapshot-$version.tar.bz2/download',
- 'extract-dir': os.path.join('mingw-w64-v1.0-$version', 'mingw-w64-headers'),
- 'version': '20100223',
- 'md5': '700b9f54e740b1b962c8a3a0f52b7c04',
- },
- }
-
- source_files_ia32 = {
- 'gcc': source_files_x64['gcc'],
- 'mingw_hdr': {
- 'url': 'http://sourceforge.net/projects/' + \
- 'mingw/files/MinGW%20Runtime/' + \
- 'mingwrt-$version/' + \
- 'mingwrt-$version-mingw32-src.tar.gz/download',
- 'extract-dir': 'mingwrt-$version-mingw32',
- 'version': '3.15.2',
- 'md5': '7bf0525f158213f3ac990ea68a5ec34d',
- },
- }
-
- source_files_ipf = source_files_x64.copy()
- source_files_ipf['gcc']['configure-params'] = (
- '--with-gnu-as', '--with-gnu-ld', '--with-newlib',
- '--verbose', '--disable-libssp', '--disable-nls',
- '--enable-languages=c,c++'
- )
-
- source_files = {
- 'ia32': [source_files_common, source_files_ia32],
- 'x64': [source_files_common, source_files_x64],
- 'ipf': [source_files_common, source_files_ipf],
- }
-
- for arch in source_files:
- mergedSourceFiles = {}
- for source_files_dict in source_files[arch]:
- mergedSourceFiles.update(source_files_dict)
- for downloadItem in mergedSourceFiles:
- fdata = mergedSourceFiles[downloadItem]
- fdata['filename'] = fdata['url'].split('/')[-1]
- if 'extract-dir' not in fdata:
- for ext in ('.tar.gz', '.tar.bz2', '.zip'):
- if fdata['filename'].endswith(ext):
- fdata['extract-dir'] = fdata['filename'][:-len(ext)]
- break
- replaceables = ('extract-dir', 'filename', 'url')
- for replaceItem in fdata:
- if replaceItem in replaceables: continue
- if type(fdata[replaceItem]) != str: continue
- for replaceable in replaceables:
- if type(fdata[replaceable]) != str: continue
- if replaceable in fdata:
- fdata[replaceable] = \
- fdata[replaceable].replace(
- '$' + replaceItem,
- fdata[replaceItem]
- )
- source_files[arch] = mergedSourceFiles
- #print 'source_files:', source_files
-
- def GetAll(self):
-
- def progress(received, blockSize, fileSize):
- if fileSize < 0: return
- wDots = (100 * received * blockSize) / fileSize / 10
- if wDots > self.dots:
- for i in range(wDots - self.dots):
- print '.',
- sys.stdout.flush()
- self.dots += 1
-
- maxRetries = 1
- for (fname, fdata) in self.source_files.items():
- for retries in range(maxRetries):
- try:
- self.dots = 0
- local_file = os.path.join(self.config.src_dir, fdata['filename'])
- url = fdata['url']
- print 'Downloading %s:' % fname, url
- if retries > 0:
- print '(retry)',
- sys.stdout.flush()
-
- completed = False
- if os.path.exists(local_file):
- md5_pass = self.checkHash(fdata)
- if md5_pass:
- print '[md5 match]',
- else:
- print '[md5 mismatch]',
- sys.stdout.flush()
- completed = md5_pass
-
- if not completed:
- urllib.urlretrieve(url, local_file, progress)
-
- #
- # BUGBUG: Suggest proxy to user if download fails.
- #
- # export http_proxy=http://proxyservername.mycompany.com:911
- # export ftp_proxy=http://proxyservername.mycompany.com:911
-
- if not completed and os.path.exists(local_file):
- md5_pass = self.checkHash(fdata)
- if md5_pass:
- print '[md5 match]',
- else:
- print '[md5 mismatch]',
- sys.stdout.flush()
- completed = md5_pass
-
- if completed:
- print '[done]'
- break
- else:
- print '[failed]'
- print ' Tried to retrieve', url
- print ' to', local_file
- print 'Possible fixes:'
- print '* If you are behind a web-proxy, try setting the',
- print 'http_proxy environment variable'
- print '* You can try to download this file separately',
- print 'and rerun this script'
- raise Exception()
-
- except KeyboardInterrupt:
- print '[KeyboardInterrupt]'
- return False
-
- except Exception, e:
- print e
-
- if not completed: return False
-
- return True
-
- def checkHash(self, fdata):
- local_file = os.path.join(self.config.src_dir, fdata['filename'])
- expect_md5 = fdata['md5']
- data = open(local_file).read()
- md5sum = md5()
- md5sum.update(data)
- return md5sum.hexdigest().lower() == expect_md5.lower()
-
- def GetModules(self):
- return self.source_files.keys()
-
- def GetFilenameOf(self, module):
- return self.source_files[module]['filename']
-
- def GetMd5Of(self, module):
- return self.source_files[module]['md5']
-
- def GetExtractDirOf(self, module):
- return self.source_files[module]['extract-dir']
-
- def GetAdditionalParameters(self, module, step):
- key = step + '-params'
- if key in self.source_files[module]:
- return self.source_files[module][key]
- else:
- return tuple()
-
-class Extracter:
- """class Extracter
-
- Handles the extraction of the source files from their downloaded
- archive files.
- """
-
- def __init__(self, source_files, config):
- self.source_files = source_files
- self.config = config
-
- def Extract(self, module):
- src = self.config.src_dir
- extractDst = os.path.join(src, self.config.arch)
- local_file = os.path.join(src, self.source_files.GetFilenameOf(module))
- moduleMd5 = self.source_files.GetMd5Of(module)
- extracted = os.path.join(extractDst, os.path.split(local_file)[1] + '.extracted')
- if not os.path.exists(extractDst):
- os.mkdir(extractDst)
-
- extractedMd5 = None
- if os.path.exists(extracted):
- extractedMd5 = open(extracted).read()
-
- if extractedMd5 != moduleMd5:
- print 'Extracting %s:' % self.config.Relative(local_file)
- tar = tarfile.open(local_file)
- tar.extractall(extractDst)
- open(extracted, 'w').write(moduleMd5)
- else:
- pass
- #print 'Previously extracted', self.config.Relative(local_file)
-
- def ExtractAll(self):
- for module in self.source_files.GetModules():
- self.Extract(module)
-
-class Builder:
- """class Builder
-
- Builds and installs the GCC tool suite.
- """
-
- def __init__(self, source_files, config):
- self.source_files = source_files
- self.config = config
-
- def Build(self):
- if not self.config.options.skip_binutils:
- self.BuildModule('binutils')
- if not self.config.options.skip_gcc:
- self.CopyIncludeDirectory()
- self.BuildModule('gcc')
- self.MakeSymLinks()
-
- def IsBuildStepComplete(self, step):
- return \
- os.path.exists(
- os.path.join(
- self.config.build_dir, self.config.arch, step + '.completed'
- )
- )
-
- def MarkBuildStepComplete(self, step):
- open(
- os.path.join(
- self.config.build_dir, self.config.arch, step + '.completed'
- ),
- "w"
- ).close()
-
- def CopyIncludeDirectory(self):
- linkdst = os.path.join(self.config.prefix, 'mingw')
- src = os.path.join(
- self.config.src_dir,
- self.config.arch,
- self.source_files.GetExtractDirOf('mingw_hdr'),
- 'include'
- )
- dst_parent = os.path.join(self.config.prefix, self.config.target_combo)
- dst = os.path.join(dst_parent, 'include')
- if not os.path.exists(dst):
- if not os.path.exists(dst_parent):
- os.makedirs(dst_parent)
- print 'Copying headers to', self.config.Relative(dst)
- shutil.copytree(src, dst, True)
- if not os.path.lexists(linkdst):
- print 'Making symlink at', self.config.Relative(linkdst)
- os.symlink(self.config.target_combo, linkdst)
-
- def BuildModule(self, module):
- base_dir = os.getcwd()
- build_dir = os.path.join(self.config.build_dir, self.config.arch, module)
- module_dir = self.source_files.GetExtractDirOf(module)
- module_dir = os.path.realpath(os.path.join('src', self.config.arch, module_dir))
- configure = os.path.join(module_dir, 'configure')
- prefix = self.config.prefix
- if not os.path.exists(build_dir):
- os.makedirs(build_dir)
- os.chdir(build_dir)
-
- cmd = (
- configure,
- '--target=%s' % self.config.target_combo,
- '--prefix=' + prefix,
- '--with-sysroot=' + prefix,
- '--disable-werror',
- )
- if os.path.exists('/opt/local/include/gmp.h'):
- cmd += ('--with-gmp=/opt/local',)
- if module == 'gcc': cmd += ('--oldincludedir=/opt/local/include',)
- cmd += self.source_files.GetAdditionalParameters(module, 'configure')
- self.RunCommand(cmd, module, 'config', skipable=True)
-
- cmd = ('make',)
- if module == 'gcc':
- cmd += ('all-gcc',)
- self.RunCommand(cmd, module, 'build')
-
- cmd = ('make',)
- if module == 'gcc':
- cmd += ('install-gcc',)
- else:
- cmd += ('install',)
- self.RunCommand(cmd, module, 'install')
-
- os.chdir(base_dir)
-
- print '%s module is now built and installed' % module
-
- def RunCommand(self, cmd, module, stage, skipable=False):
- if skipable:
- if self.IsBuildStepComplete('%s.%s' % (module, stage)):
- return
-
- popen = lambda cmd: \
- subprocess.Popen(
- cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT
- )
-
- print '%s [%s] ...' % (module, stage),
- sys.stdout.flush()
- p = popen(cmd)
- output = p.stdout.read()
- p.wait()
- if p.returncode != 0:
- print '[failed!]'
- logFile = os.path.join(self.config.build_dir, 'log.txt')
- f = open(logFile, "w")
- f.write(output)
- f.close()
- raise Exception, 'Failed to %s %s\n' % (stage, module) + \
- 'See output log at %s' % self.config.Relative(logFile)
- else:
- print '[done]'
-
- if skipable:
- self.MarkBuildStepComplete('%s.%s' % (module, stage))
-
- def MakeSymLinks(self):
- links_dir = os.path.join(self.config.symlinks, self.config.arch)
- if not os.path.exists(links_dir):
- os.makedirs(links_dir)
- startPrinted = False
- for link in ('ar', 'ld', 'gcc'):
- src = os.path.join(
- self.config.prefix, 'bin', self.config.target_combo + '-' + link
- )
- linkdst = os.path.join(links_dir, link)
- if not os.path.lexists(linkdst):
- if not startPrinted:
- print 'Making symlinks in %s:' % self.config.Relative(links_dir),
- startPrinted = True
- print link,
- os.symlink(src, linkdst)
-
- if startPrinted:
- print '[done]'
-
-class App:
- """class App
-
- The main body of the application.
- """
-
- def __init__(self):
- config = Config()
-
- if not config.IsConfigOk():
- return
-
- config.MakeDirs()
-
- sources = SourceFiles(config)
- result = sources.GetAll()
- if result:
- print 'All files have been downloaded & verified'
- else:
- print 'An error occured while downloading a file'
- return
-
- Extracter(sources, config).ExtractAll()
-
- Builder(sources, config).Build()
-
-App()
-
+#!/usr/bin/env python\r
+\r
+## @file\r
+#\r
+# Automation of instructions from:\r
+# http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-doc/\r
+# howto-build/mingw-w64-howto-build.txt?revision=216&view=markup\r
+#\r
+# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
+# This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+\r
+\r
+from __future__ import print_function\r
+from optparse import OptionParser\r
+import os\r
+import shutil\r
+import subprocess\r
+import sys\r
+import tarfile\r
+import urllib\r
+import urlparse\r
+try:\r
+ from hashlib import md5\r
+except Exception:\r
+ from md5 import md5\r
+\r
+if sys.version_info < (2, 5):\r
+ #\r
+ # This script (and edk2 BaseTools) require Python 2.5 or newer\r
+ #\r
+ print('Python version 2.5 or later is required.')\r
+ sys.exit(-1)\r
+\r
+#\r
+# Version and Copyright\r
+#\r
+VersionNumber = "0.01"\r
+__version__ = "%prog Version " + VersionNumber\r
+__copyright__ = "Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved."\r
+\r
+class Config:\r
+ """class Config\r
+\r
+ Stores the configuration options for the rest of the script.\r
+\r
+ Handles the command line options, and allows the code within\r
+ the script to easily interact with the 'config' requested by\r
+ the user.\r
+ """\r
+\r
+ def __init__(self):\r
+ self.base_dir = os.getcwd()\r
+ (self.options, self.args) = self.CheckOptions()\r
+ self.__init_dirs__()\r
+\r
+ def CheckOptions(self):\r
+ Parser = \\r
+ OptionParser(\r
+ description=__copyright__,\r
+ version=__version__,\r
+ prog="mingw-gcc-build",\r
+ usage="%prog [options] [target]"\r
+ )\r
+ Parser.add_option(\r
+ "--arch",\r
+ action = "store", type = "string",\r
+ default = '',\r
+ dest = "arch",\r
+ help = "Processor architecture to build gcc for."\r
+ )\r
+ Parser.add_option(\r
+ "--src-dir",\r
+ action = "store", type = "string", dest = "src_dir",\r
+ default = os.path.join(self.base_dir, 'src'),\r
+ help = "Directory to download/extract binutils/gcc sources"\r
+ )\r
+ Parser.add_option(\r
+ "--build-dir",\r
+ action = "store", type = "string", dest = "build_dir",\r
+ default = os.path.join(self.base_dir, 'build'),\r
+ help = "Directory to download/extract binutils/gcc sources"\r
+ )\r
+ Parser.add_option(\r
+ "--prefix",\r
+ action = "store", type = "string", dest = "prefix",\r
+ default = os.path.join(self.base_dir, 'install'),\r
+ help = "Prefix to install binutils/gcc into"\r
+ )\r
+ Parser.add_option(\r
+ "--skip-binutils",\r
+ action = "store_true", dest = "skip_binutils",\r
+ default = False,\r
+ help = "Will skip building binutils"\r
+ )\r
+ Parser.add_option(\r
+ "--skip-gcc",\r
+ action = "store_true", dest = "skip_gcc",\r
+ default = False,\r
+ help = "Will skip building GCC"\r
+ )\r
+ Parser.add_option(\r
+ "--symlinks",\r
+ action = "store", type = "string", dest = "symlinks",\r
+ default = os.path.join(self.base_dir, 'symlinks'),\r
+ help = "Directory to create binutils/gcc symbolic links into."\r
+ )\r
+ Parser.add_option(\r
+ "-v", "--verbose",\r
+ action="store_true",\r
+ type=None, help="Print verbose messages"\r
+ )\r
+\r
+ (Opt, Args) = Parser.parse_args()\r
+\r
+ self.arch = Opt.arch.lower()\r
+ allowedArchs = ('ia32', 'x64', 'ipf')\r
+ if self.arch not in allowedArchs:\r
+ Parser.error(\r
+ 'Please use --arch to specify one of: %s' %\r
+ ', '.join(allowedArchs)\r
+ )\r
+ self.target_arch = {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self.arch]\r
+ self.target_sys = {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self.arch]\r
+ self.target_bin = {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self.arch]\r
+ self.target_combo = '-'.join((self.target_arch, self.target_sys, self.target_bin))\r
+\r
+ return (Opt, Args)\r
+\r
+ def __init_dirs__(self):\r
+ self.src_dir = os.path.realpath(os.path.expanduser(self.options.src_dir))\r
+ self.build_dir = os.path.realpath(os.path.expanduser(self.options.build_dir))\r
+ self.prefix = os.path.realpath(os.path.expanduser(self.options.prefix))\r
+ self.symlinks = os.path.realpath(os.path.expanduser(self.options.symlinks))\r
+\r
+ def IsConfigOk(self):\r
+\r
+ building = []\r
+ if not self.options.skip_binutils:\r
+ building.append('binutils')\r
+ if not self.options.skip_gcc:\r
+ building.append('gcc')\r
+ if len(building) == 0:\r
+ print("Nothing will be built!")\r
+ print()\r
+ print("Please try using --help and then change the configuration.")\r
+ return False\r
+\r
+ print("Current directory:")\r
+ print(" ", self.base_dir)\r
+ print("Sources download/extraction:", self.Relative(self.src_dir))\r
+ print("Build directory :", self.Relative(self.build_dir))\r
+ print("Prefix (install) directory :", self.Relative(self.prefix))\r
+ print("Create symlinks directory :", self.Relative(self.symlinks))\r
+ print("Building :", ', '.join(building))\r
+ print()\r
+ answer = raw_input("Is this configuration ok? (default = no): ")\r
+ if (answer.lower() not in ('y', 'yes')):\r
+ print()\r
+ print("Please try using --help and then change the configuration.")\r
+ return False\r
+\r
+ if self.arch.lower() == 'ipf':\r
+ print()\r
+ print('Please note that the IPF compiler built by this script has')\r
+ print('not yet been validated!')\r
+ print()\r
+ answer = raw_input("Are you sure you want to build it? (default = no): ")\r
+ if (answer.lower() not in ('y', 'yes')):\r
+ print()\r
+ print("Please try using --help and then change the configuration.")\r
+ return False\r
+\r
+ print()\r
+ return True\r
+\r
+ def Relative(self, path):\r
+ if path.startswith(self.base_dir):\r
+ return '.' + path[len(self.base_dir):]\r
+ return path\r
+\r
+ def MakeDirs(self):\r
+ for path in (self.src_dir, self.build_dir, self.prefix, self.symlinks):\r
+ if not os.path.exists(path):\r
+ os.makedirs(path)\r
+\r
+class SourceFiles:\r
+ """class SourceFiles\r
+\r
+ Handles the downloading of source files used by the script.\r
+ """\r
+\r
+ def __init__(self, config):\r
+ self.config = config\r
+ self.source_files = self.source_files[config.arch]\r
+\r
+ if config.options.skip_binutils:\r
+ del self.source_files['binutils']\r
+\r
+ if config.options.skip_gcc:\r
+ del self.source_files['gcc']\r
+ del self.source_files['mingw_hdr']\r
+\r
+ source_files_common = {\r
+ 'binutils': {\r
+ 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \\r
+ 'binutils-$version.tar.bz2',\r
+ 'version': '2.20.51.0.5',\r
+ 'md5': '6d2de7cdf7a8389e70b124e3d73b4d37',\r
+ },\r
+ }\r
+\r
+ source_files_x64 = {\r
+ 'gcc': {\r
+ 'url': 'http://ftpmirror.gnu.org/gcc/' + \\r
+ 'gcc-$version/gcc-$version.tar.bz2',\r
+ 'version': '4.3.0',\r
+ 'md5': '197ed8468b38db1d3481c3111691d85b',\r
+ },\r
+ }\r
+\r
+ source_files_ia32 = {\r
+ 'gcc': source_files_x64['gcc'],\r
+ }\r
+\r
+ source_files_ipf = source_files_x64.copy()\r
+ source_files_ipf['gcc']['configure-params'] = (\r
+ '--with-gnu-as', '--with-gnu-ld', '--with-newlib',\r
+ '--verbose', '--disable-libssp', '--disable-nls',\r
+ '--enable-languages=c,c++'\r
+ )\r
+\r
+ source_files = {\r
+ 'ia32': [source_files_common, source_files_ia32],\r
+ 'x64': [source_files_common, source_files_x64],\r
+ 'ipf': [source_files_common, source_files_ipf],\r
+ }\r
+\r
+ for arch in source_files:\r
+ mergedSourceFiles = {}\r
+ for source_files_dict in source_files[arch]:\r
+ mergedSourceFiles.update(source_files_dict)\r
+ for downloadItem in mergedSourceFiles:\r
+ fdata = mergedSourceFiles[downloadItem]\r
+ fdata['filename'] = fdata['url'].split('/')[-1]\r
+ if 'extract-dir' not in fdata:\r
+ for ext in ('.tar.gz', '.tar.bz2', '.zip'):\r
+ if fdata['filename'].endswith(ext):\r
+ fdata['extract-dir'] = fdata['filename'][:-len(ext)]\r
+ break\r
+ replaceables = ('extract-dir', 'filename', 'url')\r
+ for replaceItem in fdata:\r
+ if replaceItem in replaceables: continue\r
+ if not isinstance(fdata[replaceItem], str): continue\r
+ for replaceable in replaceables:\r
+ if not isinstance(fdata[replaceable], str): continue\r
+ if replaceable in fdata:\r
+ fdata[replaceable] = \\r
+ fdata[replaceable].replace(\r
+ '$' + replaceItem,\r
+ fdata[replaceItem]\r
+ )\r
+ source_files[arch] = mergedSourceFiles\r
+ #print 'source_files:', source_files\r
+\r
+ def GetAll(self):\r
+\r
+ def progress(received, blockSize, fileSize):\r
+ if fileSize < 0: return\r
+ wDots = (100 * received * blockSize) / fileSize / 10\r
+ if wDots > self.dots:\r
+ for i in range(wDots - self.dots):\r
+ print('.', end=' ')\r
+ sys.stdout.flush()\r
+ self.dots += 1\r
+\r
+ maxRetries = 1\r
+ for (fname, fdata) in self.source_files.items():\r
+ for retries in range(maxRetries):\r
+ try:\r
+ self.dots = 0\r
+ local_file = os.path.join(self.config.src_dir, fdata['filename'])\r
+ url = fdata['url']\r
+ print('Downloading %s:' % fname, url)\r
+ if retries > 0:\r
+ print('(retry)', end=' ')\r
+ sys.stdout.flush()\r
+\r
+ completed = False\r
+ if os.path.exists(local_file):\r
+ md5_pass = self.checkHash(fdata)\r
+ if md5_pass:\r
+ print('[md5 match]', end=' ')\r
+ else:\r
+ print('[md5 mismatch]', end=' ')\r
+ sys.stdout.flush()\r
+ completed = md5_pass\r
+\r
+ if not completed:\r
+ urllib.urlretrieve(url, local_file, progress)\r
+\r
+ #\r
+ # BUGBUG: Suggest proxy to user if download fails.\r
+ #\r
+ # export http_proxy=http://proxyservername.mycompany.com:911\r
+ # export ftp_proxy=http://proxyservername.mycompany.com:911\r
+\r
+ if not completed and os.path.exists(local_file):\r
+ md5_pass = self.checkHash(fdata)\r
+ if md5_pass:\r
+ print('[md5 match]', end=' ')\r
+ else:\r
+ print('[md5 mismatch]', end=' ')\r
+ sys.stdout.flush()\r
+ completed = md5_pass\r
+\r
+ if completed:\r
+ print('[done]')\r
+ break\r
+ else:\r
+ print('[failed]')\r
+ print(' Tried to retrieve', url)\r
+ print(' to', local_file)\r
+ print('Possible fixes:')\r
+ print('* If you are behind a web-proxy, try setting the', end=' ')\r
+ print('http_proxy environment variable')\r
+ print('* You can try to download this file separately', end=' ')\r
+ print('and rerun this script')\r
+ raise Exception()\r
+\r
+ except KeyboardInterrupt:\r
+ print('[KeyboardInterrupt]')\r
+ return False\r
+\r
+ except Exception as e:\r
+ print(e)\r
+\r
+ if not completed: return False\r
+\r
+ return True\r
+\r
+ def checkHash(self, fdata):\r
+ local_file = os.path.join(self.config.src_dir, fdata['filename'])\r
+ expect_md5 = fdata['md5']\r
+ data = open(local_file).read()\r
+ md5sum = md5()\r
+ md5sum.update(data)\r
+ return md5sum.hexdigest().lower() == expect_md5.lower()\r
+\r
+ def GetModules(self):\r
+ return self.source_files.keys()\r
+\r
+ def GetFilenameOf(self, module):\r
+ return self.source_files[module]['filename']\r
+\r
+ def GetMd5Of(self, module):\r
+ return self.source_files[module]['md5']\r
+\r
+ def GetExtractDirOf(self, module):\r
+ return self.source_files[module]['extract-dir']\r
+\r
+ def GetAdditionalParameters(self, module, step):\r
+ key = step + '-params'\r
+ if key in self.source_files[module]:\r
+ return self.source_files[module][key]\r
+ else:\r
+ return tuple()\r
+\r
+class Extracter:\r
+ """class Extracter\r
+\r
+ Handles the extraction of the source files from their downloaded\r
+ archive files.\r
+ """\r
+\r
+ def __init__(self, source_files, config):\r
+ self.source_files = source_files\r
+ self.config = config\r
+\r
+ def Extract(self, module):\r
+ src = self.config.src_dir\r
+ extractDst = os.path.join(src, self.config.arch)\r
+ local_file = os.path.join(src, self.source_files.GetFilenameOf(module))\r
+ moduleMd5 = self.source_files.GetMd5Of(module)\r
+ extracted = os.path.join(extractDst, os.path.split(local_file)[1] + '.extracted')\r
+ if not os.path.exists(extractDst):\r
+ os.mkdir(extractDst)\r
+\r
+ extractedMd5 = None\r
+ if os.path.exists(extracted):\r
+ extractedMd5 = open(extracted).read()\r
+\r
+ if extractedMd5 != moduleMd5:\r
+ print('Extracting %s:' % self.config.Relative(local_file))\r
+ tar = tarfile.open(local_file)\r
+ tar.extractall(extractDst)\r
+ open(extracted, 'w').write(moduleMd5)\r
+ else:\r
+ pass\r
+ #print 'Previously extracted', self.config.Relative(local_file)\r
+\r
+ def ExtractAll(self):\r
+ for module in self.source_files.GetModules():\r
+ self.Extract(module)\r
+\r
+class Builder:\r
+ """class Builder\r
+\r
+ Builds and installs the GCC tool suite.\r
+ """\r
+\r
+ def __init__(self, source_files, config):\r
+ self.source_files = source_files\r
+ self.config = config\r
+\r
+ def Build(self):\r
+ if not self.config.options.skip_binutils:\r
+ self.BuildModule('binutils')\r
+ if not self.config.options.skip_gcc:\r
+ self.BuildModule('gcc')\r
+ self.MakeSymLinks()\r
+\r
+ def IsBuildStepComplete(self, step):\r
+ return \\r
+ os.path.exists(\r
+ os.path.join(\r
+ self.config.build_dir, self.config.arch, step + '.completed'\r
+ )\r
+ )\r
+\r
+ def MarkBuildStepComplete(self, step):\r
+ open(\r
+ os.path.join(\r
+ self.config.build_dir, self.config.arch, step + '.completed'\r
+ ),\r
+ "w"\r
+ ).close()\r
+\r
+\r
+ def BuildModule(self, module):\r
+ base_dir = os.getcwd()\r
+ build_dir = os.path.join(self.config.build_dir, self.config.arch, module)\r
+ module_dir = self.source_files.GetExtractDirOf(module)\r
+ module_dir = os.path.realpath(os.path.join('src', self.config.arch, module_dir))\r
+ configure = os.path.join(module_dir, 'configure')\r
+ prefix = self.config.prefix\r
+ if not os.path.exists(build_dir):\r
+ os.makedirs(build_dir)\r
+ os.chdir(build_dir)\r
+\r
+ cmd = (\r
+ configure,\r
+ '--target=%s' % self.config.target_combo,\r
+ '--prefix=' + prefix,\r
+ '--with-sysroot=' + prefix,\r
+ '--disable-werror',\r
+ )\r
+ if os.path.exists('/opt/local/include/gmp.h'):\r
+ cmd += ('--with-gmp=/opt/local',)\r
+ if module == 'gcc': cmd += ('--oldincludedir=/opt/local/include',)\r
+ cmd += self.source_files.GetAdditionalParameters(module, 'configure')\r
+ self.RunCommand(cmd, module, 'config', skipable=True)\r
+\r
+ cmd = ('make',)\r
+ if module == 'gcc':\r
+ cmd += ('all-gcc',)\r
+ self.RunCommand(cmd, module, 'build')\r
+\r
+ cmd = ('make',)\r
+ if module == 'gcc':\r
+ cmd += ('install-gcc',)\r
+ else:\r
+ cmd += ('install',)\r
+ self.RunCommand(cmd, module, 'install')\r
+\r
+ os.chdir(base_dir)\r
+\r
+ print('%s module is now built and installed' % module)\r
+\r
+ def RunCommand(self, cmd, module, stage, skipable=False):\r
+ if skipable:\r
+ if self.IsBuildStepComplete('%s.%s' % (module, stage)):\r
+ return\r
+\r
+ popen = lambda cmd: \\r
+ subprocess.Popen(\r
+ cmd,\r
+ stdin=subprocess.PIPE,\r
+ stdout=subprocess.PIPE,\r
+ stderr=subprocess.STDOUT\r
+ )\r
+\r
+ print('%s [%s] ...' % (module, stage), end=' ')\r
+ sys.stdout.flush()\r
+ p = popen(cmd)\r
+ output = p.stdout.read()\r
+ p.wait()\r
+ if p.returncode != 0:\r
+ print('[failed!]')\r
+ logFile = os.path.join(self.config.build_dir, 'log.txt')\r
+ f = open(logFile, "w")\r
+ f.write(output)\r
+ f.close()\r
+ raise Exception('Failed to %s %s\n' % (stage, module) + \\r
+ 'See output log at %s' % self.config.Relative(logFile))\r
+ else:\r
+ print('[done]')\r
+\r
+ if skipable:\r
+ self.MarkBuildStepComplete('%s.%s' % (module, stage))\r
+\r
+ def MakeSymLinks(self):\r
+ links_dir = os.path.join(self.config.symlinks, self.config.arch)\r
+ if not os.path.exists(links_dir):\r
+ os.makedirs(links_dir)\r
+ startPrinted = False\r
+ for link in ('ar', 'ld', 'gcc'):\r
+ src = os.path.join(\r
+ self.config.prefix, 'bin', self.config.target_combo + '-' + link\r
+ )\r
+ linkdst = os.path.join(links_dir, link)\r
+ if not os.path.lexists(linkdst):\r
+ if not startPrinted:\r
+ print('Making symlinks in %s:' % self.config.Relative(links_dir), end=' ')\r
+ startPrinted = True\r
+ print(link, end=' ')\r
+ os.symlink(src, linkdst)\r
+\r
+ if startPrinted:\r
+ print('[done]')\r
+\r
+class App:\r
+ """class App\r
+\r
+ The main body of the application.\r
+ """\r
+\r
+ def __init__(self):\r
+ config = Config()\r
+\r
+ if not config.IsConfigOk():\r
+ return\r
+\r
+ config.MakeDirs()\r
+\r
+ sources = SourceFiles(config)\r
+ result = sources.GetAll()\r
+ if result:\r
+ print('All files have been downloaded & verified')\r
+ else:\r
+ print('An error occured while downloading a file')\r
+ return\r
+\r
+ Extracter(sources, config).ExtractAll()\r
+\r
+ Builder(sources, config).Build()\r
+\r
+App()\r
+\r