]>
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
23 # Version and Copyright
25 VersionNumber
= "0.01"
26 __version__
= "%prog Version " + VersionNumber
27 __copyright__
= "Copyright (c) 2008, Intel Corporation. All rights reserved."
32 Stores the configuration options for the rest of the script.
34 Handles the command line options, and allows the code within
35 the script to easily interact with the 'config' requested by
40 self
.base_dir
= os
.getcwd()
41 (self
.options
, self
.args
) = self
.CheckOptions()
44 def CheckOptions(self
):
47 description
=__copyright__
,
49 prog
="mingw-gcc-build",
50 usage
="%prog [options] [target]"
54 action
= "store", type = "string",
57 help = "Processor architecture to build gcc for."
61 action
= "store", type = "string", dest
= "src_dir",
62 default
= os
.path
.join(self
.base_dir
, 'src'),
63 help = "Directory to download/extract binutils/gcc sources"
67 action
= "store", type = "string", dest
= "build_dir",
68 default
= os
.path
.join(self
.base_dir
, 'build'),
69 help = "Directory to download/extract binutils/gcc sources"
73 action
= "store", type = "string", dest
= "prefix",
74 default
= os
.path
.join(self
.base_dir
, 'install'),
75 help = "Prefix to install binutils/gcc into"
79 action
= "store", type = "string", dest
= "symlinks",
80 default
= os
.path
.join(self
.base_dir
, 'symlinks'),
81 help = "Directory to create binutils/gcc symbolic links into."
86 type=None, help="Print verbose messages"
89 (Opt
, Args
) = Parser
.parse_args()
91 self
.arch
= Opt
.arch
.lower()
92 allowedArchs
= ('ia32', 'x64', 'ipf')
93 if self
.arch
not in allowedArchs
:
95 'Please use --arch to specify one of: %s' %
96 ', '.join(allowedArchs
)
98 self
.target_arch
= {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self
.arch
]
99 self
.target_sys
= {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self
.arch
]
100 self
.target_bin
= {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self
.arch
]
101 self
.target_combo
= '-'.join((self
.target_arch
, self
.target_sys
, self
.target_bin
))
105 def __init_dirs__(self
):
106 self
.src_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.src_dir
))
107 self
.build_dir
= os
.path
.realpath(os
.path
.expanduser(self
.options
.build_dir
))
108 self
.prefix
= os
.path
.realpath(os
.path
.expanduser(self
.options
.prefix
))
109 self
.symlinks
= os
.path
.realpath(os
.path
.expanduser(self
.options
.symlinks
))
111 def IsConfigOk(self
):
113 print "Current directory:"
114 print " ", self
.base_dir
115 print "Sources download/extraction:", self
.Relative(self
.src_dir
)
116 print "Build directory :", self
.Relative(self
.build_dir
)
117 print "Prefix (install) directory :", self
.Relative(self
.prefix
)
118 print "Create symlinks directory :", self
.Relative(self
.symlinks
)
120 answer
= raw_input("Is this configuration ok? (default = no): ")
121 if (answer
.lower() not in ('y', 'yes')):
123 print "Please try using --help and then change the configuration."
126 if self
.arch
.lower() == 'ipf':
128 print 'Please note that the IPF compiler built by this script has'
129 print 'not yet been validated!'
131 answer
= raw_input("Are you sure you want to build it? (default = no): ")
132 if (answer
.lower() not in ('y', 'yes')):
134 print "Please try using --help and then change the configuration."
140 def Relative(self
, path
):
141 if path
.startswith(self
.base_dir
):
142 return '.' + path
[len(self
.base_dir
):]
146 for path
in (self
.src_dir
, self
.build_dir
,self
.prefix
, self
.symlinks
):
147 if not os
.path
.exists(path
):
153 Handles the downloading of source files used by the script.
156 def __init__(self
, config
):
158 self
.source_files
= self
.source_files
[config
.arch
]
160 source_files_common
= {
162 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \
163 'binutils-$version.tar.bz2',
164 'version': '2.18.50.0.5',
165 'md5': 'daee18dbbf0a6ccfc186141bee18bf62',
171 'url': 'http://gcc-ca.internet.bs/releases/' + \
172 'gcc-$version/gcc-$version.tar.bz2',
174 'md5': '197ed8468b38db1d3481c3111691d85b',
177 'url': 'http://superb-west.dl.sourceforge.net/sourceforge/' + \
178 'mingw-w64/mingw-w64-snapshot-$version.tar.bz2',
179 'extract-dir': os
.path
.join('trunk', 'mingw-w64-headers'),
180 'version': '20080310',
181 'md5': '235b2d15c2411f7d213c0c0977b2162f',
185 source_files_ia32
= {
187 'url': 'http://superb-east.dl.sourceforge.net/sourceforge/' + \
188 'mingw/gcc-$version-mingw-$minor_version-src.tar.gz',
190 'minor_version': 'alpha-20080403',
191 'extract-dir': 'gcc-$version',
192 'md5': '27961d80e304f4ef32c980833c6e8e44',
193 'configure-params': ('--with-gnu-as', '--with-gnu-ld', '--with-newlib',
194 '--verbose', '--disable-libssp', '--disable-nls',
195 '--enable-languages=c,c++'
199 'url': 'http://superb-west.dl.sourceforge.net/sourceforge/' + \
200 'mingw/mingw-runtime-$version-src.tar.gz',
201 'extract-dir': 'mingw-runtime-$version',
203 'md5': '7d049a8331efcfe34600c0cda6934ac6',
207 source_files_ipf
= source_files_x64
.copy()
208 source_files_ipf
['gcc']['configure-params'] = (
209 '--with-gnu-as', '--with-gnu-ld', '--with-newlib',
210 '--verbose', '--disable-libssp', '--disable-nls',
211 '--enable-languages=c,c++'
215 'ia32': [source_files_common
, source_files_ia32
],
216 'x64': [source_files_common
, source_files_x64
],
217 'ipf': [source_files_common
, source_files_ipf
],
220 for arch
in source_files
:
221 mergedSourceFiles
= {}
222 for source_files_dict
in source_files
[arch
]:
223 mergedSourceFiles
.update(source_files_dict
)
224 for downloadItem
in mergedSourceFiles
:
225 fdata
= mergedSourceFiles
[downloadItem
]
226 fdata
['filename'] = fdata
['url'].split('/')[-1]
227 if 'extract-dir' not in fdata
:
228 for ext
in ('.tar.gz', '.tar.bz2', '.zip'):
229 if fdata
['filename'].endswith(ext
):
230 fdata
['extract-dir'] = fdata
['filename'][:-len(ext
)]
232 replaceables
= ('extract-dir', 'filename', 'url')
233 for replaceItem
in fdata
:
234 if replaceItem
in replaceables
: continue
235 if type(fdata
[replaceItem
]) != str: continue
236 for replaceable
in replaceables
:
237 if type(fdata
[replaceable
]) != str: continue
238 if replaceable
in fdata
:
239 fdata
[replaceable
] = \
240 fdata
[replaceable
].replace(
244 source_files
[arch
] = mergedSourceFiles
245 #print 'source_files:', source_files
249 def progress(received
, blockSize
, fileSize
):
250 if fileSize
< 0: return
251 wDots
= (100 * received
* blockSize
) / fileSize
/ 10
252 if wDots
> self
.dots
:
253 for i
in range(wDots
- self
.dots
):
259 for (fname
, fdata
) in self
.source_files
.items():
260 for retries
in range(maxRetries
):
263 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
265 print 'Downloading %s:' % fname
,
271 if os
.path
.exists(local_file
):
272 md5_pass
= self
.checkHash(fdata
)
276 print '[md5 mismatch]',
281 urllib
.urlretrieve(url
, local_file
, progress
)
284 # BUGBUG: Suggest proxy to user if download fails.
286 # export http_proxy=http://proxyservername.mycompany.com:911
287 # export ftp_proxy=http://proxyservername.mycompany.com:911
289 if not completed
and os
.path
.exists(local_file
):
290 md5_pass
= self
.checkHash(fdata
)
294 print '[md5 mismatch]',
305 except KeyboardInterrupt:
306 print '[KeyboardInterrupt]'
312 if not completed
: return False
316 def checkHash(self
, fdata
):
317 local_file
= os
.path
.join(self
.config
.src_dir
, fdata
['filename'])
318 expect_md5
= fdata
['md5']
319 data
= open(local_file
).read()
322 return md5sum
.hexdigest().lower() == expect_md5
.lower()
324 def GetModules(self
):
325 return self
.source_files
.keys()
327 def GetFilenameOf(self
, module
):
328 return self
.source_files
[module
]['filename']
330 def GetMd5Of(self
, module
):
331 return self
.source_files
[module
]['md5']
333 def GetExtractDirOf(self
, module
):
334 return self
.source_files
[module
]['extract-dir']
336 def GetAdditionalParameters(self
, module
, step
):
337 key
= step
+ '-params'
338 if key
in self
.source_files
[module
]:
339 return self
.source_files
[module
][key
]
346 Handles the extraction of the source files from their downloaded
350 def __init__(self
, source_files
, config
):
351 self
.source_files
= source_files
354 def Extract(self
, module
):
355 src
= self
.config
.src_dir
356 extractDst
= os
.path
.join(src
, self
.config
.arch
)
357 local_file
= os
.path
.join(src
, self
.source_files
.GetFilenameOf(module
))
358 moduleMd5
= self
.source_files
.GetMd5Of(module
)
359 extracted
= os
.path
.join(extractDst
, os
.path
.split(local_file
)[1] + '.extracted')
360 if not os
.path
.exists(extractDst
):
364 if os
.path
.exists(extracted
):
365 extractedMd5
= open(extracted
).read()
367 if extractedMd5
!= moduleMd5
:
368 print 'Extracting %s:' % self
.config
.Relative(local_file
)
369 tar
= tarfile
.open(local_file
)
370 tar
.extractall(extractDst
)
371 open(extracted
, 'w').write(moduleMd5
)
374 #print 'Previously extracted', self.config.Relative(local_file)
376 def ExtractAll(self
):
377 for module
in self
.source_files
.GetModules():
383 Builds and installs the GCC tool suite.
386 def __init__(self
, source_files
, config
):
387 self
.source_files
= source_files
391 self
.BuildModule('binutils')
392 self
.CopyIncludeDirectory()
393 self
.BuildModule('gcc')
396 def IsBuildStepComplete(self
, step
):
400 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
404 def MarkBuildStepComplete(self
, step
):
407 self
.config
.build_dir
, self
.config
.arch
, step
+ '.completed'
412 def CopyIncludeDirectory(self
):
413 linkdst
= os
.path
.join(self
.config
.prefix
, 'mingw')
417 self
.source_files
.GetExtractDirOf('mingw_hdr'),
420 dst_parent
= os
.path
.join(self
.config
.prefix
, self
.config
.target_combo
)
421 dst
= os
.path
.join(dst_parent
, 'include')
422 if not os
.path
.exists(dst
):
423 if not os
.path
.exists(dst_parent
):
424 os
.makedirs(dst_parent
)
425 print 'Copying headers to', self
.config
.Relative(dst
)
426 shutil
.copytree(src
, dst
, True)
427 if not os
.path
.lexists(linkdst
):
428 print 'Making symlink at', self
.config
.Relative(linkdst
)
429 os
.symlink(self
.config
.target_combo
, linkdst
)
431 def BuildModule(self
, module
):
432 base_dir
= os
.getcwd()
433 build_dir
= os
.path
.join(self
.config
.build_dir
, self
.config
.arch
, module
)
434 module_dir
= self
.source_files
.GetExtractDirOf(module
)
435 module_dir
= os
.path
.realpath(os
.path
.join('src', self
.config
.arch
, module_dir
))
436 configure
= os
.path
.join(module_dir
, 'configure')
437 prefix
= self
.config
.prefix
438 if not os
.path
.exists(build_dir
):
439 os
.makedirs(build_dir
)
444 '--target=%s' % self
.config
.target_combo
,
445 '--prefix=' + prefix
,
446 '--with-sysroot=' + prefix
,
449 if os
.path
.exists('/opt/local/include/gmp.h'):
450 cmd
+= ('--with-gmp=/opt/local',)
451 if module
== 'gcc': cmd
+= ('--oldincludedir=/opt/local/include',)
452 cmd
+= self
.source_files
.GetAdditionalParameters(module
, 'configure')
453 self
.RunCommand(cmd
, module
, 'config', skipable
=True)
458 self
.RunCommand(cmd
, module
, 'build')
462 cmd
+= ('install-gcc',)
465 self
.RunCommand(cmd
, module
, 'install')
469 print '%s module is now built and installed' % module
471 def RunCommand(self
, cmd
, module
, stage
, skipable
=False):
473 if self
.IsBuildStepComplete('%s.%s' % (module
, stage
)):
476 popen
= lambda cmd
: \
479 stdin
=subprocess
.PIPE
,
480 stdout
=subprocess
.PIPE
,
481 stderr
=subprocess
.STDOUT
484 print '%s [%s] ...' % (module
, stage
),
487 output
= p
.stdout
.read()
489 if p
.returncode
!= 0:
491 logFile
= os
.path
.join(self
.config
.build_dir
, 'log.txt')
492 f
= open(logFile
, "w")
495 raise Exception, 'Failed to %s %s\n' % (stage
, module
) + \
496 'See output log at %s' % self
.config
.Relative(logFile
)
501 self
.MarkBuildStepComplete('%s.%s' % (module
, stage
))
503 def MakeSymLinks(self
):
504 links_dir
= os
.path
.join(self
.config
.symlinks
, self
.config
.arch
)
505 if not os
.path
.exists(links_dir
):
506 os
.makedirs(links_dir
)
508 for link
in ('ar', 'ld', 'gcc'):
510 self
.config
.prefix
, 'bin', self
.config
.target_combo
+ '-' + link
512 linkdst
= os
.path
.join(links_dir
, link
)
513 if not os
.path
.lexists(linkdst
):
515 print 'Making symlinks in %s:' % self
.config
.Relative(links_dir
),
518 os
.symlink(src
, linkdst
)
526 The main body of the application.
532 if not config
.IsConfigOk():
537 sources
= SourceFiles(config
)
538 result
= sources
.GetAll()
540 print 'All files have been downloaded & verified'
542 print 'An error occured while downloading a file'
545 Extracter(sources
, config
).ExtractAll()
547 Builder(sources
, config
).Build()