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