]> Git Repo - buildroot-mgba.git/blob - utils/genrandconfig
utils/genrandconfig: add mxs-bootlets custom handling
[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     if 'BR2_PACKAGE_SUNXI_BOARDS=y\n' in configlines:
251         configlines.remove('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE=""\n')
252         configlines.append('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a10/hackberry.fex"\n')
253     # This MIPS uClibc toolchain fails to build the gdb package
254     if 'BR2_PACKAGE_GDB=y\n' in configlines and \
255        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
256         return False
257     # This MIPS uClibc toolchain fails to build the rt-tests package
258     if 'BR2_PACKAGE_RT_TESTS=y\n' in configlines and \
259        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
260         return False
261     # This MIPS uClibc toolchain fails to build the civetweb package
262     if 'BR2_PACKAGE_CIVETWEB=y\n' in configlines and \
263        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
264         return False
265     # This MIPS ctng toolchain fails to build the python3 package
266     if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
267        BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
268         return False
269     # This MIPS uClibc toolchain fails to build the strace package
270     if 'BR2_PACKAGE_STRACE=y\n' in configlines and \
271        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
272         return False
273     # This MIPS uClibc toolchain fails to build the cdrkit package
274     if 'BR2_PACKAGE_CDRKIT=y\n' in configlines and \
275        'BR2_STATIC_LIBS=y\n' in configlines and \
276        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
277         return False
278     # uClibc vfork static linking issue
279     if 'BR2_PACKAGE_ALSA_LIB=y\n' in configlines and \
280        'BR2_STATIC_LIBS=y\n' in configlines and \
281        BR2_TOOLCHAIN_EXTERNAL_URL + 'i486-ctng-linux-uclibc.tar.xz"\n' in configlines:
282         return False
283     # This MIPS uClibc toolchain fails to build the weston package
284     if 'BR2_PACKAGE_WESTON=y\n' in configlines and \
285        BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
286         return False
287     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
288     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
289        'BR2_PACKAGE_BOOST=y\n' in configlines:
290         return False
291     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
292     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
293        'BR2_PACKAGE_QT5BASE_GUI=y\n' in configlines:
294         return False
295     # The cs nios2 2017.02 toolchain is affected by binutils PR19405
296     if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
297        'BR2_PACKAGE_FLANN=y\n' in configlines:
298         return False
299     if 'BR2_PACKAGE_AUFS_UTIL=y\n' in configlines and \
300        'BR2_PACKAGE_AUFS_UTIL_VERSION=""\n' in configlines:
301         return False
302
303     if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE=y\n' in configlines and \
304        'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n' in configlines and \
305        'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\n' in configlines:
306         bootenv = os.path.join(args.outputdir, "boot_env.txt")
307         with open(bootenv, "w+") as bootenvf:
308             bootenvf.write("prop=value")
309         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n')
310         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE="%s"\n' % bootenv)
311         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\n')
312         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE="0x1000"\n')
313
314     if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y\n' in configlines and \
315        'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n' in configlines:
316         bootscr = os.path.join(args.outputdir, "boot_script.txt")
317         with open(bootscr, "w+") as bootscrf:
318             bootscrf.write("prop=value")
319         configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n')
320         configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="%s"\n' % bootscr)
321
322     if 'BR2_ROOTFS_SKELETON_CUSTOM=y\n' in configlines and \
323        'BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n' in configlines:
324         configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM=y\n')
325         configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n')
326
327     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
328        'BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n' in configlines and \
329        'BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n' in configlines:
330         configlines.remove('BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n')
331         configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
332         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n')
333
334     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
335        'BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n' in configlines and \
336        'BR2_LINUX_KERNEL_DEFCONFIG=""\n' in configlines:
337         configlines.remove('BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n')
338         configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
339         configlines.remove('BR2_LINUX_KERNEL_DEFCONFIG=""\n')
340
341     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
342        'BR2_LINUX_KERNEL_CUSTOM_GIT=y\n' in configlines and \
343        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
344         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_GIT=y\n')
345         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
346         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
347
348     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
349        'BR2_LINUX_KERNEL_CUSTOM_HG=y\n' in configlines and \
350        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
351         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_HG=y\n')
352         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
353         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
354
355     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
356        'BR2_LINUX_KERNEL_CUSTOM_SVN=y\n' in configlines and \
357        'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
358         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_SVN=y\n')
359         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
360         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
361
362     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
363        'BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n' in configlines and \
364        'BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
365         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n')
366         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
367         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n')
368
369     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
370        'BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n' in configlines and \
371        'BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n' in configlines:
372         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n')
373         configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
374         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n')
375
376     if 'BR2_LINUX_KERNEL=y\n' in configlines and \
377        'BR2_LINUX_KERNEL_DTS_SUPPORT=y\n' in configlines and \
378        'BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n' in configlines and \
379        'BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n' in configlines:
380         configlines.remove('BR2_LINUX_KERNEL_DTS_SUPPORT=y\n')
381         configlines.remove('BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n')
382         configlines.remove('BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n')
383         if 'BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n' in configlines:
384             configlines.remove('BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n')
385             configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
386         if 'BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n' in configlines:
387             configlines.remove('BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n')
388             configlines.append('BR2_LINUX_KERNEL_ZIMAGE=y\n')
389         if 'BR2_LINUX_KERNEL_CUIMAGE=y\n' in configlines:
390             configlines.remove('BR2_LINUX_KERNEL_CUIMAGE=y\n')
391             configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
392         if 'BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n' in configlines:
393             configlines.remove('BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n')
394             configlines.append('BR2_LINUX_KERNEL_VMLINUX=y\n')
395
396     if 'BR2_LINUX_KERNEL_EXT_AUFS=y\n' in configlines and \
397        'BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n' in configlines:
398         configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS=y\n')
399         configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n')
400
401     if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
402        'BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n' in configlines and \
403        'BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n' in configlines:
404         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
405         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n')
406         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n')
407
408     if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
409        'BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n' in configlines and \
410        'BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n' in configlines:
411         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
412         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n')
413         configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n')
414
415     if 'BR2_KERNEL_HEADERS_VERSION=y\n' in configlines and \
416        'BR2_DEFAULT_KERNEL_VERSION=""\n' in configlines:
417         configlines.remove('BR2_KERNEL_HEADERS_VERSION=y\n')
418         configlines.remove('BR2_DEFAULT_KERNEL_VERSION=""\n')
419
420     if 'BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n' in configlines and \
421        'BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n':
422         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n')
423         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n')
424
425     if 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n' in configlines and \
426        'BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
427         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n')
428         configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n')
429
430     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
431        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_PLATFORM=""\n' in configlines:
432         return False
433
434     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
435        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n' in configlines and \
436        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n' in configlines:
437         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n')
438         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
439         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n')
440
441     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
442        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n' in configlines and \
443        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
444         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n')
445         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
446         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n')
447
448     if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
449        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n' in configlines and \
450        'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n' in configlines:
451         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n')
452         configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
453         configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n')
454
455     if 'BR2_TARGET_AT91BOOTSTRAP3=y\n' in configlines and \
456        'BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n' in configlines:
457         configlines.remove('BR2_TARGET_AT91BOOTSTRAP3=y\n')
458         configlines.remove('BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n')
459
460     if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
461        'BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n' in configlines and \
462        'BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n' in configlines:
463         configlines.remove('BR2_TARGET_BAREBOX=y\n')
464         configlines.remove('BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n')
465         configlines.remove('BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n')
466
467     if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
468        'BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n' in configlines and \
469        'BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n' in configlines:
470         configlines.remove('BR2_TARGET_BAREBOX=y\n')
471         configlines.remove('BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n')
472         configlines.remove('BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n')
473
474     if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
475        'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n' in configlines and \
476        'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
477         configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n')
478         configlines.append('BR2_TARGET_OPTEE_OS_LATEST=y\n')
479         configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n')
480
481     if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
482        'BR2_TARGET_OPTEE_OS_PLATFORM=""\n' in configlines:
483         configlines.remove('BR2_TARGET_OPTEE_OS=y\n')
484         configlines.remove('BR2_TARGET_OPTEE_OS_PLATFORM=""\n')
485
486     if 'BR2_TARGET_ROOTFS_EXT2=y\n' in configlines and \
487        'BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n' in configlines:
488         configlines.remove('BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n')
489         configlines.append('BR2_TARGET_ROOTFS_EXT2_SIZE="%s"\n' % ROOTFS_SIZE)
490
491     if 'BR2_TARGET_ROOTFS_F2FS=y\n' in configlines and \
492        'BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n' in configlines:
493         configlines.remove('BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n')
494         configlines.append('BR2_TARGET_ROOTFS_F2FS_SIZE="%s"\n' % ROOTFS_SIZE)
495
496     if 'BR2_TARGET_S500_BOOTLOADER=y\n' in configlines and \
497        'BR2_TARGET_S500_BOOTLOADER_BOARD=""\n' in configlines:
498         configlines.remove('BR2_TARGET_S500_BOOTLOADER=y\n')
499         configlines.remove('BR2_TARGET_S500_BOOTLOADER_BOARD=""\n')
500
501     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
502        'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
503        'BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n' in configlines and \
504        'BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n' in configlines:
505         configlines.remove('BR2_TARGET_UBOOT=y\n')
506         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
507         configlines.remove('BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n')
508         configlines.remove('BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n')
509
510     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
511        'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
512        'BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n' in configlines and \
513        'BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n' in configlines:
514         configlines.remove('BR2_TARGET_UBOOT=y\n')
515         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
516         configlines.remove('BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n')
517         configlines.remove('BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n')
518
519     if 'BR2_TARGET_UBOOT=y\n' in configlines and \
520        'BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n' in configlines and \
521        'BR2_TARGET_UBOOT_BOARDNAME=""\n' in configlines:
522         configlines.remove('BR2_TARGET_UBOOT=y\n')
523         configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n')
524         configlines.remove('BR2_TARGET_UBOOT_BOARDNAME=""\n')
525
526     if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
527        'BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n' in configlines and \
528        'BR2_TOOLCHAIN_EXTERNAL_PATH=""\n' in configlines:
529         configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
530         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n')
531         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PATH=""\n')
532         if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
533             return False
534
535     if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
536        'BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n' in configlines and \
537        'BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n' in configlines and \
538        'BR2_TOOLCHAIN_EXTERNAL_URL=""\n' in configlines:
539         configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
540         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n')
541         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n')
542         configlines.remove('BR2_TOOLCHAIN_EXTERNAL_URL=""\n')
543         if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
544             return False
545
546     if 'BR2_TARGET_MXS_BOOTLETS=y\n' in configlines and \
547        'BR2_TARGET_MXS_BOOTLETS_CUSTOM_GIT=y\n' in configlines and \
548        'BR2_TARGET_MXS_BOOTLETS_CUSTOM_GIT_URL=""\n' in configlines:
549         configlines.remove('BR2_TARGET_MXS_BOOTLETS_CUSTOM_GIT=y\n')
550         configlines.append('BR2_TARGET_MXS_BOOTLETS_FREESCALE=y\n')
551         configlines.remove('BR2_TARGET_MXS_BOOTLETS_CUSTOM_GIT_URL=""\n')
552
553     if 'BR2_TARGET_MXS_BOOTLETS=y\n' in configlines and \
554        'BR2_TARGET_MXS_BOOTLETS_CUSTOM_TARBALL=y\n' in configlines and \
555        'BR2_TARGET_MXS_BOOTLETS_CUSTOM_TARBALL_URL=""\n' in configlines:
556         configlines.remove('BR2_TARGET_MXS_BOOTLETS_CUSTOM_TARBALL=y\n')
557         configlines.append('BR2_TARGET_MXS_BOOTLETS_FREESCALE=y\n')
558         configlines.remove('BR2_TARGET_MXS_BOOTLETS_CUSTOM_TARBALL_URL=""\n')
559
560     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
561        'BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n' in configlines and \
562        'BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n' in configlines:
563         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n')
564         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
565         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n')
566
567     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
568        'BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n' in configlines and \
569        'BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
570         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n')
571         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
572         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n')
573
574     if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
575        'BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n' in configlines and \
576        'BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n' in configlines:
577         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n')
578         configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
579         configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n')
580
581     if 'BR2_PACKAGE_REFPOLICY=y\n' in configlines and \
582        'BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n' in configlines and \
583        'BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n' in configlines:
584         configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n')
585         configlines.append('BR2_PACKAGE_REFPOLICY_UPSTREAM_VERSION=y\n')
586         configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n')
587
588     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
589        'BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n' in configlines and \
590        'BR2_PACKAGE_XENOMAI_REPOSITORY=""\n' in configlines:
591         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n')
592         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
593         configlines.remove('BR2_PACKAGE_XENOMAI_REPOSITORY=""\n')
594
595     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
596        'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n' in configlines and \
597        'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n' in configlines:
598         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n')
599         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
600         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n')
601
602     if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
603        'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n' in configlines and \
604        'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n' in configlines:
605         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n')
606         configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
607         configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n')
608
609     if 'BR2_PACKAGE_XVISOR=y\n' in configlines and \
610        'BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n' in configlines and \
611        'BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n' in configlines:
612         configlines.remove('BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n')
613         configlines.append('BR2_PACKAGE_XVISOR_USE_DEFCONFIG=y\n')
614         configlines.remove('BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n')
615
616     with open(configfile, "w+") as configf:
617         configf.writelines(configlines)
618
619     return True
620
621
622 def gen_config(args):
623     """Generate a new random configuration
624
625     This function generates the configuration, by choosing a random
626     toolchain configuration and then generating a random selection of
627     packages.
628     """
629
630     sysinfo = SystemInfo()
631
632     if args.toolchains_csv:
633         # Select a random toolchain configuration
634         configs = get_toolchain_configs(args.toolchains_csv, args.buildrootdir)
635
636         i = randint(0, len(configs) - 1)
637         toolchainconfig = configs[i]
638     else:
639         toolchainconfig = []
640
641     configlines = list(toolchainconfig)
642
643     # Combine with the minimal configuration
644     minimalconfigfile = os.path.join(args.buildrootdir,
645                                      'support/config-fragments/minimal.config')
646     with open(minimalconfigfile) as minimalf:
647         configlines += minimalf.readlines()
648
649     # Allow hosts with old certificates to download over https
650     configlines.append("BR2_WGET=\"wget --passive-ftp -nd -t 3 --no-check-certificate\"\n")
651
652     # Per-package folder
653     if randint(0, 15) == 0:
654         configlines.append("BR2_PER_PACKAGE_DIRECTORIES=y\n")
655
656     # Amend the configuration with a few things.
657     if randint(0, 20) == 0:
658         configlines.append("BR2_ENABLE_DEBUG=y\n")
659     if randint(0, 20) == 0:
660         configlines.append("BR2_ENABLE_RUNTIME_DEBUG=y\n")
661     if randint(0, 1) == 0:
662         configlines.append("BR2_INIT_BUSYBOX=y\n")
663     elif randint(0, 15) == 0:
664         configlines.append("BR2_INIT_SYSTEMD=y\n")
665     elif randint(0, 10) == 0:
666         configlines.append("BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y\n")
667     if randint(0, 20) == 0:
668         configlines.append("BR2_STATIC_LIBS=y\n")
669     if randint(0, 20) == 0:
670         configlines.append("BR2_PACKAGE_PYTHON3_PY_ONLY=y\n")
671     if randint(0, 5) == 0:
672         configlines.append("BR2_OPTIMIZE_2=y\n")
673     if randint(0, 4) == 0:
674         configlines.append("BR2_SYSTEM_ENABLE_NLS=y\n")
675     if randint(0, 4) == 0:
676         configlines.append("BR2_FORTIFY_SOURCE_2=y\n")
677
678     # Randomly enable BR2_REPRODUCIBLE 10% of times
679     # also enable tar filesystem images for testing
680     if sysinfo.has("diffoscope") and randint(0, 10) == 0:
681         configlines.append("BR2_REPRODUCIBLE=y\n")
682         configlines.append("BR2_TARGET_ROOTFS_TAR=y\n")
683
684     # Write out the configuration file
685     if not os.path.exists(args.outputdir):
686         os.makedirs(args.outputdir)
687     if args.outputdir == os.path.abspath(os.path.join(args.buildrootdir, "output")):
688         configfile = os.path.join(args.buildrootdir, ".config")
689     else:
690         configfile = os.path.join(args.outputdir, ".config")
691     with open(configfile, "w+") as configf:
692         configf.writelines(configlines)
693
694     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
695                            "olddefconfig"])
696
697     if not is_toolchain_usable(configfile, toolchainconfig):
698         return 2
699
700     # Now, generate the random selection of packages, and fixup
701     # things if needed.
702     # Safe-guard, in case we can not quickly come to a valid
703     # configuration: allow at most 100 (arbitrary) iterations.
704     bounded_loop = 100
705     while True:
706         if bounded_loop == 0:
707             print("ERROR: cannot generate random configuration after 100 iterations",
708                   file=sys.stderr)
709             return 1
710         bounded_loop -= 1
711         make_rand = [
712             "make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
713             "KCONFIG_SEED=0x%s" % hexlify(os.urandom(4)).decode("ascii").upper(),
714             "KCONFIG_PROBABILITY=%d" % randint(1, 20),
715             "randpackageconfig" if args.toolchains_csv else "randconfig"
716         ]
717         subprocess.check_call(make_rand)
718
719         if fixup_config(sysinfo, configfile):
720             break
721
722     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
723                            "olddefconfig"])
724
725     subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
726                            "savedefconfig"])
727
728     return subprocess.call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
729                             "dependencies"])
730
731
732 if __name__ == '__main__':
733     import argparse
734     parser = argparse.ArgumentParser(description="Generate a random configuration")
735     parser.add_argument("--outputdir", "-o",
736                         help="Output directory (relative to current directory)",
737                         type=str, default='output')
738     parser.add_argument("--buildrootdir", "-b",
739                         help="Buildroot directory (relative to current directory)",
740                         type=str, default='.')
741
742     toolchains_csv = parser.add_mutually_exclusive_group(required=False)
743     toolchains_csv.add_argument("--toolchains-csv",
744                                 dest="toolchains_csv",
745                                 help="Path of the toolchain configuration file",
746                                 type=str)
747     toolchains_csv.add_argument("--no-toolchains-csv",
748                                 dest="toolchains_csv",
749                                 help="Generate random toolchain configuration",
750                                 action='store_false')
751     parser.set_defaults(toolchains_csv="support/config-fragments/autobuild/toolchain-configs.csv")
752
753     args = parser.parse_args()
754
755     # We need the absolute path to use with O=, because the relative
756     # path to the output directory here is not relative to the
757     # Buildroot sources, but to the current directory.
758     args.outputdir = os.path.abspath(args.outputdir)
759
760     try:
761         ret = gen_config(args)
762     except Exception:
763         traceback.print_exc()
764         parser.exit(1)
765     parser.exit(ret)
This page took 0.072053 seconds and 4 git commands to generate.