1#!/usr/bin/env python3
2
3import os.path
4import re
5import requests
6import textwrap
7import sys
8
9BASE_URL = "https://toolchains.bootlin.com/downloads/releases/toolchains"
10
11AUTOGENERATED_COMMENT = """# This file was auto-generated by support/scripts/gen-bootlin-toolchains
12# Do not edit
13"""
14
15# In the below dict:
16
17# - 'conditions' indicate the cumulative conditions under which the
18#   toolchain will be made available. In several situations, a given
19#   toolchain is usable on several architectures variants (for
20#   example, an ARMv6 toolchain can be used on ARMv7)
21# - 'test_options' indicate one specific configuration where the
22#   toolchain can be used. It is used to create the runtime test
23#   cases. If 'test_options' does not exist, the code assumes it can
24#   be made equal to 'conditions'
25# - 'prefix' is the prefix of the cross-compilation toolchain tools
26
27arches = {
28    'aarch64': {
29        'conditions': ['BR2_aarch64'],
30        'prefix': 'aarch64',
31    },
32    'aarch64be': {
33        'conditions': ['BR2_aarch64_be'],
34        'prefix': 'aarch64_be',
35    },
36    'arcle-750d': {
37        'conditions': ['BR2_arcle', 'BR2_arc750d'],
38        'prefix': 'arc',
39    },
40    'arcle-hs38': {
41        'conditions': ['BR2_arcle', 'BR2_archs38'],
42        'prefix': 'arc',
43    },
44    'armv5-eabi': {
45        'conditions': ['BR2_arm', 'BR2_ARM_CPU_ARMV5', 'BR2_ARM_EABI'],
46        'test_options': ['BR2_arm', 'BR2_arm926t', 'BR2_ARM_EABI'],
47        'prefix': 'arm',
48    },
49    'armv6-eabihf': {
50        'conditions': ['BR2_arm', 'BR2_ARM_CPU_ARMV6', 'BR2_ARM_EABIHF'],
51        'test_options': ['BR2_arm', 'BR2_arm1176jzf_s', 'BR2_ARM_EABIHF'],
52        'prefix': 'arm',
53    },
54    'armv7-eabihf': {
55        'conditions': ['BR2_arm', 'BR2_ARM_CPU_ARMV7A', 'BR2_ARM_EABIHF'],
56        'test_options': ['BR2_arm', 'BR2_cortex_a8', 'BR2_ARM_EABIHF'],
57        'prefix': 'arm',
58    },
59    'armebv7-eabihf': {
60        'conditions': ['BR2_armeb', 'BR2_ARM_CPU_ARMV7A', 'BR2_ARM_EABIHF'],
61        'test_options': ['BR2_armeb', 'BR2_cortex_a8', 'BR2_ARM_EABIHF'],
62        'prefix': 'armeb',
63    },
64    'armv7m': {
65        'conditions': ['BR2_arm', 'BR2_ARM_CPU_ARMV7M'],
66        'test_options': ['BR2_arm', 'BR2_cortex_m4'],
67        'prefix': 'arm',
68    },
69    'm68k-68xxx': {
70        'conditions': ['BR2_m68k_m68k'],
71        'test_options': ['BR2_m68k', 'BR2_m68k_68040'],
72        'prefix': 'm68k',
73    },
74    'm68k-coldfire': {
75        'conditions': ['BR2_m68k_cf'],
76        'test_options': ['BR2_m68k', 'BR2_m68k_cf5208'],
77        'prefix': 'm68k',
78    },
79    'microblazebe': {
80        'conditions': ['BR2_microblazebe'],
81        'prefix': 'microblaze',
82        'gdbserver': False
83    },
84    'microblazeel': {
85        'conditions': ['BR2_microblazeel'],
86        'prefix': 'microblazeel',
87        'gdbserver': False
88    },
89    'mips32': {
90        # Not sure it could be used by other mips32 variants?
91        'conditions': ['BR2_mips', 'BR2_mips_32', '!BR2_MIPS_SOFT_FLOAT'],
92        'prefix': 'mips',
93    },
94    'mips32el': {
95        # Not sure it could be used by other mips32el variants?
96        'conditions': ['BR2_mipsel', 'BR2_mips_32', '!BR2_MIPS_SOFT_FLOAT'],
97        'prefix': 'mipsel',
98    },
99    'mips32r5el': {
100        'conditions': ['BR2_mipsel', 'BR2_mips_32r5', '!BR2_MIPS_SOFT_FLOAT'],
101        'prefix': 'mipsel',
102    },
103    'mips32r6el': {
104        'conditions': ['BR2_mipsel', 'BR2_mips_32r6', '!BR2_MIPS_SOFT_FLOAT'],
105        'prefix': 'mipsel',
106    },
107    'mips64-n32': {
108        # Not sure it could be used by other mips64 variants?
109        'conditions': ['BR2_mips64', 'BR2_mips_64', 'BR2_MIPS_NABI32', '!BR2_MIPS_SOFT_FLOAT'],
110        'prefix': 'mips64',
111    },
112    'mips64el-n32': {
113        # Not sure it could be used by other mips64el variants?
114        'conditions': ['BR2_mips64el', 'BR2_mips_64', 'BR2_MIPS_NABI32', '!BR2_MIPS_SOFT_FLOAT'],
115        'prefix': 'mips64el',
116    },
117    'mips64r6el-n32': {
118        'conditions': ['BR2_mips64el', 'BR2_mips_64r6', 'BR2_MIPS_NABI32', '!BR2_MIPS_SOFT_FLOAT'],
119        'prefix': 'mips64el',
120    },
121    'nios2': {
122        'conditions': ['BR2_nios2'],
123        'prefix': 'nios2',
124    },
125    'openrisc': {
126        'conditions': ['BR2_or1k'],
127        'prefix': 'or1k',
128        'gdbserver': False,
129    },
130    'powerpc-440fp': {
131        # Not sure it could be used by other powerpc variants?
132        'conditions': ['BR2_powerpc', 'BR2_powerpc_440fp'],
133        'prefix': 'powerpc',
134    },
135    'powerpc-e300c3': {
136        # Not sure it could be used by other powerpc variants?
137        'conditions': ['BR2_powerpc', 'BR2_powerpc_e300c3'],
138        'prefix': 'powerpc',
139    },
140    'powerpc-e500mc': {
141        # Not sure it could be used by other powerpc variants?
142        'conditions': ['BR2_powerpc', 'BR2_powerpc_e500mc'],
143        'prefix': 'powerpc',
144    },
145    'powerpc64-e5500': {
146        'conditions': ['BR2_powerpc64', 'BR2_powerpc_e5500'],
147        'prefix': 'powerpc64',
148    },
149    'powerpc64-e6500': {
150        'conditions': ['BR2_powerpc64', 'BR2_powerpc_e6500'],
151        'prefix': 'powerpc64',
152    },
153    'powerpc64-power8': {
154        'conditions': ['BR2_powerpc64', 'BR2_powerpc_power8'],
155        'prefix': 'powerpc64',
156    },
157    'powerpc64le-power8': {
158        'conditions': ['BR2_powerpc64le', 'BR2_powerpc_power8'],
159        'prefix': 'powerpc64le',
160    },
161    'riscv32-ilp32d': {
162        'conditions': ['BR2_riscv', 'BR2_riscv_g', 'BR2_RISCV_32', 'BR2_RISCV_ABI_ILP32D'],
163        'prefix': 'riscv32',
164    },
165    'riscv64-lp64d': {
166        'conditions': ['BR2_riscv', 'BR2_riscv_g', 'BR2_RISCV_64', 'BR2_RISCV_ABI_LP64D', 'BR2_USE_MMU'],
167        'prefix': 'riscv64',
168    },
169    's390x-z13': {
170        'conditions': ['BR2_s390x', 'BR2_s390x_z13'],
171        'prefix': 's390x',
172    },
173    'sh-sh4': {
174        'conditions': ['BR2_sh', 'BR2_sh4'],
175        'prefix': 'sh4',
176    },
177    'sh-sh4aeb': {
178        'conditions': ['BR2_sh', 'BR2_sh4aeb'],
179        'prefix': 'sh4aeb',
180    },
181    'sparc64': {
182        'conditions': ['BR2_sparc64', 'BR2_sparc_v9'],
183        'prefix': 'sparc64',
184    },
185    'sparcv8': {
186        'conditions': ['BR2_sparc', 'BR2_sparc_v8'],
187        'prefix': 'sparc',
188    },
189    'x86-64': {
190        'conditions': ['BR2_x86_64',
191                       'BR2_X86_CPU_HAS_MMX',
192                       'BR2_X86_CPU_HAS_SSE',
193                       'BR2_X86_CPU_HAS_SSE2'],
194        'test_options': ['BR2_x86_64', 'BR2_x86_x86_64'],
195        'prefix': 'x86_64',
196    },
197    'x86-64-v2': {
198        'conditions': ['BR2_x86_64',
199                       'BR2_X86_CPU_HAS_MMX',
200                       'BR2_X86_CPU_HAS_SSE',
201                       'BR2_X86_CPU_HAS_SSE2',
202                       'BR2_X86_CPU_HAS_SSE3',
203                       'BR2_X86_CPU_HAS_SSSE3',
204                       'BR2_X86_CPU_HAS_SSE4',
205                       'BR2_X86_CPU_HAS_SSE42'],
206        'test_options': ['BR2_x86_64', 'BR2_x86_x86_64_v2'],
207        'prefix': 'x86_64',
208    },
209    'x86-64-v3': {
210        'conditions': ['BR2_x86_64',
211                       'BR2_X86_CPU_HAS_MMX',
212                       'BR2_X86_CPU_HAS_SSE',
213                       'BR2_X86_CPU_HAS_SSE2',
214                       'BR2_X86_CPU_HAS_SSE3',
215                       'BR2_X86_CPU_HAS_SSSE3',
216                       'BR2_X86_CPU_HAS_SSE4',
217                       'BR2_X86_CPU_HAS_SSE42',
218                       'BR2_X86_CPU_HAS_AVX',
219                       'BR2_X86_CPU_HAS_AVX2'],
220        'test_options': ['BR2_x86_64', 'BR2_x86_x86_64_v3'],
221        'prefix': 'x86_64',
222    },
223    'x86-64-v4': {
224        'conditions': ['BR2_x86_64',
225                       'BR2_X86_CPU_HAS_MMX',
226                       'BR2_X86_CPU_HAS_SSE',
227                       'BR2_X86_CPU_HAS_SSE2',
228                       'BR2_X86_CPU_HAS_SSE3',
229                       'BR2_X86_CPU_HAS_SSSE3',
230                       'BR2_X86_CPU_HAS_SSE4',
231                       'BR2_X86_CPU_HAS_SSE42',
232                       'BR2_X86_CPU_HAS_AVX',
233                       'BR2_X86_CPU_HAS_AVX2',
234                       'BR2_X86_CPU_HAS_AVX512'],
235        'test_options': ['BR2_x86_64', 'BR2_x86_x86_64_v4'],
236        'prefix': 'x86_64',
237    },
238    'x86-64-core-i7': {
239        'conditions': ['BR2_x86_64',
240                       'BR2_X86_CPU_HAS_MMX',
241                       'BR2_X86_CPU_HAS_SSE',
242                       'BR2_X86_CPU_HAS_SSE2',
243                       'BR2_X86_CPU_HAS_SSE3',
244                       'BR2_X86_CPU_HAS_SSSE3',
245                       'BR2_X86_CPU_HAS_SSE4',
246                       'BR2_X86_CPU_HAS_SSE42'],
247        'test_options': ['BR2_x86_64', 'BR2_x86_corei7'],
248        'prefix': 'x86_64',
249    },
250    'x86-core2': {
251        'conditions': ['BR2_i386',
252                       'BR2_X86_CPU_HAS_MMX',
253                       'BR2_X86_CPU_HAS_SSE',
254                       'BR2_X86_CPU_HAS_SSE2',
255                       'BR2_X86_CPU_HAS_SSE3',
256                       'BR2_X86_CPU_HAS_SSSE3'],
257        'test_options': ['BR2_i386', 'BR2_x86_core2'],
258        'prefix': 'i686',
259    },
260    'x86-i686': {
261        'conditions': ['BR2_i386',
262                       '!BR2_x86_i486',
263                       '!BR2_x86_i586',
264                       '!BR2_x86_x1000',
265                       '!BR2_x86_pentium_mmx',
266                       '!BR2_x86_geode',
267                       '!BR2_x86_c3',
268                       '!BR2_x86_winchip_c6',
269                       '!BR2_x86_winchip2'],
270        'test_options': ['BR2_i386',
271                         'BR2_x86_i686'],
272        'prefix': 'i686',
273    },
274    'xtensa-lx60': {
275        'conditions': ['BR2_xtensa', 'BR2_XTENSA_CUSTOM', 'BR2_XTENSA_LITTLE_ENDIAN'],
276        'prefix': 'xtensa',
277    },
278}
279
280
281class Toolchain:
282    def __init__(self, arch, libc, variant, version):
283        self.arch = arch
284        self.libc = libc
285        self.variant = variant
286        self.version = version
287        self.fname_prefix = "%s--%s--%s-%s" % (self.arch, self.libc, self.variant, self.version)
288        self.option_name = "BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_%s_%s_%s" % \
289            (self.arch.replace("-", "_").upper(), self.libc.upper(), self.variant.replace("-", "_").upper())
290        self.fragment = requests.get(self.fragment_url).text.split("\n")
291        self.sha256 = requests.get(self.hash_url).text.split(" ")[0]
292
293    @property
294    def tarball_url(self):
295        return os.path.join(BASE_URL, self.arch, "tarballs",
296                            self.fname_prefix + ".tar.bz2")
297
298    @property
299    def hash_url(self):
300        return os.path.join(BASE_URL, self.arch, "tarballs",
301                            self.fname_prefix + ".sha256")
302
303    @property
304    def fragment_url(self):
305        return os.path.join(BASE_URL, self.arch, "fragments",
306                            self.fname_prefix + ".frag")
307
308    def gen_config_in_options(self, f):
309        f.write("config %s\n" % self.option_name)
310        f.write("\tbool \"%s %s %s %s\"\n" %
311                (self.arch, self.libc, self.variant, self.version))
312        depends = []
313        selects = []
314
315        for c in arches[self.arch]['conditions']:
316            depends.append(c)
317
318        if not arches[self.arch].get('gdbserver', True):
319            selects.append("BR2_TOOLCHAIN_EXTERNAL_HAS_NO_GDBSERVER")
320
321        for frag in self.fragment:
322            # libc type
323            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_CUSTOM_UCLIBC"):
324                selects.append("BR2_TOOLCHAIN_EXTERNAL_UCLIBC")
325            elif frag.startswith("BR2_TOOLCHAIN_EXTERNAL_CUSTOM_GLIBC"):
326                # glibc needs mmu support
327                if "BR2_USE_MMU" not in depends:
328                    depends.append("BR2_USE_MMU")
329                selects.append("BR2_TOOLCHAIN_EXTERNAL_GLIBC")
330            elif frag.startswith("BR2_TOOLCHAIN_EXTERNAL_CUSTOM_MUSL"):
331                # musl needs mmu support
332                if "BR2_USE_MMU" not in depends:
333                    depends.append("BR2_USE_MMU")
334                selects.append("BR2_TOOLCHAIN_EXTERNAL_MUSL")
335
336            # gcc version
337            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_GCC_"):
338                m = re.match("^BR2_TOOLCHAIN_EXTERNAL_GCC_([0-9_]*)=y$", frag)
339                assert m, "Cannot get gcc version for toolchain %s" % self.fname_prefix
340                selects.append("BR2_TOOLCHAIN_GCC_AT_LEAST_%s" % m[1])
341                # respect the GCC requirement for the selected CPU/arch tuning
342                depends.append("!BR2_ARCH_NEEDS_GCC_AT_LEAST_%s" % str(int(m[1]) + 1))
343
344            # kernel headers version
345            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_HEADERS_"):
346                m = re.match("^BR2_TOOLCHAIN_EXTERNAL_HEADERS_([0-9_]*)=y$", frag)
347                assert m, "Cannot get kernel headers version for toolchain %s" % self.fname_prefix
348                selects.append("BR2_TOOLCHAIN_HEADERS_AT_LEAST_%s" % m[1])
349
350            # C++
351            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_CXX"):
352                selects.append("BR2_INSTALL_LIBSTDCPP")
353
354            # SSP
355            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_HAS_SSP"):
356                selects.append("BR2_TOOLCHAIN_HAS_SSP")
357
358            # wchar
359            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_WCHAR"):
360                selects.append("BR2_USE_WCHAR")
361
362            # locale
363            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_LOCALE"):
364                # locale implies the availability of wchar
365                selects.append("BR2_USE_WCHAR")
366                selects.append("BR2_ENABLE_LOCALE")
367
368            # thread support
369            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_HAS_THREADS"):
370                selects.append("BR2_TOOLCHAIN_HAS_THREADS")
371
372            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_HAS_THREADS_DEBUG"):
373                selects.append("BR2_TOOLCHAIN_HAS_THREADS_DEBUG")
374
375            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_HAS_THREADS_NPTL"):
376                selects.append("BR2_TOOLCHAIN_HAS_THREADS_NPTL")
377
378            # RPC
379            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_INET_RPC"):
380                selects.append("BR2_TOOLCHAIN_HAS_NATIVE_RPC")
381
382            # D language
383            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_DLANG"):
384                selects.append("BR2_TOOLCHAIN_HAS_DLANG")
385
386            # fortran
387            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_FORTRAN"):
388                selects.append("BR2_TOOLCHAIN_HAS_FORTRAN")
389
390            # OpenMP
391            if frag.startswith("BR2_TOOLCHAIN_EXTERNAL_OPENMP"):
392                selects.append("BR2_TOOLCHAIN_HAS_OPENMP")
393
394        for depend in depends:
395            f.write("\tdepends on %s\n" % depend)
396
397        for select in selects:
398            f.write("\tselect %s\n" % select)
399
400        f.write("\thelp\n")
401
402        desc = "Bootlin toolchain for the %s architecture, using the %s C library. " % \
403            (self.arch, self.libc)
404
405        if self.variant == "stable":
406            desc += "This is a stable version, which means it is using stable and proven versions of gcc, gdb and binutils."
407        else:
408            desc += "This is a bleeding-edge version, which means it is using the latest versions of gcc, gdb and binutils."
409
410        f.write(textwrap.fill(desc, width=62, initial_indent="\t  ", subsequent_indent="\t  ") + "\n")
411        f.write("\n")
412        f.write("\t  https://toolchains.bootlin.com/\n")
413
414        f.write("\n")
415
416    def gen_mk(self, f):
417        f.write("ifeq ($(%s),y)\n" % self.option_name)
418        f.write("TOOLCHAIN_EXTERNAL_BOOTLIN_VERSION = %s\n" % self.version)
419        f.write("TOOLCHAIN_EXTERNAL_BOOTLIN_SOURCE = %s--%s--%s-$(TOOLCHAIN_EXTERNAL_BOOTLIN_VERSION).tar.bz2\n" %
420                (self.arch, self.libc, self.variant))
421        f.write("TOOLCHAIN_EXTERNAL_BOOTLIN_SITE = %s\n" %
422                os.path.join(BASE_URL, self.arch, "tarballs"))
423        f.write("endif\n\n")
424        pass
425
426    def gen_hash(self, f):
427        f.write("# From %s\n" % self.hash_url)
428        f.write("sha256  %s  %s\n" % (self.sha256, os.path.basename(self.tarball_url)))
429
430    def gen_test(self, f):
431        if self.variant == "stable":
432            variant = "Stable"
433        else:
434            variant = "BleedingEdge"
435        testname = "TestExternalToolchainBootlin" + \
436            self.arch.replace("-", "").capitalize() + \
437            self.libc.capitalize() + variant
438        f.write("\n\n")
439        f.write("class %s(TestExternalToolchain):\n" % testname)
440        f.write("    config = \"\"\"\n")
441        if 'test_options' in arches[self.arch]:
442            test_options = arches[self.arch]['test_options']
443        else:
444            test_options = arches[self.arch]['conditions']
445        for opt in test_options:
446            if opt.startswith("!"):
447                f.write("        # %s is not set\n" % opt[1:])
448            else:
449                f.write("        %s=y\n" % opt)
450        f.write("        BR2_TOOLCHAIN_EXTERNAL=y\n")
451        f.write("        BR2_TOOLCHAIN_EXTERNAL_BOOTLIN=y\n")
452        f.write("        %s=y\n" % self.option_name)
453        f.write("        # BR2_TARGET_ROOTFS_TAR is not set\n")
454        f.write("        \"\"\"\n")
455        f.write("    toolchain_prefix = \"%s-linux\"\n" % arches[self.arch]['prefix'])
456        f.write("\n")
457        f.write("    def test_run(self):\n")
458        f.write("        TestExternalToolchain.common_check(self)\n")
459
460    def __repr__(self):
461        return "Toolchain(arch=%s libc=%s variant=%s version=%s, option=%s)" % \
462            (self.arch, self.libc, self.variant, self.version, self.option_name)
463
464
465def get_toolchains():
466    toolchains = list()
467    for arch, details in arches.items():
468        print(arch)
469        url = os.path.join(BASE_URL, arch, "available_toolchains")
470        page = requests.get(url).text
471        fnames = sorted(re.findall(r'<td><a href="(\w[^"]+)"', page))
472        # This dict will allow us to keep only the latest version for
473        # each toolchain.
474        tmp = dict()
475        for fname in fnames:
476            parts = fname.split('--')
477            assert parts[0] == arch, "Arch does not match: %s vs. %s" % (parts[0], arch)
478            libc = parts[1]
479            if parts[2].startswith("stable-"):
480                variant = "stable"
481                version = parts[2][len("stable-"):]
482            elif parts[2].startswith("bleeding-edge-"):
483                variant = "bleeding-edge"
484                version = parts[2][len("bleeding-edge-"):]
485            tmp[(arch, libc, variant)] = version
486
487        if len(tmp) == 0:
488            print("ERROR: no toolchains found for architecture %s" % arch)
489            sys.exit(1)
490
491        toolchains += [Toolchain(k[0], k[1], k[2], v) for k, v in tmp.items()]
492
493    return toolchains
494
495
496def gen_config_in_options(toolchains, fpath):
497    with open(fpath, "w") as f:
498        f.write(AUTOGENERATED_COMMENT)
499
500        f.write("config BR2_TOOLCHAIN_EXTERNAL_BOOTLIN_ARCH_SUPPORTS\n")
501        f.write("\tbool\n")
502        for arch, details in arches.items():
503            conditions = details['conditions'].copy()
504            f.write("\tdefault y if %s\n" % " && ".join(conditions))
505        f.write("\n")
506
507        f.write("if BR2_TOOLCHAIN_EXTERNAL_BOOTLIN\n\n")
508
509        f.write("config BR2_TOOLCHAIN_EXTERNAL_PREFIX\n")
510        f.write("\tdefault \"$(ARCH)-linux\"\n")
511
512        f.write("\n")
513
514        f.write("config BR2_PACKAGE_PROVIDES_TOOLCHAIN_EXTERNAL\n")
515        f.write("\tdefault \"toolchain-external-bootlin\"\n")
516
517        f.write("\n")
518
519        f.write("choice\n")
520        f.write("\tprompt \"Bootlin toolchain variant\"\n")
521
522        for toolchain in toolchains:
523            toolchain.gen_config_in_options(f)
524
525        f.write("endchoice\n")
526        f.write("endif\n")
527
528
529def gen_mk(toolchains, fpath):
530    with open(fpath, "w") as f:
531        f.write("#" * 80 + "\n")
532        f.write("#\n")
533        f.write("# toolchain-external-bootlin\n")
534        f.write("#\n")
535        f.write("#" * 80 + "\n")
536        f.write("\n")
537        f.write(AUTOGENERATED_COMMENT)
538        for toolchain in toolchains:
539            toolchain.gen_mk(f)
540        f.write("$(eval $(toolchain-external-package))\n")
541
542
543def gen_hash(toolchains, fpath):
544    with open(fpath, "w") as f:
545        f.write(AUTOGENERATED_COMMENT)
546        for toolchain in toolchains:
547            toolchain.gen_hash(f)
548
549
550def gen_runtime_test(toolchains, fpath):
551    with open(fpath, "w") as f:
552        f.write(AUTOGENERATED_COMMENT)
553        f.write("from tests.toolchain.test_external import TestExternalToolchain\n")
554        for toolchain in toolchains:
555            toolchain.gen_test(f)
556
557
558def gen_toolchains(toolchains):
559    maindir = "toolchain/toolchain-external/toolchain-external-bootlin"
560    gen_config_in_options(toolchains, os.path.join(maindir, "Config.in.options"))
561    gen_mk(toolchains, os.path.join(maindir, "toolchain-external-bootlin.mk"))
562    gen_hash(toolchains, os.path.join(maindir, "toolchain-external-bootlin.hash"))
563    gen_runtime_test(toolchains,
564                     os.path.join("support", "testing", "tests", "toolchain", "test_external_bootlin.py"))
565
566
567toolchains = get_toolchains()
568gen_toolchains(toolchains)
569