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