]>
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',
227 source_files_ia32
= {
228 'gcc': source_files_x64
['gcc'],
231 source_files_ipf
= source_files_x64
.copy()
232 source_files_ipf
['gcc']['configure-params'] = (
233 '--with-gnu-as', '--with-gnu-ld', '--with-newlib',
234 '--verbose', '--disable-libssp', '--disable-nls',
235 '--enable-languages=c,c++'
239 'ia32': [source_files_common
, source_files_ia32
],
240 'x64': [source_files_common
, source_files_x64
],
241 'ipf': [source_files_common
, source_files_ipf
],
244 for arch
in source_files
:
245 mergedSourceFiles
= {}
246 for source_files_dict
in source_files
[arch
]:
247 mergedSourceFiles
.update(source_files_dict
)
248 for downloadItem
in mergedSourceFiles
:
249 fdata
= mergedSourceFiles
[downloadItem
]
250 fdata
['filename'] = fdata
['url'].split('/')[-1]
251 if 'extract-dir' not in fdata
:
252 for ext
in ('.tar.gz', '.tar.bz2', '.zip'):
253 if fdata
['filename'].endswith(ext
):
254 fdata
['extract-dir'] = fdata
['filename'][:-len(ext
)]
256 replaceables
= ('extract-dir', 'filename', 'url')
257 for replaceItem
in fdata
:
258 if replaceItem
in replaceables
: continue
259 if type(fdata
[replaceItem
]) != str: continue
260 for replaceable
in replaceables
:
261 if type(fdata
[replaceable
]) != str: continue
262 if replaceable
in fdata
:
263 fdata
[replaceable
] = \
264 fdata
[replaceable
].replace(
268 source_files
[arch
] = mergedSourceFiles
269 #print 'source_files:', source_files
273 def progress(received
, blockSize
, fileSize
):
274 if fileSize
< 0: return
275 wDots
= (100 * received
* blockSize
) / fileSize
/ 10
276 if wDots
> self
.dots
:
277 for i
in range(wDots
- self
.dots
):
283 for (fname
, fdata
) in self
.source_files
.items():
284 for retries
in range(maxRetries
):
287 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
289 print 'Downloading %s:' % fname
, url
295 if os
.path
.exists(local_file
):
296 md5_pass
= self
.checkHash(fdata
)
300 print '[md5 mismatch]',
305 urllib
.urlretrieve(url
, local_file
, progress
)
308 # BUGBUG: Suggest proxy to user if download fails.
310 # export http_proxy=http://proxyservername.mycompany.com:911
311 # export ftp_proxy=http://proxyservername.mycompany.com:911
313 if not completed
and os
.path
.exists(local_file
):
314 md5_pass
= self
.checkHash(fdata
)
318 print '[md5 mismatch]',
327 print ' Tried to retrieve', url
328 print ' to', local_file
329 print 'Possible fixes:'
330 print '* If you are behind a web-proxy, try setting the',
331 print 'http_proxy environment variable'
332 print '* You can try to download this file separately',
333 print 'and rerun this script'
336 except KeyboardInterrupt:
337 print '[KeyboardInterrupt]'
343 if not completed
: return False
347 def checkHash(self
, fdata
):
348 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
349 expect_md5
= fdata
['md5']
350 data
= open(local_file
).read()
353 return md5sum
.hexdigest().lower() == expect_md5
.lower()
355 def GetModules(self
):
356 return self
.source_files
.keys()
358 def GetFilenameOf(self
, module
):
359 return self
.source_files
[module
]['filename']
361 def GetMd5Of(self
, module
):
362 return self
.source_files
[module
]['md5']
364 def GetExtractDirOf(self
, module
):
365 return self
.source_files
[module
]['extract-dir']
367 def GetAdditionalParameters(self
, module
, step
):
368 key
= step
+ '-params'
369 if key
in self
.source_files
[module
]:
370 return self
.source_files
[module
][key
]
377 Handles the extraction of the source files from their downloaded
381 def __init__(self
, source_files
, config
):
382 self
.source_files
= source_files
385 def Extract(self
, module
):
386 src
= self
.config
.src_dir
387 extractDst
= os
.path
.join(src
, self
.config
.arch
)
388 local_file
= os
.path
.join(src
, self
.source_files
.GetFilenameOf(module
))
389 moduleMd5
= self
.source_files
.GetMd5Of(module
)
390 extracted
= os
.path
.join(extractDst
, os
.path
.split(local_file
)[1] + '.extracted')
391 if not os
.path
.exists(extractDst
):
395 if os
.path
.exists(extracted
):
396 extractedMd5
= open(extracted
).read()
398 if extractedMd5
!= moduleMd5
:
399 print 'Extracting %s:' % self
.config
.Relative(local_file
)
400 tar
= tarfile
.open(local_file
)
401 tar
.extractall(extractDst
)
402 open(extracted
, 'w').write(moduleMd5
)
405 #print 'Previously extracted', self.config.Relative(local_file)
407 def ExtractAll(self
):
408 for module
in self
.source_files
.GetModules():
414 Builds and installs the GCC tool suite.
417 def __init__(self
, source_files
, config
):
418 self
.source_files
= source_files
422 if not self
.config
.options
.skip_binutils
:
423 self
.BuildModule('binutils')
424 if not self
.config
.options
.skip_gcc
:
425 self
.BuildModule('gcc')
428 def IsBuildStepComplete(self
, step
):
432 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
436 def MarkBuildStepComplete(self
, step
):
439 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
445 def BuildModule(self
, module
):
446 base_dir
= os
.getcwd()
447 build_dir
= os
.path
.join(self
.config
.build_dir
, self
.config
.arch
, module
)
448 module_dir
= self
.source_files
.GetExtractDirOf(module
)
449 module_dir
= os
.path
.realpath(os
.path
.join('src', self
.config
.arch
, module_dir
))
450 configure
= os
.path
.join(module_dir
, 'configure')
451 prefix
= self
.config
.prefix
452 if not os
.path
.exists(build_dir
):
453 os
.makedirs(build_dir
)
458 '--target=%s' % self
.config
.target_combo
,
459 '--prefix=' + prefix
,
460 '--with-sysroot=' + prefix
,
463 if os
.path
.exists('/opt/local/include/gmp.h'):
464 cmd
+= ('--with-gmp=/opt/local',)
465 if module
== 'gcc': cmd
+= ('--oldincludedir=/opt/local/include',)
466 cmd
+= self
.source_files
.GetAdditionalParameters(module
, 'configure')
467 self
.RunCommand(cmd
, module
, 'config', skipable
=True)
472 self
.RunCommand(cmd
, module
, 'build')
476 cmd
+= ('install-gcc',)
479 self
.RunCommand(cmd
, module
, 'install')
483 print '%s module is now built and installed' % module
485 def RunCommand(self
, cmd
, module
, stage
, skipable
=False):
487 if self
.IsBuildStepComplete('%s.%s' % (module
, stage
)):
490 popen
= lambda cmd
: \
493 stdin
=subprocess
.PIPE
,
494 stdout
=subprocess
.PIPE
,
495 stderr
=subprocess
.STDOUT
498 print '%s [%s] ...' % (module
, stage
),
501 output
= p
.stdout
.read()
503 if p
.returncode
!= 0:
505 logFile
= os
.path
.join(self
.config
.build_dir
, 'log.txt')
506 f
= open(logFile
, "w")
509 raise Exception, 'Failed to %s %s\n' % (stage
, module
) + \
510 'See output log at %s' % self
.config
.Relative(logFile
)
515 self
.MarkBuildStepComplete('%s.%s' % (module
, stage
))
517 def MakeSymLinks(self
):
518 links_dir
= os
.path
.join(self
.config
.symlinks
, self
.config
.arch
)
519 if not os
.path
.exists(links_dir
):
520 os
.makedirs(links_dir
)
522 for link
in ('ar', 'ld', 'gcc'):
524 self
.config
.prefix
, 'bin', self
.config
.target_combo
+ '-' + link
526 linkdst
= os
.path
.join(links_dir
, link
)
527 if not os
.path
.lexists(linkdst
):
529 print 'Making symlinks in %s:' % self
.config
.Relative(links_dir
),
532 os
.symlink(src
, linkdst
)
540 The main body of the application.
546 if not config
.IsConfigOk():
551 sources
= SourceFiles(config
)
552 result
= sources
.GetAll()
554 print 'All files have been downloaded & verified'
556 print 'An error occured while downloading a file'
559 Extracter(sources
, config
).ExtractAll()
561 Builder(sources
, config
).Build()