]>
Commit | Line | Data |
---|---|---|
f7496d71 LG |
1 | #!/usr/bin/env python\r |
2 | \r | |
3 | ## @file\r | |
4 | #\r | |
5 | # Automation of instructions from:\r | |
6 | # http://mingw-w64.svn.sourceforge.net/viewvc/mingw-w64/trunk/mingw-w64-doc/\r | |
7 | # howto-build/mingw-w64-howto-build.txt?revision=216&view=markup\r | |
8 | #\r | |
9 | # Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r | |
10 | # This program and the accompanying materials\r | |
11 | # are licensed and made available under the terms and conditions of the BSD License\r | |
12 | # which accompanies this distribution. The full text of the license may be found at\r | |
13 | # http://opensource.org/licenses/bsd-license.php\r | |
14 | #\r | |
15 | # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
16 | # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
17 | #\r | |
18 | \r | |
19 | \r | |
72443dd2 | 20 | from __future__ import print_function\r |
f7496d71 LG |
21 | from optparse import OptionParser\r |
22 | import os\r | |
23 | import shutil\r | |
24 | import subprocess\r | |
25 | import sys\r | |
26 | import tarfile\r | |
27 | import urllib\r | |
28 | import urlparse\r | |
29 | try:\r | |
30 | from hashlib import md5\r | |
31 | except Exception:\r | |
32 | from md5 import md5\r | |
33 | \r | |
34 | if sys.version_info < (2, 5):\r | |
35 | #\r | |
36 | # This script (and edk2 BaseTools) require Python 2.5 or newer\r | |
37 | #\r | |
72443dd2 | 38 | print('Python version 2.5 or later is required.')\r |
f7496d71 LG |
39 | sys.exit(-1)\r |
40 | \r | |
41 | #\r | |
42 | # Version and Copyright\r | |
43 | #\r | |
44 | VersionNumber = "0.01"\r | |
45 | __version__ = "%prog Version " + VersionNumber\r | |
46 | __copyright__ = "Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved."\r | |
47 | \r | |
48 | class Config:\r | |
49 | """class Config\r | |
50 | \r | |
51 | Stores the configuration options for the rest of the script.\r | |
52 | \r | |
53 | Handles the command line options, and allows the code within\r | |
54 | the script to easily interact with the 'config' requested by\r | |
55 | the user.\r | |
56 | """\r | |
57 | \r | |
58 | def __init__(self):\r | |
59 | self.base_dir = os.getcwd()\r | |
60 | (self.options, self.args) = self.CheckOptions()\r | |
61 | self.__init_dirs__()\r | |
62 | \r | |
63 | def CheckOptions(self):\r | |
64 | Parser = \\r | |
65 | OptionParser(\r | |
66 | description=__copyright__,\r | |
67 | version=__version__,\r | |
68 | prog="mingw-gcc-build",\r | |
69 | usage="%prog [options] [target]"\r | |
70 | )\r | |
71 | Parser.add_option(\r | |
72 | "--arch",\r | |
73 | action = "store", type = "string",\r | |
74 | default = '',\r | |
75 | dest = "arch",\r | |
76 | help = "Processor architecture to build gcc for."\r | |
77 | )\r | |
78 | Parser.add_option(\r | |
79 | "--src-dir",\r | |
80 | action = "store", type = "string", dest = "src_dir",\r | |
81 | default = os.path.join(self.base_dir, 'src'),\r | |
82 | help = "Directory to download/extract binutils/gcc sources"\r | |
83 | )\r | |
84 | Parser.add_option(\r | |
85 | "--build-dir",\r | |
86 | action = "store", type = "string", dest = "build_dir",\r | |
87 | default = os.path.join(self.base_dir, 'build'),\r | |
88 | help = "Directory to download/extract binutils/gcc sources"\r | |
89 | )\r | |
90 | Parser.add_option(\r | |
91 | "--prefix",\r | |
92 | action = "store", type = "string", dest = "prefix",\r | |
93 | default = os.path.join(self.base_dir, 'install'),\r | |
94 | help = "Prefix to install binutils/gcc into"\r | |
95 | )\r | |
96 | Parser.add_option(\r | |
97 | "--skip-binutils",\r | |
98 | action = "store_true", dest = "skip_binutils",\r | |
99 | default = False,\r | |
100 | help = "Will skip building binutils"\r | |
101 | )\r | |
102 | Parser.add_option(\r | |
103 | "--skip-gcc",\r | |
104 | action = "store_true", dest = "skip_gcc",\r | |
105 | default = False,\r | |
106 | help = "Will skip building GCC"\r | |
107 | )\r | |
108 | Parser.add_option(\r | |
109 | "--symlinks",\r | |
110 | action = "store", type = "string", dest = "symlinks",\r | |
111 | default = os.path.join(self.base_dir, 'symlinks'),\r | |
112 | help = "Directory to create binutils/gcc symbolic links into."\r | |
113 | )\r | |
114 | Parser.add_option(\r | |
115 | "-v", "--verbose",\r | |
116 | action="store_true",\r | |
117 | type=None, help="Print verbose messages"\r | |
118 | )\r | |
119 | \r | |
120 | (Opt, Args) = Parser.parse_args()\r | |
121 | \r | |
122 | self.arch = Opt.arch.lower()\r | |
123 | allowedArchs = ('ia32', 'x64', 'ipf')\r | |
124 | if self.arch not in allowedArchs:\r | |
125 | Parser.error(\r | |
126 | 'Please use --arch to specify one of: %s' %\r | |
127 | ', '.join(allowedArchs)\r | |
128 | )\r | |
129 | self.target_arch = {'ia32': 'i686', 'x64': 'x86_64', 'ipf': 'ia64'}[self.arch]\r | |
130 | self.target_sys = {'ia32': 'pc', 'x64': 'pc', 'ipf': 'pc'}[self.arch]\r | |
131 | self.target_bin = {'ia32': 'mingw32', 'x64': 'mingw32', 'ipf': 'elf'}[self.arch]\r | |
132 | self.target_combo = '-'.join((self.target_arch, self.target_sys, self.target_bin))\r | |
133 | \r | |
134 | return (Opt, Args)\r | |
135 | \r | |
136 | def __init_dirs__(self):\r | |
137 | self.src_dir = os.path.realpath(os.path.expanduser(self.options.src_dir))\r | |
138 | self.build_dir = os.path.realpath(os.path.expanduser(self.options.build_dir))\r | |
139 | self.prefix = os.path.realpath(os.path.expanduser(self.options.prefix))\r | |
140 | self.symlinks = os.path.realpath(os.path.expanduser(self.options.symlinks))\r | |
141 | \r | |
142 | def IsConfigOk(self):\r | |
143 | \r | |
144 | building = []\r | |
145 | if not self.options.skip_binutils:\r | |
146 | building.append('binutils')\r | |
147 | if not self.options.skip_gcc:\r | |
148 | building.append('gcc')\r | |
149 | if len(building) == 0:\r | |
72443dd2 GL |
150 | print("Nothing will be built!")\r |
151 | print()\r | |
152 | print("Please try using --help and then change the configuration.")\r | |
f7496d71 LG |
153 | return False\r |
154 | \r | |
72443dd2 GL |
155 | print("Current directory:")\r |
156 | print(" ", self.base_dir)\r | |
157 | print("Sources download/extraction:", self.Relative(self.src_dir))\r | |
158 | print("Build directory :", self.Relative(self.build_dir))\r | |
159 | print("Prefix (install) directory :", self.Relative(self.prefix))\r | |
160 | print("Create symlinks directory :", self.Relative(self.symlinks))\r | |
161 | print("Building :", ', '.join(building))\r | |
162 | print()\r | |
f7496d71 LG |
163 | answer = raw_input("Is this configuration ok? (default = no): ")\r |
164 | if (answer.lower() not in ('y', 'yes')):\r | |
72443dd2 GL |
165 | print()\r |
166 | print("Please try using --help and then change the configuration.")\r | |
f7496d71 LG |
167 | return False\r |
168 | \r | |
169 | if self.arch.lower() == 'ipf':\r | |
72443dd2 GL |
170 | print()\r |
171 | print('Please note that the IPF compiler built by this script has')\r | |
172 | print('not yet been validated!')\r | |
173 | print()\r | |
f7496d71 LG |
174 | answer = raw_input("Are you sure you want to build it? (default = no): ")\r |
175 | if (answer.lower() not in ('y', 'yes')):\r | |
72443dd2 GL |
176 | print()\r |
177 | print("Please try using --help and then change the configuration.")\r | |
f7496d71 LG |
178 | return False\r |
179 | \r | |
72443dd2 | 180 | print()\r |
f7496d71 LG |
181 | return True\r |
182 | \r | |
183 | def Relative(self, path):\r | |
184 | if path.startswith(self.base_dir):\r | |
185 | return '.' + path[len(self.base_dir):]\r | |
186 | return path\r | |
187 | \r | |
188 | def MakeDirs(self):\r | |
ccaa7754 | 189 | for path in (self.src_dir, self.build_dir, self.prefix, self.symlinks):\r |
f7496d71 LG |
190 | if not os.path.exists(path):\r |
191 | os.makedirs(path)\r | |
192 | \r | |
193 | class SourceFiles:\r | |
194 | """class SourceFiles\r | |
195 | \r | |
196 | Handles the downloading of source files used by the script.\r | |
197 | """\r | |
198 | \r | |
199 | def __init__(self, config):\r | |
200 | self.config = config\r | |
201 | self.source_files = self.source_files[config.arch]\r | |
202 | \r | |
203 | if config.options.skip_binutils:\r | |
204 | del self.source_files['binutils']\r | |
205 | \r | |
206 | if config.options.skip_gcc:\r | |
207 | del self.source_files['gcc']\r | |
208 | del self.source_files['mingw_hdr']\r | |
209 | \r | |
210 | source_files_common = {\r | |
211 | 'binutils': {\r | |
212 | 'url': 'http://www.kernel.org/pub/linux/devel/binutils/' + \\r | |
213 | 'binutils-$version.tar.bz2',\r | |
214 | 'version': '2.20.51.0.5',\r | |
215 | 'md5': '6d2de7cdf7a8389e70b124e3d73b4d37',\r | |
216 | },\r | |
217 | }\r | |
218 | \r | |
219 | source_files_x64 = {\r | |
220 | 'gcc': {\r | |
221 | 'url': 'http://ftpmirror.gnu.org/gcc/' + \\r | |
222 | 'gcc-$version/gcc-$version.tar.bz2',\r | |
223 | 'version': '4.3.0',\r | |
224 | 'md5': '197ed8468b38db1d3481c3111691d85b',\r | |
225 | },\r | |
226 | }\r | |
227 | \r | |
228 | source_files_ia32 = {\r | |
229 | 'gcc': source_files_x64['gcc'],\r | |
230 | }\r | |
231 | \r | |
232 | source_files_ipf = source_files_x64.copy()\r | |
233 | source_files_ipf['gcc']['configure-params'] = (\r | |
234 | '--with-gnu-as', '--with-gnu-ld', '--with-newlib',\r | |
235 | '--verbose', '--disable-libssp', '--disable-nls',\r | |
236 | '--enable-languages=c,c++'\r | |
237 | )\r | |
238 | \r | |
239 | source_files = {\r | |
240 | 'ia32': [source_files_common, source_files_ia32],\r | |
241 | 'x64': [source_files_common, source_files_x64],\r | |
242 | 'ipf': [source_files_common, source_files_ipf],\r | |
243 | }\r | |
244 | \r | |
245 | for arch in source_files:\r | |
246 | mergedSourceFiles = {}\r | |
247 | for source_files_dict in source_files[arch]:\r | |
248 | mergedSourceFiles.update(source_files_dict)\r | |
249 | for downloadItem in mergedSourceFiles:\r | |
250 | fdata = mergedSourceFiles[downloadItem]\r | |
251 | fdata['filename'] = fdata['url'].split('/')[-1]\r | |
252 | if 'extract-dir' not in fdata:\r | |
253 | for ext in ('.tar.gz', '.tar.bz2', '.zip'):\r | |
254 | if fdata['filename'].endswith(ext):\r | |
255 | fdata['extract-dir'] = fdata['filename'][:-len(ext)]\r | |
256 | break\r | |
257 | replaceables = ('extract-dir', 'filename', 'url')\r | |
258 | for replaceItem in fdata:\r | |
259 | if replaceItem in replaceables: continue\r | |
0d1f5b2b | 260 | if not isinstance(fdata[replaceItem], str): continue\r |
f7496d71 | 261 | for replaceable in replaceables:\r |
0d1f5b2b | 262 | if not isinstance(fdata[replaceable], str): continue\r |
f7496d71 LG |
263 | if replaceable in fdata:\r |
264 | fdata[replaceable] = \\r | |
265 | fdata[replaceable].replace(\r | |
266 | '$' + replaceItem,\r | |
267 | fdata[replaceItem]\r | |
268 | )\r | |
269 | source_files[arch] = mergedSourceFiles\r | |
270 | #print 'source_files:', source_files\r | |
271 | \r | |
272 | def GetAll(self):\r | |
273 | \r | |
274 | def progress(received, blockSize, fileSize):\r | |
275 | if fileSize < 0: return\r | |
276 | wDots = (100 * received * blockSize) / fileSize / 10\r | |
277 | if wDots > self.dots:\r | |
278 | for i in range(wDots - self.dots):\r | |
72443dd2 | 279 | print('.', end=' ')\r |
f7496d71 LG |
280 | sys.stdout.flush()\r |
281 | self.dots += 1\r | |
282 | \r | |
283 | maxRetries = 1\r | |
284 | for (fname, fdata) in self.source_files.items():\r | |
285 | for retries in range(maxRetries):\r | |
286 | try:\r | |
287 | self.dots = 0\r | |
288 | local_file = os.path.join(self.config.src_dir, fdata['filename'])\r | |
289 | url = fdata['url']\r | |
72443dd2 | 290 | print('Downloading %s:' % fname, url)\r |
f7496d71 | 291 | if retries > 0:\r |
72443dd2 | 292 | print('(retry)', end=' ')\r |
f7496d71 LG |
293 | sys.stdout.flush()\r |
294 | \r | |
295 | completed = False\r | |
296 | if os.path.exists(local_file):\r | |
297 | md5_pass = self.checkHash(fdata)\r | |
298 | if md5_pass:\r | |
72443dd2 | 299 | print('[md5 match]', end=' ')\r |
f7496d71 | 300 | else:\r |
72443dd2 | 301 | print('[md5 mismatch]', end=' ')\r |
f7496d71 LG |
302 | sys.stdout.flush()\r |
303 | completed = md5_pass\r | |
304 | \r | |
305 | if not completed:\r | |
306 | urllib.urlretrieve(url, local_file, progress)\r | |
307 | \r | |
308 | #\r | |
309 | # BUGBUG: Suggest proxy to user if download fails.\r | |
310 | #\r | |
311 | # export http_proxy=http://proxyservername.mycompany.com:911\r | |
312 | # export ftp_proxy=http://proxyservername.mycompany.com:911\r | |
313 | \r | |
314 | if not completed and os.path.exists(local_file):\r | |
315 | md5_pass = self.checkHash(fdata)\r | |
316 | if md5_pass:\r | |
72443dd2 | 317 | print('[md5 match]', end=' ')\r |
f7496d71 | 318 | else:\r |
72443dd2 | 319 | print('[md5 mismatch]', end=' ')\r |
f7496d71 LG |
320 | sys.stdout.flush()\r |
321 | completed = md5_pass\r | |
322 | \r | |
323 | if completed:\r | |
72443dd2 | 324 | print('[done]')\r |
f7496d71 LG |
325 | break\r |
326 | else:\r | |
72443dd2 GL |
327 | print('[failed]')\r |
328 | print(' Tried to retrieve', url)\r | |
329 | print(' to', local_file)\r | |
330 | print('Possible fixes:')\r | |
331 | print('* If you are behind a web-proxy, try setting the', end=' ')\r | |
332 | print('http_proxy environment variable')\r | |
333 | print('* You can try to download this file separately', end=' ')\r | |
334 | print('and rerun this script')\r | |
f7496d71 LG |
335 | raise Exception()\r |
336 | \r | |
337 | except KeyboardInterrupt:\r | |
72443dd2 | 338 | print('[KeyboardInterrupt]')\r |
f7496d71 LG |
339 | return False\r |
340 | \r | |
5b0671c1 | 341 | except Exception as e:\r |
72443dd2 | 342 | print(e)\r |
f7496d71 LG |
343 | \r |
344 | if not completed: return False\r | |
345 | \r | |
346 | return True\r | |
347 | \r | |
348 | def checkHash(self, fdata):\r | |
349 | local_file = os.path.join(self.config.src_dir, fdata['filename'])\r | |
350 | expect_md5 = fdata['md5']\r | |
351 | data = open(local_file).read()\r | |
352 | md5sum = md5()\r | |
353 | md5sum.update(data)\r | |
354 | return md5sum.hexdigest().lower() == expect_md5.lower()\r | |
355 | \r | |
356 | def GetModules(self):\r | |
357 | return self.source_files.keys()\r | |
358 | \r | |
359 | def GetFilenameOf(self, module):\r | |
360 | return self.source_files[module]['filename']\r | |
361 | \r | |
362 | def GetMd5Of(self, module):\r | |
363 | return self.source_files[module]['md5']\r | |
364 | \r | |
365 | def GetExtractDirOf(self, module):\r | |
366 | return self.source_files[module]['extract-dir']\r | |
367 | \r | |
368 | def GetAdditionalParameters(self, module, step):\r | |
369 | key = step + '-params'\r | |
370 | if key in self.source_files[module]:\r | |
371 | return self.source_files[module][key]\r | |
372 | else:\r | |
373 | return tuple()\r | |
374 | \r | |
375 | class Extracter:\r | |
376 | """class Extracter\r | |
377 | \r | |
378 | Handles the extraction of the source files from their downloaded\r | |
379 | archive files.\r | |
380 | """\r | |
381 | \r | |
382 | def __init__(self, source_files, config):\r | |
383 | self.source_files = source_files\r | |
384 | self.config = config\r | |
385 | \r | |
386 | def Extract(self, module):\r | |
387 | src = self.config.src_dir\r | |
388 | extractDst = os.path.join(src, self.config.arch)\r | |
389 | local_file = os.path.join(src, self.source_files.GetFilenameOf(module))\r | |
390 | moduleMd5 = self.source_files.GetMd5Of(module)\r | |
391 | extracted = os.path.join(extractDst, os.path.split(local_file)[1] + '.extracted')\r | |
392 | if not os.path.exists(extractDst):\r | |
393 | os.mkdir(extractDst)\r | |
394 | \r | |
395 | extractedMd5 = None\r | |
396 | if os.path.exists(extracted):\r | |
397 | extractedMd5 = open(extracted).read()\r | |
398 | \r | |
399 | if extractedMd5 != moduleMd5:\r | |
72443dd2 | 400 | print('Extracting %s:' % self.config.Relative(local_file))\r |
f7496d71 LG |
401 | tar = tarfile.open(local_file)\r |
402 | tar.extractall(extractDst)\r | |
403 | open(extracted, 'w').write(moduleMd5)\r | |
404 | else:\r | |
405 | pass\r | |
406 | #print 'Previously extracted', self.config.Relative(local_file)\r | |
407 | \r | |
408 | def ExtractAll(self):\r | |
409 | for module in self.source_files.GetModules():\r | |
410 | self.Extract(module)\r | |
411 | \r | |
412 | class Builder:\r | |
413 | """class Builder\r | |
414 | \r | |
415 | Builds and installs the GCC tool suite.\r | |
416 | """\r | |
417 | \r | |
418 | def __init__(self, source_files, config):\r | |
419 | self.source_files = source_files\r | |
420 | self.config = config\r | |
421 | \r | |
422 | def Build(self):\r | |
423 | if not self.config.options.skip_binutils:\r | |
424 | self.BuildModule('binutils')\r | |
425 | if not self.config.options.skip_gcc:\r | |
426 | self.BuildModule('gcc')\r | |
427 | self.MakeSymLinks()\r | |
428 | \r | |
429 | def IsBuildStepComplete(self, step):\r | |
430 | return \\r | |
431 | os.path.exists(\r | |
432 | os.path.join(\r | |
433 | self.config.build_dir, self.config.arch, step + '.completed'\r | |
434 | )\r | |
435 | )\r | |
436 | \r | |
437 | def MarkBuildStepComplete(self, step):\r | |
438 | open(\r | |
439 | os.path.join(\r | |
440 | self.config.build_dir, self.config.arch, step + '.completed'\r | |
441 | ),\r | |
442 | "w"\r | |
443 | ).close()\r | |
444 | \r | |
445 | \r | |
446 | def BuildModule(self, module):\r | |
447 | base_dir = os.getcwd()\r | |
448 | build_dir = os.path.join(self.config.build_dir, self.config.arch, module)\r | |
449 | module_dir = self.source_files.GetExtractDirOf(module)\r | |
450 | module_dir = os.path.realpath(os.path.join('src', self.config.arch, module_dir))\r | |
451 | configure = os.path.join(module_dir, 'configure')\r | |
452 | prefix = self.config.prefix\r | |
453 | if not os.path.exists(build_dir):\r | |
454 | os.makedirs(build_dir)\r | |
455 | os.chdir(build_dir)\r | |
456 | \r | |
457 | cmd = (\r | |
458 | configure,\r | |
459 | '--target=%s' % self.config.target_combo,\r | |
460 | '--prefix=' + prefix,\r | |
461 | '--with-sysroot=' + prefix,\r | |
462 | '--disable-werror',\r | |
463 | )\r | |
464 | if os.path.exists('/opt/local/include/gmp.h'):\r | |
465 | cmd += ('--with-gmp=/opt/local',)\r | |
466 | if module == 'gcc': cmd += ('--oldincludedir=/opt/local/include',)\r | |
467 | cmd += self.source_files.GetAdditionalParameters(module, 'configure')\r | |
468 | self.RunCommand(cmd, module, 'config', skipable=True)\r | |
469 | \r | |
470 | cmd = ('make',)\r | |
471 | if module == 'gcc':\r | |
472 | cmd += ('all-gcc',)\r | |
473 | self.RunCommand(cmd, module, 'build')\r | |
474 | \r | |
475 | cmd = ('make',)\r | |
476 | if module == 'gcc':\r | |
477 | cmd += ('install-gcc',)\r | |
478 | else:\r | |
479 | cmd += ('install',)\r | |
480 | self.RunCommand(cmd, module, 'install')\r | |
481 | \r | |
482 | os.chdir(base_dir)\r | |
483 | \r | |
72443dd2 | 484 | print('%s module is now built and installed' % module)\r |
f7496d71 LG |
485 | \r |
486 | def RunCommand(self, cmd, module, stage, skipable=False):\r | |
487 | if skipable:\r | |
488 | if self.IsBuildStepComplete('%s.%s' % (module, stage)):\r | |
489 | return\r | |
490 | \r | |
491 | popen = lambda cmd: \\r | |
492 | subprocess.Popen(\r | |
493 | cmd,\r | |
494 | stdin=subprocess.PIPE,\r | |
495 | stdout=subprocess.PIPE,\r | |
496 | stderr=subprocess.STDOUT\r | |
497 | )\r | |
498 | \r | |
72443dd2 | 499 | print('%s [%s] ...' % (module, stage), end=' ')\r |
f7496d71 LG |
500 | sys.stdout.flush()\r |
501 | p = popen(cmd)\r | |
502 | output = p.stdout.read()\r | |
503 | p.wait()\r | |
504 | if p.returncode != 0:\r | |
72443dd2 | 505 | print('[failed!]')\r |
f7496d71 LG |
506 | logFile = os.path.join(self.config.build_dir, 'log.txt')\r |
507 | f = open(logFile, "w")\r | |
508 | f.write(output)\r | |
509 | f.close()\r | |
df29fd13 GL |
510 | raise Exception('Failed to %s %s\n' % (stage, module) + \\r |
511 | 'See output log at %s' % self.config.Relative(logFile))\r | |
f7496d71 | 512 | else:\r |
72443dd2 | 513 | print('[done]')\r |
f7496d71 LG |
514 | \r |
515 | if skipable:\r | |
516 | self.MarkBuildStepComplete('%s.%s' % (module, stage))\r | |
517 | \r | |
518 | def MakeSymLinks(self):\r | |
519 | links_dir = os.path.join(self.config.symlinks, self.config.arch)\r | |
520 | if not os.path.exists(links_dir):\r | |
521 | os.makedirs(links_dir)\r | |
522 | startPrinted = False\r | |
523 | for link in ('ar', 'ld', 'gcc'):\r | |
524 | src = os.path.join(\r | |
525 | self.config.prefix, 'bin', self.config.target_combo + '-' + link\r | |
526 | )\r | |
527 | linkdst = os.path.join(links_dir, link)\r | |
528 | if not os.path.lexists(linkdst):\r | |
529 | if not startPrinted:\r | |
72443dd2 | 530 | print('Making symlinks in %s:' % self.config.Relative(links_dir), end=' ')\r |
f7496d71 | 531 | startPrinted = True\r |
72443dd2 | 532 | print(link, end=' ')\r |
f7496d71 LG |
533 | os.symlink(src, linkdst)\r |
534 | \r | |
535 | if startPrinted:\r | |
72443dd2 | 536 | print('[done]')\r |
f7496d71 LG |
537 | \r |
538 | class App:\r | |
539 | """class App\r | |
540 | \r | |
541 | The main body of the application.\r | |
542 | """\r | |
543 | \r | |
544 | def __init__(self):\r | |
545 | config = Config()\r | |
546 | \r | |
547 | if not config.IsConfigOk():\r | |
548 | return\r | |
549 | \r | |
550 | config.MakeDirs()\r | |
551 | \r | |
552 | sources = SourceFiles(config)\r | |
553 | result = sources.GetAll()\r | |
554 | if result:\r | |
72443dd2 | 555 | print('All files have been downloaded & verified')\r |
f7496d71 | 556 | else:\r |
72443dd2 | 557 | print('An error occured while downloading a file')\r |
f7496d71 LG |
558 | return\r |
559 | \r | |
560 | Extracter(sources, config).ExtractAll()\r | |
561 | \r | |
562 | Builder(sources, config).Build()\r | |
563 | \r | |
564 | App()\r | |
565 | \r |