]>
git.proxmox.com Git - mirror_edk2.git/blob - BaseTools/gcc/mingw-gcc-build.py
4 # Automation of instructions from:
5 # http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-doc/
6 # howto-build/mingw-w64-howto-build.txt?revision=216&view=markup
9 from optparse
import OptionParser
18 from hashlib
import md5
22 if sys
.version_info
< (2, 5):
24 # This script (and edk2 BaseTools) require Python 2.5 or newer
26 print 'Python version 2.5 or later is required.'
30 # Version and Copyright
32 VersionNumber
= "0.01"
33 __version__
= "%prog Version " + VersionNumber
34 __copyright__
= "Copyright (c) 2008, Intel Corporation. All rights reserved."
39 Stores the configuration options for the rest of the script.
41 Handles the command line options, and allows the code within
42 the script to easily interact with the 'config' requested by
47 self
.base_dir
= os
.getcwd()
48 (self
.options
, self
.args
) = self
.CheckOptions()
51 def CheckOptions(self
):
54 description
=__copyright__
,
56 prog
="mingw-gcc-build",
57 usage
="%prog [options] [target]"
61 action
= "store", type = "string",
64 help = "Processor architecture to build gcc for."
68 action
= "store", type = "string", dest
= "src_dir",
69 default
= os
.path
.join(self
.base_dir
, 'src'),
70 help = "Directory to download/extract binutils/gcc sources"
74 action
= "store", type = "string", dest
= "build_dir",
75 default
= os
.path
.join(self
.base_dir
, 'build'),
76 help = "Directory to download/extract binutils/gcc sources"
80 action
= "store", type = "string", dest
= "prefix",
81 default
= os
.path
.join(self
.base_dir
, 'install'),
82 help = "Prefix to install binutils/gcc into"
86 action
= "store", type = "string", dest
= "symlinks",
87 default
= os
.path
.join(self
.base_dir
, 'symlinks'),
88 help = "Directory to create binutils/gcc symbolic links into."
93 type=None, help="Print verbose messages"
96 (Opt
, Args
) = Parser
.parse_args()
98 self
.arch
= Opt
.arch
.lower()
99 allowedArchs
= ('ia32', 'x64', 'ipf')
100 if self
.arch
not in allowedArchs
:
102 'Please use --arch to specify one of: %s' %
103 ', '.join(allowedArchs
)
105 self
.target_arch
= {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self
.arch
]
106 self
.target_sys
= {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self
.arch
]
107 self
.target_bin
= {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self
.arch
]
108 self
.target_combo
= '-'.join((self
.target_arch
, self
.target_sys
, self
.target_bin
))
112 def __init_dirs__(self
):
113 self
.src_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.src_dir
))
114 self
.build_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.build_dir
))
115 self
.prefix
= os
.path
.realpath(os
.path
.expanduser(self
.options
.prefix
))
116 self
.symlinks
= os
.path
.realpath(os
.path
.expanduser(self
.options
.symlinks
))
118 def IsConfigOk(self
):
120 print "Current directory:"
121 print " ", self
.base_dir
122 print "Sources download/extraction:", self
.Relative(self
.src_dir
)
123 print "Build directory :", self
.Relative(self
.build_dir
)
124 print "Prefix (install) directory :", self
.Relative(self
.prefix
)
125 print "Create symlinks directory :", self
.Relative(self
.symlinks
)
127 answer
= raw_input("Is this configuration ok? (default = no): ")
128 if (answer
.lower() not in ('y', 'yes')):
130 print "Please try using --help and then change the configuration."
133 if self
.arch
.lower() == 'ipf':
135 print 'Please note that the IPF compiler built by this script has'
136 print 'not yet been validated!'
138 answer
= raw_input("Are you sure you want to build it? (default = no): ")
139 if (answer
.lower() not in ('y', 'yes')):
141 print "Please try using --help and then change the configuration."
147 def Relative(self
, path
):
148 if path
.startswith(self
.base_dir
):
149 return '.' + path
[len(self
.base_dir
):]
153 for path
in (self
.src_dir
, self
.build_dir
,self
.prefix
, self
.symlinks
):
154 if not os
.path
.exists(path
):
160 Handles the downloading of source files used by the script.
163 def __init__(self
, config
):
165 self
.source_files
= self
.source_files
[config
.arch
]
167 source_files_common
= {
169 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \
170 'binutils-$version.tar.bz2',
171 'version': '2.18.50.0.5',
172 'md5': 'daee18dbbf0a6ccfc186141bee18bf62',
178 'url': 'http://gcc-ca.internet.bs/releases/' + \
179 'gcc-$version/gcc-$version.tar.bz2',
181 'md5': '197ed8468b38db1d3481c3111691d85b',
184 'url': 'http://downloads.sourceforge.net/project/' + \
185 'mingw-w64/mingw-w64/mingw-w64-snapshot/' + \
186 'mingw-w64-snapshot-$version.tar.bz2',
187 'extract-dir': os
.path
.join('trunk', 'mingw-w64-headers'),
188 'version': '20090419',
189 'md5': '9146ecfabaf172e4cc427b88e8d218c1',
193 source_files_ia32
= {
194 'gcc': source_files_x64
['gcc'],
196 'url': 'http://downloads.sourceforge.net/project/' + \
197 'mingw/MinGW%20Runtime/' + \
198 'Current%20Release_%20mingwrt-$version/' + \
199 'mingwrt-$version-mingw32-src.tar.gz',
200 'extract-dir': 'mingwrt-$version-mingw32',
202 'md5': '7bf0525f158213f3ac990ea68a5ec34d',
206 source_files_ipf
= source_files_x64
.copy()
207 source_files_ipf
['gcc']['configure-params'] = (
208 '--with-gnu-as', '--with-gnu-ld', '--with-newlib',
209 '--verbose', '--disable-libssp', '--disable-nls',
210 '--enable-languages=c,c++'
214 'ia32': [source_files_common
, source_files_ia32
],
215 'x64': [source_files_common
, source_files_x64
],
216 'ipf': [source_files_common
, source_files_ipf
],
219 for arch
in source_files
:
220 mergedSourceFiles
= {}
221 for source_files_dict
in source_files
[arch
]:
222 mergedSourceFiles
.update(source_files_dict
)
223 for downloadItem
in mergedSourceFiles
:
224 fdata
= mergedSourceFiles
[downloadItem
]
225 fdata
['filename'] = fdata
['url'].split('/')[-1]
226 if 'extract-dir' not in fdata
:
227 for ext
in ('.tar.gz', '.tar.bz2', '.zip'):
228 if fdata
['filename'].endswith(ext
):
229 fdata
['extract-dir'] = fdata
['filename'][:-len(ext
)]
231 replaceables
= ('extract-dir', 'filename', 'url')
232 for replaceItem
in fdata
:
233 if replaceItem
in replaceables
: continue
234 if type(fdata
[replaceItem
]) != str: continue
235 for replaceable
in replaceables
:
236 if type(fdata
[replaceable
]) != str: continue
237 if replaceable
in fdata
:
238 fdata
[replaceable
] = \
239 fdata
[replaceable
].replace(
243 source_files
[arch
] = mergedSourceFiles
244 #print 'source_files:', source_files
248 def progress(received
, blockSize
, fileSize
):
249 if fileSize
< 0: return
250 wDots
= (100 * received
* blockSize
) / fileSize
/ 10
251 if wDots
> self
.dots
:
252 for i
in range(wDots
- self
.dots
):
258 for (fname
, fdata
) in self
.source_files
.items():
259 for retries
in range(maxRetries
):
262 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
264 print 'Downloading %s:' % fname
,
270 if os
.path
.exists(local_file
):
271 md5_pass
= self
.checkHash(fdata
)
275 print '[md5 mismatch]',
280 urllib
.urlretrieve(url
, local_file
, progress
)
283 # BUGBUG: Suggest proxy to user if download fails.
285 # export http_proxy=http://proxyservername.mycompany.com:911
286 # export ftp_proxy=http://proxyservername.mycompany.com:911
288 if not completed
and os
.path
.exists(local_file
):
289 md5_pass
= self
.checkHash(fdata
)
293 print '[md5 mismatch]',
302 print ' Tried to retrieve', url
303 print ' to', local_file
304 print 'Possible fixes:'
305 print '* If you are behind a web-proxy, try setting the',
306 print 'http_proxy environment variable'
307 print '* You can try to download this file separately',
308 print 'and rerun this script'
311 except KeyboardInterrupt:
312 print '[KeyboardInterrupt]'
318 if not completed
: return False
322 def checkHash(self
, fdata
):
323 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
324 expect_md5
= fdata
['md5']
325 data
= open(local_file
).read()
328 return md5sum
.hexdigest().lower() == expect_md5
.lower()
330 def GetModules(self
):
331 return self
.source_files
.keys()
333 def GetFilenameOf(self
, module
):
334 return self
.source_files
[module
]['filename']
336 def GetMd5Of(self
, module
):
337 return self
.source_files
[module
]['md5']
339 def GetExtractDirOf(self
, module
):
340 return self
.source_files
[module
]['extract-dir']
342 def GetAdditionalParameters(self
, module
, step
):
343 key
= step
+ '-params'
344 if key
in self
.source_files
[module
]:
345 return self
.source_files
[module
][key
]
352 Handles the extraction of the source files from their downloaded
356 def __init__(self
, source_files
, config
):
357 self
.source_files
= source_files
360 def Extract(self
, module
):
361 src
= self
.config
.src_dir
362 extractDst
= os
.path
.join(src
, self
.config
.arch
)
363 local_file
= os
.path
.join(src
, self
.source_files
.GetFilenameOf(module
))
364 moduleMd5
= self
.source_files
.GetMd5Of(module
)
365 extracted
= os
.path
.join(extractDst
, os
.path
.split(local_file
)[1] + '.extracted')
366 if not os
.path
.exists(extractDst
):
370 if os
.path
.exists(extracted
):
371 extractedMd5
= open(extracted
).read()
373 if extractedMd5
!= moduleMd5
:
374 print 'Extracting %s:' % self
.config
.Relative(local_file
)
375 tar
= tarfile
.open(local_file
)
376 tar
.extractall(extractDst
)
377 open(extracted
, 'w').write(moduleMd5
)
380 #print 'Previously extracted', self.config.Relative(local_file)
382 def ExtractAll(self
):
383 for module
in self
.source_files
.GetModules():
389 Builds and installs the GCC tool suite.
392 def __init__(self
, source_files
, config
):
393 self
.source_files
= source_files
397 self
.BuildModule('binutils')
398 self
.CopyIncludeDirectory()
399 self
.BuildModule('gcc')
402 def IsBuildStepComplete(self
, step
):
406 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
410 def MarkBuildStepComplete(self
, step
):
413 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
418 def CopyIncludeDirectory(self
):
419 linkdst
= os
.path
.join(self
.config
.prefix
, 'mingw')
423 self
.source_files
.GetExtractDirOf('mingw_hdr'),
426 dst_parent
= os
.path
.join(self
.config
.prefix
, self
.config
.target_combo
)
427 dst
= os
.path
.join(dst_parent
, 'include')
428 if not os
.path
.exists(dst
):
429 if not os
.path
.exists(dst_parent
):
430 os
.makedirs(dst_parent
)
431 print 'Copying headers to', self
.config
.Relative(dst
)
432 shutil
.copytree(src
, dst
, True)
433 if not os
.path
.lexists(linkdst
):
434 print 'Making symlink at', self
.config
.Relative(linkdst
)
435 os
.symlink(self
.config
.target_combo
, linkdst
)
437 def BuildModule(self
, module
):
438 base_dir
= os
.getcwd()
439 build_dir
= os
.path
.join(self
.config
.build_dir
, self
.config
.arch
, module
)
440 module_dir
= self
.source_files
.GetExtractDirOf(module
)
441 module_dir
= os
.path
.realpath(os
.path
.join('src', self
.config
.arch
, module_dir
))
442 configure
= os
.path
.join(module_dir
, 'configure')
443 prefix
= self
.config
.prefix
444 if not os
.path
.exists(build_dir
):
445 os
.makedirs(build_dir
)
450 '--target=%s' % self
.config
.target_combo
,
451 '--prefix=' + prefix
,
452 '--with-sysroot=' + prefix
,
455 if os
.path
.exists('/opt/local/include/gmp.h'):
456 cmd
+= ('--with-gmp=/opt/local',)
457 if module
== 'gcc': cmd
+= ('--oldincludedir=/opt/local/include',)
458 cmd
+= self
.source_files
.GetAdditionalParameters(module
, 'configure')
459 self
.RunCommand(cmd
, module
, 'config', skipable
=True)
464 self
.RunCommand(cmd
, module
, 'build')
468 cmd
+= ('install-gcc',)
471 self
.RunCommand(cmd
, module
, 'install')
475 print '%s module is now built and installed' % module
477 def RunCommand(self
, cmd
, module
, stage
, skipable
=False):
479 if self
.IsBuildStepComplete('%s.%s' % (module
, stage
)):
482 popen
= lambda cmd
: \
485 stdin
=subprocess
.PIPE
,
486 stdout
=subprocess
.PIPE
,
487 stderr
=subprocess
.STDOUT
490 print '%s [%s] ...' % (module
, stage
),
493 output
= p
.stdout
.read()
495 if p
.returncode
!= 0:
497 logFile
= os
.path
.join(self
.config
.build_dir
, 'log.txt')
498 f
= open(logFile
, "w")
501 raise Exception, 'Failed to %s %s\n' % (stage
, module
) + \
502 'See output log at %s' % self
.config
.Relative(logFile
)
507 self
.MarkBuildStepComplete('%s.%s' % (module
, stage
))
509 def MakeSymLinks(self
):
510 links_dir
= os
.path
.join(self
.config
.symlinks
, self
.config
.arch
)
511 if not os
.path
.exists(links_dir
):
512 os
.makedirs(links_dir
)
514 for link
in ('ar', 'ld', 'gcc'):
516 self
.config
.prefix
, 'bin', self
.config
.target_combo
+ '-' + link
518 linkdst
= os
.path
.join(links_dir
, link
)
519 if not os
.path
.lexists(linkdst
):
521 print 'Making symlinks in %s:' % self
.config
.Relative(links_dir
),
524 os
.symlink(src
, linkdst
)
532 The main body of the application.
538 if not config
.IsConfigOk():
543 sources
= SourceFiles(config
)
544 result
= sources
.GetAll()
546 print 'All files have been downloaded & verified'
548 print 'An error occured while downloading a file'
551 Extracter(sources
, config
).ExtractAll()
553 Builder(sources
, config
).Build()