]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/gcc/mingw-gcc-build.py
5 # Automation of instructions from:
6 # http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-doc/
7 # howto-build/mingw-w64-howto-build.txt?revision=216&view=markup
9 # Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
10 # This program and the accompanying materials
11 # are licensed and made available under the terms and conditions of the BSD License
12 # which accompanies this distribution. The full text of the license may be found at
13 # http://opensource.org/licenses/bsd-license.php
15 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 from optparse
import OptionParser
29 from hashlib
import md5
33 if sys
.version_info
< (2, 5):
35 # This script (and edk2 BaseTools) require Python 2.5 or newer
37 print 'Python version 2.5 or later is required.'
41 # Version and Copyright
43 VersionNumber
= "0.01"
44 __version__
= "%prog Version " + VersionNumber
45 __copyright__
= "Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved."
50 Stores the configuration options for the rest of the script.
52 Handles the command line options, and allows the code within
53 the script to easily interact with the 'config' requested by
58 self
.base_dir
= os
.getcwd()
59 (self
.options
, self
.args
) = self
.CheckOptions()
62 def CheckOptions(self
):
65 description
=__copyright__
,
67 prog
="mingw-gcc-build",
68 usage
="%prog [options] [target]"
72 action
= "store", type = "string",
75 help = "Processor architecture to build gcc for."
79 action
= "store", type = "string", dest
= "src_dir",
80 default
= os
.path
.join(self
.base_dir
, 'src'),
81 help = "Directory to download/extract binutils/gcc sources"
85 action
= "store", type = "string", dest
= "build_dir",
86 default
= os
.path
.join(self
.base_dir
, 'build'),
87 help = "Directory to download/extract binutils/gcc sources"
91 action
= "store", type = "string", dest
= "prefix",
92 default
= os
.path
.join(self
.base_dir
, 'install'),
93 help = "Prefix to install binutils/gcc into"
97 action
= "store_true", dest
= "skip_binutils",
99 help = "Will skip building binutils"
103 action
= "store_true", dest
= "skip_gcc",
105 help = "Will skip building GCC"
109 action
= "store", type = "string", dest
= "symlinks",
110 default
= os
.path
.join(self
.base_dir
, 'symlinks'),
111 help = "Directory to create binutils/gcc symbolic links into."
116 type=None, help="Print verbose messages"
119 (Opt
, Args
) = Parser
.parse_args()
121 self
.arch
= Opt
.arch
.lower()
122 allowedArchs
= ('ia32', 'x64', 'ipf')
123 if self
.arch
not in allowedArchs
:
125 'Please use --arch to specify one of: %s' %
126 ', '.join(allowedArchs
)
128 self
.target_arch
= {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self
.arch
]
129 self
.target_sys
= {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self
.arch
]
130 self
.target_bin
= {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self
.arch
]
131 self
.target_combo
= '-'.join((self
.target_arch
, self
.target_sys
, self
.target_bin
))
135 def __init_dirs__(self
):
136 self
.src_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.src_dir
))
137 self
.build_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.build_dir
))
138 self
.prefix
= os
.path
.realpath(os
.path
.expanduser(self
.options
.prefix
))
139 self
.symlinks
= os
.path
.realpath(os
.path
.expanduser(self
.options
.symlinks
))
141 def IsConfigOk(self
):
144 if not self
.options
.skip_binutils
:
145 building
.append('binutils')
146 if not self
.options
.skip_gcc
:
147 building
.append('gcc')
148 if len(building
) == 0:
149 print "Nothing will be built!"
151 print "Please try using --help and then change the configuration."
154 print "Current directory:"
155 print " ", self
.base_dir
156 print "Sources download/extraction:", self
.Relative(self
.src_dir
)
157 print "Build directory :", self
.Relative(self
.build_dir
)
158 print "Prefix (install) directory :", self
.Relative(self
.prefix
)
159 print "Create symlinks directory :", self
.Relative(self
.symlinks
)
160 print "Building :", ', '.join(building
)
162 answer
= raw_input("Is this configuration ok? (default = no): ")
163 if (answer
.lower() not in ('y', 'yes')):
165 print "Please try using --help and then change the configuration."
168 if self
.arch
.lower() == 'ipf':
170 print 'Please note that the IPF compiler built by this script has'
171 print 'not yet been validated!'
173 answer
= raw_input("Are you sure you want to build it? (default = no): ")
174 if (answer
.lower() not in ('y', 'yes')):
176 print "Please try using --help and then change the configuration."
182 def Relative(self
, path
):
183 if path
.startswith(self
.base_dir
):
184 return '.' + path
[len(self
.base_dir
):]
188 for path
in (self
.src_dir
, self
.build_dir
,self
.prefix
, self
.symlinks
):
189 if not os
.path
.exists(path
):
195 Handles the downloading of source files used by the script.
198 def __init__(self
, config
):
200 self
.source_files
= self
.source_files
[config
.arch
]
202 if config
.options
.skip_binutils
:
203 del self
.source_files
['binutils']
205 if config
.options
.skip_gcc
:
206 del self
.source_files
['gcc']
207 del self
.source_files
['mingw_hdr']
209 source_files_common
= {
211 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \
212 'binutils-$version.tar.bz2',
213 'version': '2.20.51.0.5',
214 'md5': '6d2de7cdf7a8389e70b124e3d73b4d37',
220 'url': 'http://ftpmirror.gnu.org/gcc/' + \
221 'gcc-$version/gcc-$version.tar.bz2',
223 'md5': '197ed8468b38db1d3481c3111691d85b',
226 'url': 'http://sourceforge.net/projects/' + \
227 'mingw-w64/files/mingw-w64/mingw-w64-snapshot/' + \
228 'mingw-w64-v1.0-snapshot-$version.tar.bz2/download',
229 'extract-dir': os
.path
.join('mingw-w64-v1.0-$version', 'mingw-w64-headers'),
230 'version': '20100427',
231 'md5': '1fe68f486bba8995f6a5cf0ed06c80f3',
235 source_files_ia32
= {
236 'gcc': source_files_x64
['gcc'],
238 'url': 'http://sourceforge.net/projects/' + \
239 'mingw/files/MinGW%20Runtime/' + \
240 'mingwrt-$version/' + \
241 'mingwrt-$version-mingw32-src.tar.gz/download',
242 'extract-dir': 'mingwrt-$version-mingw32',
244 'md5': '7bf0525f158213f3ac990ea68a5ec34d',
248 source_files_ipf
= source_files_x64
.copy()
249 source_files_ipf
['gcc']['configure-params'] = (
250 '--with-gnu-as', '--with-gnu-ld', '--with-newlib',
251 '--verbose', '--disable-libssp', '--disable-nls',
252 '--enable-languages=c,c++'
256 'ia32': [source_files_common
, source_files_ia32
],
257 'x64': [source_files_common
, source_files_x64
],
258 'ipf': [source_files_common
, source_files_ipf
],
261 for arch
in source_files
:
262 mergedSourceFiles
= {}
263 for source_files_dict
in source_files
[arch
]:
264 mergedSourceFiles
.update(source_files_dict
)
265 for downloadItem
in mergedSourceFiles
:
266 fdata
= mergedSourceFiles
[downloadItem
]
267 fdata
['filename'] = fdata
['url'].split('/')[-1]
268 if 'extract-dir' not in fdata
:
269 for ext
in ('.tar.gz', '.tar.bz2', '.zip'):
270 if fdata
['filename'].endswith(ext
):
271 fdata
['extract-dir'] = fdata
['filename'][:-len(ext
)]
273 replaceables
= ('extract-dir', 'filename', 'url')
274 for replaceItem
in fdata
:
275 if replaceItem
in replaceables
: continue
276 if type(fdata
[replaceItem
]) != str: continue
277 for replaceable
in replaceables
:
278 if type(fdata
[replaceable
]) != str: continue
279 if replaceable
in fdata
:
280 fdata
[replaceable
] = \
281 fdata
[replaceable
].replace(
285 source_files
[arch
] = mergedSourceFiles
286 #print 'source_files:', source_files
290 def progress(received
, blockSize
, fileSize
):
291 if fileSize
< 0: return
292 wDots
= (100 * received
* blockSize
) / fileSize
/ 10
293 if wDots
> self
.dots
:
294 for i
in range(wDots
- self
.dots
):
300 for (fname
, fdata
) in self
.source_files
.items():
301 for retries
in range(maxRetries
):
304 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
306 print 'Downloading %s:' % fname
, url
312 if os
.path
.exists(local_file
):
313 md5_pass
= self
.checkHash(fdata
)
317 print '[md5 mismatch]',
322 urllib
.urlretrieve(url
, local_file
, progress
)
325 # BUGBUG: Suggest proxy to user if download fails.
327 # export http_proxy=http://proxyservername.mycompany.com:911
328 # export ftp_proxy=http://proxyservername.mycompany.com:911
330 if not completed
and os
.path
.exists(local_file
):
331 md5_pass
= self
.checkHash(fdata
)
335 print '[md5 mismatch]',
344 print ' Tried to retrieve', url
345 print ' to', local_file
346 print 'Possible fixes:'
347 print '* If you are behind a web-proxy, try setting the',
348 print 'http_proxy environment variable'
349 print '* You can try to download this file separately',
350 print 'and rerun this script'
353 except KeyboardInterrupt:
354 print '[KeyboardInterrupt]'
360 if not completed
: return False
364 def checkHash(self
, fdata
):
365 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
366 expect_md5
= fdata
['md5']
367 data
= open(local_file
).read()
370 return md5sum
.hexdigest().lower() == expect_md5
.lower()
372 def GetModules(self
):
373 return self
.source_files
.keys()
375 def GetFilenameOf(self
, module
):
376 return self
.source_files
[module
]['filename']
378 def GetMd5Of(self
, module
):
379 return self
.source_files
[module
]['md5']
381 def GetExtractDirOf(self
, module
):
382 return self
.source_files
[module
]['extract-dir']
384 def GetAdditionalParameters(self
, module
, step
):
385 key
= step
+ '-params'
386 if key
in self
.source_files
[module
]:
387 return self
.source_files
[module
][key
]
394 Handles the extraction of the source files from their downloaded
398 def __init__(self
, source_files
, config
):
399 self
.source_files
= source_files
402 def Extract(self
, module
):
403 src
= self
.config
.src_dir
404 extractDst
= os
.path
.join(src
, self
.config
.arch
)
405 local_file
= os
.path
.join(src
, self
.source_files
.GetFilenameOf(module
))
406 moduleMd5
= self
.source_files
.GetMd5Of(module
)
407 extracted
= os
.path
.join(extractDst
, os
.path
.split(local_file
)[1] + '.extracted')
408 if not os
.path
.exists(extractDst
):
412 if os
.path
.exists(extracted
):
413 extractedMd5
= open(extracted
).read()
415 if extractedMd5
!= moduleMd5
:
416 print 'Extracting %s:' % self
.config
.Relative(local_file
)
417 tar
= tarfile
.open(local_file
)
418 tar
.extractall(extractDst
)
419 open(extracted
, 'w').write(moduleMd5
)
422 #print 'Previously extracted', self.config.Relative(local_file)
424 def ExtractAll(self
):
425 for module
in self
.source_files
.GetModules():
431 Builds and installs the GCC tool suite.
434 def __init__(self
, source_files
, config
):
435 self
.source_files
= source_files
439 if not self
.config
.options
.skip_binutils
:
440 self
.BuildModule('binutils')
441 if not self
.config
.options
.skip_gcc
:
442 self
.CopyIncludeDirectory()
443 self
.BuildModule('gcc')
446 def IsBuildStepComplete(self
, step
):
450 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
454 def MarkBuildStepComplete(self
, step
):
457 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
462 def CopyIncludeDirectory(self
):
463 linkdst
= os
.path
.join(self
.config
.prefix
, 'mingw')
467 self
.source_files
.GetExtractDirOf('mingw_hdr'),
470 dst_parent
= os
.path
.join(self
.config
.prefix
, self
.config
.target_combo
)
471 dst
= os
.path
.join(dst_parent
, 'include')
472 if not os
.path
.exists(dst
):
473 if not os
.path
.exists(dst_parent
):
474 os
.makedirs(dst_parent
)
475 print 'Copying headers to', self
.config
.Relative(dst
)
476 shutil
.copytree(src
, dst
, True)
477 if not os
.path
.lexists(linkdst
):
478 print 'Making symlink at', self
.config
.Relative(linkdst
)
479 os
.symlink(self
.config
.target_combo
, linkdst
)
481 def BuildModule(self
, module
):
482 base_dir
= os
.getcwd()
483 build_dir
= os
.path
.join(self
.config
.build_dir
, self
.config
.arch
, module
)
484 module_dir
= self
.source_files
.GetExtractDirOf(module
)
485 module_dir
= os
.path
.realpath(os
.path
.join('src', self
.config
.arch
, module_dir
))
486 configure
= os
.path
.join(module_dir
, 'configure')
487 prefix
= self
.config
.prefix
488 if not os
.path
.exists(build_dir
):
489 os
.makedirs(build_dir
)
494 '--target=%s' % self
.config
.target_combo
,
495 '--prefix=' + prefix
,
496 '--with-sysroot=' + prefix
,
499 if os
.path
.exists('/opt/local/include/gmp.h'):
500 cmd
+= ('--with-gmp=/opt/local',)
501 if module
== 'gcc': cmd
+= ('--oldincludedir=/opt/local/include',)
502 cmd
+= self
.source_files
.GetAdditionalParameters(module
, 'configure')
503 self
.RunCommand(cmd
, module
, 'config', skipable
=True)
508 self
.RunCommand(cmd
, module
, 'build')
512 cmd
+= ('install-gcc',)
515 self
.RunCommand(cmd
, module
, 'install')
519 print '%s module is now built and installed' % module
521 def RunCommand(self
, cmd
, module
, stage
, skipable
=False):
523 if self
.IsBuildStepComplete('%s.%s' % (module
, stage
)):
526 popen
= lambda cmd
: \
529 stdin
=subprocess
.PIPE
,
530 stdout
=subprocess
.PIPE
,
531 stderr
=subprocess
.STDOUT
534 print '%s [%s] ...' % (module
, stage
),
537 output
= p
.stdout
.read()
539 if p
.returncode
!= 0:
541 logFile
= os
.path
.join(self
.config
.build_dir
, 'log.txt')
542 f
= open(logFile
, "w")
545 raise Exception, 'Failed to %s %s\n' % (stage
, module
) + \
546 'See output log at %s' % self
.config
.Relative(logFile
)
551 self
.MarkBuildStepComplete('%s.%s' % (module
, stage
))
553 def MakeSymLinks(self
):
554 links_dir
= os
.path
.join(self
.config
.symlinks
, self
.config
.arch
)
555 if not os
.path
.exists(links_dir
):
556 os
.makedirs(links_dir
)
558 for link
in ('ar', 'ld', 'gcc'):
560 self
.config
.prefix
, 'bin', self
.config
.target_combo
+ '-' + link
562 linkdst
= os
.path
.join(links_dir
, link
)
563 if not os
.path
.lexists(linkdst
):
565 print 'Making symlinks in %s:' % self
.config
.Relative(links_dir
),
568 os
.symlink(src
, linkdst
)
576 The main body of the application.
582 if not config
.IsConfigOk():
587 sources
= SourceFiles(config
)
588 result
= sources
.GetAll()
590 print 'All files have been downloaded & verified'
592 print 'An error occured while downloading a file'
595 Extracter(sources
, config
).ExtractAll()
597 Builder(sources
, config
).Build()