]> Git Repo - buildroot-mgba.git/blob - utils/genrandconfig
utils/genrandconfig: fix checking host glibc version
[buildroot-mgba.git] / utils / genrandconfig
1 #!/usr/bin/env python3
2
3 # Copyright (C) 2014 by Thomas Petazzoni <[email protected]>
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 2 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 # This script generates a random configuration for testing Buildroot.
20
21 from binascii import hexlify
22 import contextlib
23 import csv
24 import os
25 from random import randint
26 import subprocess
27 import sys
28 from distutils.version import StrictVersion
29 import platform
30
31 if sys.hexversion >= 0x3000000:
32     import urllib.request as _urllib
33 else:
34     import urllib2 as _urllib
35
36
37 def urlopen_closing(uri):
38     return contextlib.closing(_urllib.urlopen(uri))
39
40
41 class SystemInfo:
42     DEFAULT_NEEDED_PROGS = ["make", "git", "gcc", "timeout"]
43     DEFAULT_OPTIONAL_PROGS = ["bzr", "java", "javac", "jar", "diffoscope"]
44
45     def __init__(self):
46         self.needed_progs = list(self.__class__.DEFAULT_NEEDED_PROGS)
47         self.optional_progs = list(self.__class__.DEFAULT_OPTIONAL_PROGS)
48         self.progs = {}
49
50     def find_prog(self, name, flags=os.X_OK, env=os.environ):
51         if not name or name[0] == os.sep:
52             raise ValueError(name)
53
54         prog_path = env.get("PATH", None)
55         # for windows compatibility, we'd need to take PATHEXT into account
56
57         if prog_path:
58             for prog_dir in filter(None, prog_path.split(os.pathsep)):
59                 # os.join() not necessary: non-empty prog_dir
60                 # and name[0] != os.sep
61                 prog = prog_dir + os.sep + name
62                 if os.access(prog, flags):
63                     return prog
64         # --
65         return None
66
67     def has(self, prog):
68         """Checks whether a program is available.
69         Lazily evaluates missing entries.
70
71         Returns: None if prog not found, else path to the program [evaluates
72         to True]
73         """
74         try:
75             return self.progs[prog]
76         except KeyError:
77             pass
78
79         have_it = self.find_prog(prog)
80         # java[c] needs special care
81         if have_it and prog in ('java', 'javac'):
82             with open(os.devnull, "w") as devnull:
83                 if subprocess.call("%s -version | grep gcj" % prog,
84                                    shell=True,
85                                    stdout=devnull, stderr=devnull) != 1:
86                     have_it = False
87         # --
88         self.progs[prog] = have_it
89         return have_it
90
91     def check_requirements(self):
92         """Checks program dependencies.
93
94         Returns: True if all mandatory programs are present, else False.
95         """
96         do_check_has_prog = self.has
97
98         missing_requirements = False
99         for prog in self.needed_progs:
100             if not do_check_has_prog(prog):
101                 print("ERROR: your system lacks the '%s' program" % prog)
102                 missing_requirements = True
103
104         # check optional programs here,
105         # else they'd get checked by each worker instance
106         for prog in self.optional_progs:
107             do_check_has_prog(prog)
108
109         return not missing_requirements
110
111
112 def get_toolchain_configs(toolchains_csv, buildrootdir):
113     """Fetch and return the possible toolchain configurations
114
115     This function returns an array of toolchain configurations. Each
116     toolchain configuration is itself an array of lines of the defconfig.
117     """
118
119     with open(toolchains_csv) as r:
120         # filter empty lines and comments
121         lines = [t for t in r.readlines() if len(t.strip()) > 0 and t[0] != '#']
122         toolchains = lines
123     configs = []
124
125     (_, _, _, _, hostarch) = os.uname()
126     # ~2015 distros report x86 when on a 32bit install
127     if hostarch == 'i686' or hostarch == 'i386' or hostarch == 'x86':
128         hostarch = 'x86'
129
130     for row in csv.reader(toolchains):
131         config = {}
132         configfile = row[0]
133         config_hostarch = row[1]
134         keep = False
135
136         # Keep all toolchain configs that work regardless of the host
137         # architecture
138         if config_hostarch == "any":
139             keep = True
140
141         # Keep all toolchain configs that can work on the current host
142         # architecture
143         if hostarch == config_hostarch:
144             keep = True
145
146         # Assume that x86 32 bits toolchains work on x86_64 build
147         # machines
148         if hostarch == 'x86_64' and config_hostarch == "x86":
149             keep = True
150
151         if not keep:
152             continue
153
154         if not os.path.isabs(configfile):
155             configfile = os.path.join(buildrootdir, configfile)
156
157         with open(configfile) as r:
158             config = r.readlines()
159         configs.append(config)
160     return configs
161
162
163 def is_toolchain_usable(configfile, config):
164     """Check if the toolchain is actually usable."""
165
166     with open(configfile) as configf:
167         configlines = configf.readlines()
168
169     # Check that the toolchain configuration is still present
170     for toolchainline in config:
171         if toolchainline not in configlines:
172             print("WARN: toolchain can't be used", file=sys.stderr)
173             print("      Missing: %s" % toolchainline.strip(), file=sys.stderr)
174             return False
175
176     # The latest Linaro toolchains on x86-64 hosts requires glibc
177     # 2.14+ on the host.
178     if platform.machine() == 'x86_64':
179         if 'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM=y\n' in configlines or \
180            'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64=y\n' in configlines or \
181            'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64_BE=y\n' in configlines or \
182            'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMEB=y\n' in configlines:
183             ldd_version_output = subprocess.check_output(['ldd', '--version'])
184             glibc_version = ldd_version_output.decode().splitlines()[0].split()[-1]
185             if StrictVersion('2.14') > StrictVersion(glibc_version):
186                 print("WARN: ignoring the Linaro ARM toolchains because too old host glibc", file=sys.stderr)
187                 return False
188
189     return True
190
191
192 def fixup_config(sysinfo, configfile):
193     """Finalize the configuration and reject any problematic combinations
194
195     This function returns 'True' when the configuration has been
196     accepted, and 'False' when the configuration has not been accepted because
197     it is known to fail (in which case another random configuration will be
198     generated).
199     """
200
201     with open(configfile) as configf:
202         configlines = configf.readlines()
203
204     ROOTFS_SIZE = '5G'
205
206     BR2_TOOLCHAIN_EXTERNAL_URL = 'BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/'
207
208     if "BR2_NEEDS_HOST_JAVA=y\n" in configlines and not sysinfo.has("java"):
209         return False
210     # The ctng toolchain is affected by PR58854
211     if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
212        BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
213         return False
214     # The ctng toolchain tigger an assembler error with guile package when compiled with -Os (same issue as for CS ARM 2014.05-29)
215     if 'BR2_PACKAGE_GUILE=y\n' in configlines and \
216        'BR2_OPTIMIZE_S=y\n' in configlines and \
217        BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
218         return False
219     # The ctng toolchain is affected by PR58854
220     if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
221        BR2_TOOLCHAIN_EXTERNAL_URL + 'armv6-ctng-linux-uclibcgnueabi.tar.xz"\n' in configlines:
222         return False
223     # The ctng toolchain is affected by PR58854
224     if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
225        BR2_TOOLCHAIN_EXTERNAL_URL + 'armv7-ctng-linux-gnueabihf.tar.xz"\n' in configlines:
226         return False
227     # The ctng toolchain is affected by PR60155
228     if 'BR2_PACKAGE_SDL=y\n' in configlines and \
229        BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
230         return False
231     # The ctng toolchain is affected by PR60155
232     if 'BR2_PACKAGE_LIBMPEG2=y\n' in configlines and \
233        BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
234         return False
235     # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
236     if 'BR2_PACKAGE_STRONGSWAN=y\n' in configlines and \
237        BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
238         return False
239     # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
240     if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
241        BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
242         return False
243     # libffi not available on ARMv7-M, but propagating libffi arch
244     # dependencies in Buildroot is really too much work, so we handle
245     # this here.
246     if 'BR2_ARM_CPU_ARMV7M=y\n' in configlines and \
247        'BR2_PACKAGE_LIBFFI=y\n' in configlines:
248         return False
249     if 'BR2_PACKAGE_SUNXI_BOARDS=y\n' in configlines:
250         configlines.remove('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE=""\n')
251         configlines.append('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a10/hackberry.fex"\n')
252     # This MIPS uClibc toolchain fails to build the gdb package
253     if 'BR2_PACKAGE_GDB=y\n' in configlines and \
254        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
255         return False
256     # This MIPS uClibc toolchain fails to build the rt-tests package
257     if 'BR2_PACKAGE_RT_TESTS=y\n' in configlines and \
258        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
259         return False
260     # This MIPS uClibc toolchain fails to build the civetweb package
261     if 'BR2_PACKAGE_CIVETWEB=y\n' in configlines and \
262        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
263         return False
264     # This MIPS ctng toolchain fails to build the python3 package
265     if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
266        BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
267         return False
268     # This MIPS uClibc toolchain fails to build the strace package
269     if 'BR2_PACKAGE_STRACE=y\n' in configlines and \
270        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
271         return False
272     # This MIPS uClibc toolchain fails to build the cdrkit package
273     if 'BR2_PACKAGE_CDRKIT=y\n' in configlines and \
274        'BR2_STATIC_LIBS=y\n' in configlines and \
275        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
276         return False
277     # uClibc vfork static linking issue
278     if 'BR2_PACKAGE_ALSA_LIB=y\n' in configlines and \
279        'BR2_STATIC_LIBS=y\n' in configlines and \
280        BR2_TOOLCHAIN_EXTERNAL_URL + 'i486-ctng-linux-uclibc.tar.xz"\n' in configlines:
281         return False
282     # This MIPS uClibc toolchain fails to build the weston package
283     if 'BR2_PACKAGE_WESTON=y\n' in configlines and \
284        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
285         return False
286     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
287     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
288        'BR2_PACKAGE_BOOST=y\n' in configlines:
289         return False
290     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
291     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
292        'BR2_PACKAGE_QT5BASE_GUI=y\n' in configlines:
293         return False
294     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
295     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
296        'BR2_PACKAGE_FLANN=y\n' in configlines:
297         return False
298
299     if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE=y\n' in configlines and \
300        'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n' in configlines and \
301        'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\n' in configlines:
302         bootenv = os.path.join(args.outputdir, "boot_env.txt")
303         with open(bootenv, "w+") as bootenvf:
304             bootenvf.write("prop=value")
305         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n')
306         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE="%s"\n' % bootenv)
307         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\n')
308         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE="0x1000"\n')
309
310     if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y\n' in configlines and \
311        'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n' in configlines:
312         bootscr = os.path.join(args.outputdir, "boot_script.txt")
313         with open(bootscr, "w+") as bootscrf:
314             bootscrf.write("prop=value")
315         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n')
316         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="%s"\n' % bootscr)
317
318     if 'BR2_ROOTFS_SKELETON_CUSTOM=y\n' in configlines and \
319        'BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n' in configlines:
320         configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM=y\n')
321         configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n')
322
323     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
324        'BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n' in configlines and \
325        'BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n' in configlines:
326         configlines.remove('BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n')
327         configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
328         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n')
329
330     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
331        'BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n' in configlines and \
332        'BR2_LINUX_KERNEL_DEFCONFIG=""\n' in configlines:
333         configlines.remove('BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n')
334         configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
335         configlines.remove('BR2_LINUX_KERNEL_DEFCONFIG=""\n')
336
337     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
338        'BR2_LINUX_KERNEL_CUSTOM_GIT=y\n' in configlines and \
339        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
340         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_GIT=y\n')
341         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
342         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
343
344     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
345        'BR2_LINUX_KERNEL_CUSTOM_HG=y\n' in configlines and \
346        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
347         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_HG=y\n')
348         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
349         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
350
351     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
352        'BR2_LINUX_KERNEL_CUSTOM_SVN=y\n' in configlines and \
353        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
354         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_SVN=y\n')
355         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
356         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
357
358     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
359        'BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n' in configlines and \
360        'BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
361         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n')
362         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
363         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n')
364
365     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
366        'BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n' in configlines and \
367        'BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n' in configlines:
368         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n')
369         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
370         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n')
371
372     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
373        'BR2_LINUX_KERNEL_DTS_SUPPORT=y\n' in configlines and \
374        'BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n' in configlines and \
375        'BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n' in configlines:
376         configlines.remove('BR2_LINUX_KERNEL_DTS_SUPPORT=y\n')
377         configlines.remove('BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n')
378         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n')
379         if 'BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n' in configlines:
380             configlines.remove('BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n')
381             configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
382         if 'BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n' in configlines:
383             configlines.remove('BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n')
384             configlines.append('BR2_LINUX_KERNEL_ZIMAGE=y\n')
385         if 'BR2_LINUX_KERNEL_CUIMAGE=y\n' in configlines:
386             configlines.remove('BR2_LINUX_KERNEL_CUIMAGE=y\n')
387             configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
388         if 'BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n' in configlines:
389             configlines.remove('BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n')
390             configlines.append('BR2_LINUX_KERNEL_VMLINUX=y\n')
391
392     if 'BR2_LINUX_KERNEL_EXT_AUFS=y\n' in configlines and \
393        'BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n' in configlines:
394         configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS=y\n')
395         configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n')
396
397     if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
398        'BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n' in configlines and \
399        'BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n' in configlines:
400         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
401         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n')
402         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n')
403
404     if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
405        'BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n' in configlines and \
406        'BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n' in configlines:
407         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
408         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n')
409         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n')
410
411     if 'BR2_KERNEL_HEADERS_VERSION=y\n' in configlines and \
412        'BR2_DEFAULT_KERNEL_VERSION=""\n' in configlines:
413         configlines.remove('BR2_KERNEL_HEADERS_VERSION=y\n')
414         configlines.remove('BR2_DEFAULT_KERNEL_VERSION=""\n')
415
416     if 'BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n' in configlines and \
417        'BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n':
418         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n')
419         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n')
420
421     if 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n' in configlines and \
422        'BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
423         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n')
424         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n')
425
426     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
427        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n' in configlines and \
428        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n' in configlines:
429         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n')
430         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
431         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n')
432
433     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
434        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n' in configlines and \
435        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
436         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n')
437         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
438         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n')
439
440     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
441        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n' in configlines and \
442        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n' in configlines:
443         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n')
444         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
445         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n')
446
447     if 'BR2_TARGET_AT91BOOTSTRAP3=y\n' in configlines and \
448        'BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n' in configlines:
449         configlines.remove('BR2_TARGET_AT91BOOTSTRAP3=y\n')
450         configlines.remove('BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n')
451
452     if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
453        'BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n' in configlines and \
454        'BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n' in configlines:
455         configlines.remove('BR2_TARGET_BAREBOX=y\n')
456         configlines.remove('BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n')
457         configlines.remove('BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n')
458
459     if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
460        'BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n' in configlines and \
461        'BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n' in configlines:
462         configlines.remove('BR2_TARGET_BAREBOX=y\n')
463         configlines.remove('BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n')
464         configlines.remove('BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n')
465
466     if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
467        'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n' in configlines and \
468        'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
469         configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n')
470         configlines.append('BR2_TARGET_OPTEE_OS_LATEST=y\n')
471         configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n')
472
473     if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
474        'BR2_TARGET_OPTEE_OS_PLATFORM=""\n' in configlines:
475         configlines.remove('BR2_TARGET_OPTEE_OS=y\n')
476         configlines.remove('BR2_TARGET_OPTEE_OS_PLATFORM=""\n')
477
478     if 'BR2_TARGET_ROOTFS_EXT2=y\n' in configlines and \
479        'BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n' in configlines:
480         configlines.remove('BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n')
481         configlines.append('BR2_TARGET_ROOTFS_EXT2_SIZE="%s"\n' % ROOTFS_SIZE)
482
483     if 'BR2_TARGET_ROOTFS_F2FS=y\n' in configlines and \
484        'BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n' in configlines:
485         configlines.remove('BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n')
486         configlines.append('BR2_TARGET_ROOTFS_F2FS_SIZE="%s"\n' % ROOTFS_SIZE)
487
488     if 'BR2_TARGET_S500_BOOTLOADER=y\n' in configlines and \
489        'BR2_TARGET_S500_BOOTLOADER_BOARD=""\n' in configlines:
490         configlines.remove('BR2_TARGET_S500_BOOTLOADER=y\n')
491         configlines.remove('BR2_TARGET_S500_BOOTLOADER_BOARD=""\n')
492
493     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
494        'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
495        'BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n' in configlines and \
496        'BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n' in configlines:
497         configlines.remove('BR2_TARGET_UBOOT=y\n')
498         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
499         configlines.remove('BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n')
500         configlines.remove('BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n')
501
502     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
503        'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
504        'BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n' in configlines and \
505        'BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n' in configlines:
506         configlines.remove('BR2_TARGET_UBOOT=y\n')
507         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
508         configlines.remove('BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n')
509         configlines.remove('BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n')
510
511     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
512        'BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n' in configlines and \
513        'BR2_TARGET_UBOOT_BOARDNAME=""\n' in configlines:
514         configlines.remove('BR2_TARGET_UBOOT=y\n')
515         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n')
516         configlines.remove('BR2_TARGET_UBOOT_BOARDNAME=""\n')
517
518     if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
519        'BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n' in configlines and \
520        'BR2_TOOLCHAIN_EXTERNAL_PATH=""\n' in configlines:
521         configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
522         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n')
523         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PATH=""\n')
524         if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
525             return False
526
527     if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
528        'BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n' in configlines and \
529        'BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n' in configlines and \
530        'BR2_TOOLCHAIN_EXTERNAL_URL=""\n' in configlines:
531         configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
532         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n')
533         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n')
534         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_URL=""\n')
535         if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
536             return False
537
538     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
539        'BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n' in configlines and \
540        'BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n' in configlines:
541         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n')
542         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
543         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n')
544
545     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
546        'BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n' in configlines and \
547        'BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
548         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n')
549         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
550         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n')
551
552     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
553        'BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n' in configlines and \
554        'BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n' in configlines:
555         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n')
556         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
557         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n')
558
559     if 'BR2_PACKAGE_REFPOLICY=y\n' in configlines and \
560        'BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n' in configlines and \
561        'BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n' in configlines:
562         configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n')
563         configlines.append('BR2_PACKAGE_REFPOLICY_UPSTREAM_VERSION=y\n')
564         configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n')
565
566     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
567        'BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n' in configlines and \
568        'BR2_PACKAGE_XENOMAI_REPOSITORY=""\n' in configlines:
569         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n')
570         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
571         configlines.remove('BR2_PACKAGE_XENOMAI_REPOSITORY=""\n')
572
573     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
574        'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n' in configlines and \
575        'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n' in configlines:
576         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n')
577         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
578         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n')
579
580     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
581        'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n' in configlines and \
582        'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n' in configlines:
583         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n')
584         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
585         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n')
586
587     if 'BR2_PACKAGE_XVISOR=y\n' in configlines and \
588        'BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n' in configlines and \
589        'BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n' in configlines:
590         configlines.remove('BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n')
591         configlines.append('BR2_PACKAGE_XVISOR_USE_DEFCONFIG=y\n')
592         configlines.remove('BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n')
593
594     with open(configfile, "w+") as configf:
595         configf.writelines(configlines)
596
597     return True
598
599
600 def gen_config(args):
601     """Generate a new random configuration
602
603     This function generates the configuration, by choosing a random
604     toolchain configuration and then generating a random selection of
605     packages.
606     """
607
608     sysinfo = SystemInfo()
609
610     if args.toolchains_csv:
611         # Select a random toolchain configuration
612         configs = get_toolchain_configs(args.toolchains_csv, args.buildrootdir)
613
614         i = randint(0, len(configs) - 1)
615         toolchainconfig = configs[i]
616     else:
617         toolchainconfig = []
618
619     configlines = list(toolchainconfig)
620
621     # Combine with the minimal configuration
622     minimalconfigfile = os.path.join(args.buildrootdir,
623                                      'support/config-fragments/minimal.config')
624     with open(minimalconfigfile) as minimalf:
625         configlines += minimalf.readlines()
626
627     # Allow hosts with old certificates to download over https
628     configlines.append("BR2_WGET=\"wget --passive-ftp -nd -t 3 --no-check-certificate\"\n")
629
630     # Per-package folder
631     if randint(0, 15) == 0:
632         configlines.append("BR2_PER_PACKAGE_DIRECTORIES=y\n")
633
634     # Amend the configuration with a few things.
635     if randint(0, 20) == 0:
636         configlines.append("BR2_ENABLE_DEBUG=y\n")
637     if randint(0, 20) == 0:
638         configlines.append("BR2_ENABLE_RUNTIME_DEBUG=y\n")
639     if randint(0, 1) == 0:
640         configlines.append("BR2_INIT_BUSYBOX=y\n")
641     elif randint(0, 15) == 0:
642         configlines.append("BR2_INIT_SYSTEMD=y\n")
643     elif randint(0, 10) == 0:
644         configlines.append("BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y\n")
645     if randint(0, 20) == 0:
646         configlines.append("BR2_STATIC_LIBS=y\n")
647     if randint(0, 20) == 0:
648         configlines.append("BR2_PACKAGE_PYTHON3_PY_ONLY=y\n")
649     if randint(0, 5) == 0:
650         configlines.append("BR2_OPTIMIZE_2=y\n")
651     if randint(0, 4) == 0:
652         configlines.append("BR2_SYSTEM_ENABLE_NLS=y\n")
653     if randint(0, 4) == 0:
654         configlines.append("BR2_FORTIFY_SOURCE_2=y\n")
655
656     # Randomly enable BR2_REPRODUCIBLE 10% of times
657     # also enable tar filesystem images for testing
658     if sysinfo.has("diffoscope") and randint(0, 10) == 0:
659         configlines.append("BR2_REPRODUCIBLE=y\n")
660         configlines.append("BR2_TARGET_ROOTFS_TAR=y\n")
661
662     # Write out the configuration file
663     if not os.path.exists(args.outputdir):
664         os.makedirs(args.outputdir)
665     if args.outputdir == os.path.abspath(os.path.join(args.buildrootdir, "output")):
666         configfile = os.path.join(args.buildrootdir, ".config")
667     else:
668         configfile = os.path.join(args.outputdir, ".config")
669     with open(configfile, "w+") as configf:
670         configf.writelines(configlines)
671
672     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
673                            "olddefconfig"])
674
675     if not is_toolchain_usable(configfile, toolchainconfig):
676         return 2
677
678     # Now, generate the random selection of packages, and fixup
679     # things if needed.
680     # Safe-guard, in case we can not quickly come to a valid
681     # configuration: allow at most 100 (arbitrary) iterations.
682     bounded_loop = 100
683     while True:
684         if bounded_loop == 0:
685             print("ERROR: cannot generate random configuration after 100 iterations",
686                   file=sys.stderr)
687             return 1
688         bounded_loop -= 1
689         make_rand = [
690             "make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
691             "KCONFIG_SEED=0x%s" % hexlify(os.urandom(4)).decode("ascii").upper(),
692             "KCONFIG_PROBABILITY=%d" % randint(1, 20),
693             "randpackageconfig" if args.toolchains_csv else "randconfig"
694         ]
695         subprocess.check_call(make_rand)
696
697         if fixup_config(sysinfo, configfile):
698             break
699
700     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
701                            "olddefconfig"])
702
703     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
704                            "savedefconfig"])
705
706     return subprocess.call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
707                             "dependencies"])
708
709
710 if __name__ == '__main__':
711     import argparse
712     parser = argparse.ArgumentParser(description="Generate a random configuration")
713     parser.add_argument("--outputdir", "-o",
714                         help="Output directory (relative to current directory)",
715                         type=str, default='output')
716     parser.add_argument("--buildrootdir", "-b",
717                         help="Buildroot directory (relative to current directory)",
718                         type=str, default='.')
719
720     toolchains_csv = parser.add_mutually_exclusive_group(required=False)
721     toolchains_csv.add_argument("--toolchains-csv",
722                                 dest="toolchains_csv",
723                                 help="Path of the toolchain configuration file",
724                                 type=str)
725     toolchains_csv.add_argument("--no-toolchains-csv",
726                                 dest="toolchains_csv",
727                                 help="Generate random toolchain configuration",
728                                 action='store_false')
729     parser.set_defaults(toolchains_csv="support/config-fragments/autobuild/toolchain-configs.csv")
730
731     args = parser.parse_args()
732
733     # We need the absolute path to use with O=, because the relative
734     # path to the output directory here is not relative to the
735     # Buildroot sources, but to the current directory.
736     args.outputdir = os.path.abspath(args.outputdir)
737
738     try:
739         ret = gen_config(args)
740     except Exception as e:
741         print(str(e), file=sys.stderr)
742         parser.exit(1)
743     parser.exit(ret)
This page took 0.07275 seconds and 4 git commands to generate.