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