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.
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.
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
19 # This script generates a random configuration for testing Buildroot.
21 from binascii import hexlify
25 from random import randint
29 from distutils.version import StrictVersion
32 if sys.hexversion >= 0x3000000:
33 import urllib.request as _urllib
35 import urllib2 as _urllib
38 def urlopen_closing(uri):
39 return contextlib.closing(_urllib.urlopen(uri))
43 DEFAULT_NEEDED_PROGS = ["make", "git", "gcc", "timeout"]
44 DEFAULT_OPTIONAL_PROGS = ["bzr", "java", "javac", "jar", "diffoscope"]
47 self.needed_progs = list(self.__class__.DEFAULT_NEEDED_PROGS)
48 self.optional_progs = list(self.__class__.DEFAULT_OPTIONAL_PROGS)
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)
55 prog_path = env.get("PATH", None)
56 # for windows compatibility, we'd need to take PATHEXT into account
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):
69 """Checks whether a program is available.
70 Lazily evaluates missing entries.
72 Returns: None if prog not found, else path to the program [evaluates
76 return self.progs[prog]
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,
86 stdout=devnull, stderr=devnull) != 1:
89 self.progs[prog] = have_it
92 def check_requirements(self):
93 """Checks program dependencies.
95 Returns: True if all mandatory programs are present, else False.
97 do_check_has_prog = self.has
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
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)
110 return not missing_requirements
113 def get_toolchain_configs(toolchains_csv, buildrootdir):
114 """Fetch and return the possible toolchain configurations
116 This function returns an array of toolchain configurations. Each
117 toolchain configuration is itself an array of lines of the defconfig.
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] != '#']
126 (_, _, _, _, hostarch) = os.uname()
127 # ~2015 distros report x86 when on a 32bit install
128 if hostarch == 'i686' or hostarch == 'i386' or hostarch == 'x86':
131 for row in csv.reader(toolchains):
134 config_hostarch = row[1]
137 # Keep all toolchain configs that work regardless of the host
139 if config_hostarch == "any":
142 # Keep all toolchain configs that can work on the current host
144 if hostarch == config_hostarch:
147 # Assume that x86 32 bits toolchains work on x86_64 build
149 if hostarch == 'x86_64' and config_hostarch == "x86":
155 if not os.path.isabs(configfile):
156 configfile = os.path.join(buildrootdir, configfile)
158 with open(configfile) as r:
159 config = r.readlines()
160 configs.append(config)
164 def is_toolchain_usable(configfile, config):
165 """Check if the toolchain is actually usable."""
167 with open(configfile) as configf:
168 configlines = configf.readlines()
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)
177 # The latest Linaro toolchains on x86-64 hosts requires glibc
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)
193 def fixup_config(sysinfo, configfile):
194 """Finalize the configuration and reject any problematic combinations
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
202 with open(configfile) as configf:
203 configlines = configf.readlines()
207 BR2_TOOLCHAIN_EXTERNAL_URL = 'BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/'
209 if "BR2_NEEDS_HOST_JAVA=y\n" in configlines and not sysinfo.has("java"):
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:
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:
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:
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:
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:
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:
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:
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:
244 # libffi not available on ARMv7-M, but propagating libffi arch
245 # dependencies in Buildroot is really too much work, so we handle
247 if 'BR2_ARM_CPU_ARMV7M=y\n' in configlines and \
248 'BR2_PACKAGE_LIBFFI=y\n' in configlines:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
299 if 'BR2_PACKAGE_AUFS_UTIL=y\n' in configlines and \
300 'BR2_PACKAGE_AUFS_UTIL_VERSION=""\n' in configlines:
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')
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)
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
430 if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
431 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_PLATFORM=""\n' in configlines:
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')
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')
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')
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')
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')
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')
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')
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')
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)
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)
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')
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')
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')
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')
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:
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:
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')
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')
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')
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')
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')
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')
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')
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')
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')
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')
616 with open(configfile, "w+") as configf:
617 configf.writelines(configlines)
622 def gen_config(args):
623 """Generate a new random configuration
625 This function generates the configuration, by choosing a random
626 toolchain configuration and then generating a random selection of
630 sysinfo = SystemInfo()
632 if args.toolchains_csv:
633 # Select a random toolchain configuration
634 configs = get_toolchain_configs(args.toolchains_csv, args.buildrootdir)
636 i = randint(0, len(configs) - 1)
637 toolchainconfig = configs[i]
641 configlines = list(toolchainconfig)
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()
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")
653 if randint(0, 15) == 0:
654 configlines.append("BR2_PER_PACKAGE_DIRECTORIES=y\n")
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")
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")
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")
690 configfile = os.path.join(args.outputdir, ".config")
691 with open(configfile, "w+") as configf:
692 configf.writelines(configlines)
694 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
697 if not is_toolchain_usable(configfile, toolchainconfig):
700 # Now, generate the random selection of packages, and fixup
702 # Safe-guard, in case we can not quickly come to a valid
703 # configuration: allow at most 100 (arbitrary) iterations.
706 if bounded_loop == 0:
707 print("ERROR: cannot generate random configuration after 100 iterations",
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"
717 subprocess.check_call(make_rand)
719 if fixup_config(sysinfo, configfile):
722 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
725 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
728 return subprocess.call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
732 if __name__ == '__main__':
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='.')
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",
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")
753 args = parser.parse_args()
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)
761 ret = gen_config(args)
763 traceback.print_exc()