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
28 from distutils.version import StrictVersion
31 if sys.hexversion >= 0x3000000:
32 import urllib.request as _urllib
34 import urllib2 as _urllib
37 def urlopen_closing(uri):
38 return contextlib.closing(_urllib.urlopen(uri))
42 DEFAULT_NEEDED_PROGS = ["make", "git", "gcc", "timeout"]
43 DEFAULT_OPTIONAL_PROGS = ["bzr", "java", "javac", "jar", "diffoscope"]
46 self.needed_progs = list(self.__class__.DEFAULT_NEEDED_PROGS)
47 self.optional_progs = list(self.__class__.DEFAULT_OPTIONAL_PROGS)
50 def find_prog(self, name, flags=os.X_OK, env=os.environ):
51 if not name or name[0] == os.sep:
52 raise ValueError(name)
54 prog_path = env.get("PATH", None)
55 # for windows compatibility, we'd need to take PATHEXT into account
58 for prog_dir in filter(None, prog_path.split(os.pathsep)):
59 # os.join() not necessary: non-empty prog_dir
60 # and name[0] != os.sep
61 prog = prog_dir + os.sep + name
62 if os.access(prog, flags):
68 """Checks whether a program is available.
69 Lazily evaluates missing entries.
71 Returns: None if prog not found, else path to the program [evaluates
75 return self.progs[prog]
79 have_it = self.find_prog(prog)
80 # java[c] needs special care
81 if have_it and prog in ('java', 'javac'):
82 with open(os.devnull, "w") as devnull:
83 if subprocess.call("%s -version | grep gcj" % prog,
85 stdout=devnull, stderr=devnull) != 1:
88 self.progs[prog] = have_it
91 def check_requirements(self):
92 """Checks program dependencies.
94 Returns: True if all mandatory programs are present, else False.
96 do_check_has_prog = self.has
98 missing_requirements = False
99 for prog in self.needed_progs:
100 if not do_check_has_prog(prog):
101 print("ERROR: your system lacks the '%s' program" % prog)
102 missing_requirements = True
104 # check optional programs here,
105 # else they'd get checked by each worker instance
106 for prog in self.optional_progs:
107 do_check_has_prog(prog)
109 return not missing_requirements
112 def get_toolchain_configs(toolchains_csv, buildrootdir):
113 """Fetch and return the possible toolchain configurations
115 This function returns an array of toolchain configurations. Each
116 toolchain configuration is itself an array of lines of the defconfig.
119 with open(toolchains_csv) as r:
120 # filter empty lines and comments
121 lines = [t for t in r.readlines() if len(t.strip()) > 0 and t[0] != '#']
125 (_, _, _, _, hostarch) = os.uname()
126 # ~2015 distros report x86 when on a 32bit install
127 if hostarch == 'i686' or hostarch == 'i386' or hostarch == 'x86':
130 for row in csv.reader(toolchains):
133 config_hostarch = row[1]
136 # Keep all toolchain configs that work regardless of the host
138 if config_hostarch == "any":
141 # Keep all toolchain configs that can work on the current host
143 if hostarch == config_hostarch:
146 # Assume that x86 32 bits toolchains work on x86_64 build
148 if hostarch == 'x86_64' and config_hostarch == "x86":
154 if not os.path.isabs(configfile):
155 configfile = os.path.join(buildrootdir, configfile)
157 with open(configfile) as r:
158 config = r.readlines()
159 configs.append(config)
163 def is_toolchain_usable(configfile, config):
164 """Check if the toolchain is actually usable."""
166 with open(configfile) as configf:
167 configlines = configf.readlines()
169 # Check that the toolchain configuration is still present
170 for toolchainline in config:
171 if toolchainline not in configlines:
172 print("WARN: toolchain can't be used", file=sys.stderr)
173 print(" Missing: %s" % toolchainline.strip(), file=sys.stderr)
176 # The latest Linaro toolchains on x86-64 hosts requires glibc
178 if platform.machine() == 'x86_64':
179 if 'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM=y\n' in configlines or \
180 'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64=y\n' in configlines or \
181 'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64_BE=y\n' in configlines or \
182 'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMEB=y\n' in configlines:
183 ldd_version_output = subprocess.check_output(['ldd', '--version'])
184 glibc_version = ldd_version_output.decode().splitlines()[0].split()[-1]
185 if StrictVersion('2.14') > StrictVersion(glibc_version):
186 print("WARN: ignoring the Linaro ARM toolchains because too old host glibc", file=sys.stderr)
192 def fixup_config(sysinfo, configfile):
193 """Finalize the configuration and reject any problematic combinations
195 This function returns 'True' when the configuration has been
196 accepted, and 'False' when the configuration has not been accepted because
197 it is known to fail (in which case another random configuration will be
201 with open(configfile) as configf:
202 configlines = configf.readlines()
206 BR2_TOOLCHAIN_EXTERNAL_URL = 'BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/'
208 if "BR2_NEEDS_HOST_JAVA=y\n" in configlines and not sysinfo.has("java"):
210 # The ctng toolchain is affected by PR58854
211 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
212 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
214 # The ctng toolchain tigger an assembler error with guile package when compiled with -Os (same issue as for CS ARM 2014.05-29)
215 if 'BR2_PACKAGE_GUILE=y\n' in configlines and \
216 'BR2_OPTIMIZE_S=y\n' in configlines and \
217 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
219 # The ctng toolchain is affected by PR58854
220 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
221 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv6-ctng-linux-uclibcgnueabi.tar.xz"\n' in configlines:
223 # The ctng toolchain is affected by PR58854
224 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
225 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv7-ctng-linux-gnueabihf.tar.xz"\n' in configlines:
227 # The ctng toolchain is affected by PR60155
228 if 'BR2_PACKAGE_SDL=y\n' in configlines and \
229 BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
231 # The ctng toolchain is affected by PR60155
232 if 'BR2_PACKAGE_LIBMPEG2=y\n' in configlines and \
233 BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
235 # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
236 if 'BR2_PACKAGE_STRONGSWAN=y\n' in configlines and \
237 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
239 # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
240 if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
241 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
243 # libffi not available on ARMv7-M, but propagating libffi arch
244 # dependencies in Buildroot is really too much work, so we handle
246 if 'BR2_ARM_CPU_ARMV7M=y\n' in configlines and \
247 'BR2_PACKAGE_LIBFFI=y\n' in configlines:
249 if 'BR2_PACKAGE_SUNXI_BOARDS=y\n' in configlines:
250 configlines.remove('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE=""\n')
251 configlines.append('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a10/hackberry.fex"\n')
252 # This MIPS uClibc toolchain fails to build the gdb package
253 if 'BR2_PACKAGE_GDB=y\n' in configlines and \
254 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
256 # This MIPS uClibc toolchain fails to build the rt-tests package
257 if 'BR2_PACKAGE_RT_TESTS=y\n' in configlines and \
258 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
260 # This MIPS uClibc toolchain fails to build the civetweb package
261 if 'BR2_PACKAGE_CIVETWEB=y\n' in configlines and \
262 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
264 # This MIPS ctng toolchain fails to build the python3 package
265 if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
266 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
268 # This MIPS uClibc toolchain fails to build the strace package
269 if 'BR2_PACKAGE_STRACE=y\n' in configlines and \
270 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
272 # This MIPS uClibc toolchain fails to build the cdrkit package
273 if 'BR2_PACKAGE_CDRKIT=y\n' in configlines and \
274 'BR2_STATIC_LIBS=y\n' in configlines and \
275 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
277 # uClibc vfork static linking issue
278 if 'BR2_PACKAGE_ALSA_LIB=y\n' in configlines and \
279 'BR2_STATIC_LIBS=y\n' in configlines and \
280 BR2_TOOLCHAIN_EXTERNAL_URL + 'i486-ctng-linux-uclibc.tar.xz"\n' in configlines:
282 # This MIPS uClibc toolchain fails to build the weston package
283 if 'BR2_PACKAGE_WESTON=y\n' in configlines and \
284 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
286 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
287 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
288 'BR2_PACKAGE_BOOST=y\n' in configlines:
290 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
291 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
292 'BR2_PACKAGE_QT5BASE_GUI=y\n' in configlines:
294 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
295 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
296 'BR2_PACKAGE_FLANN=y\n' in configlines:
299 if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE=y\n' in configlines and \
300 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n' in configlines and \
301 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\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')
310 if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y\n' in configlines and \
311 'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n' in configlines:
312 bootscr = os.path.join(args.outputdir, "boot_script.txt")
313 with open(bootscr, "w+") as bootscrf:
314 bootscrf.write("prop=value")
315 configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n')
316 configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="%s"\n' % bootscr)
318 if 'BR2_ROOTFS_SKELETON_CUSTOM=y\n' in configlines and \
319 'BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n' in configlines:
320 configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM=y\n')
321 configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n')
323 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
324 'BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n' in configlines and \
325 'BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n' in configlines:
326 configlines.remove('BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n')
327 configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
328 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n')
330 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
331 'BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n' in configlines and \
332 'BR2_LINUX_KERNEL_DEFCONFIG=""\n' in configlines:
333 configlines.remove('BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n')
334 configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
335 configlines.remove('BR2_LINUX_KERNEL_DEFCONFIG=""\n')
337 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
338 'BR2_LINUX_KERNEL_CUSTOM_GIT=y\n' in configlines and \
339 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
340 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_GIT=y\n')
341 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
342 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
344 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
345 'BR2_LINUX_KERNEL_CUSTOM_HG=y\n' in configlines and \
346 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
347 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_HG=y\n')
348 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
349 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
351 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
352 'BR2_LINUX_KERNEL_CUSTOM_SVN=y\n' in configlines and \
353 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
354 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_SVN=y\n')
355 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
356 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
358 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
359 'BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n' in configlines and \
360 'BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
361 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n')
362 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
363 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n')
365 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
366 'BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n' in configlines and \
367 'BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n' in configlines:
368 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n')
369 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
370 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n')
372 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
373 'BR2_LINUX_KERNEL_DTS_SUPPORT=y\n' in configlines and \
374 'BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n' in configlines and \
375 'BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n' in configlines:
376 configlines.remove('BR2_LINUX_KERNEL_DTS_SUPPORT=y\n')
377 configlines.remove('BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n')
378 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n')
379 if 'BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n' in configlines:
380 configlines.remove('BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n')
381 configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
382 if 'BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n' in configlines:
383 configlines.remove('BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n')
384 configlines.append('BR2_LINUX_KERNEL_ZIMAGE=y\n')
385 if 'BR2_LINUX_KERNEL_CUIMAGE=y\n' in configlines:
386 configlines.remove('BR2_LINUX_KERNEL_CUIMAGE=y\n')
387 configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
388 if 'BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n' in configlines:
389 configlines.remove('BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n')
390 configlines.append('BR2_LINUX_KERNEL_VMLINUX=y\n')
392 if 'BR2_LINUX_KERNEL_EXT_AUFS=y\n' in configlines and \
393 'BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n' in configlines:
394 configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS=y\n')
395 configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n')
397 if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
398 'BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n' in configlines and \
399 'BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n' in configlines:
400 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
401 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n')
402 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n')
404 if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
405 'BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n' in configlines and \
406 'BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n' in configlines:
407 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
408 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n')
409 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n')
411 if 'BR2_KERNEL_HEADERS_VERSION=y\n' in configlines and \
412 'BR2_DEFAULT_KERNEL_VERSION=""\n' in configlines:
413 configlines.remove('BR2_KERNEL_HEADERS_VERSION=y\n')
414 configlines.remove('BR2_DEFAULT_KERNEL_VERSION=""\n')
416 if 'BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n' in configlines and \
417 'BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n':
418 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n')
419 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n')
421 if 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n' in configlines and \
422 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
423 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n')
424 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n')
426 if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
427 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n' in configlines and \
428 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n' in configlines:
429 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION=y\n')
430 configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
431 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_VERSION_VALUE=""\n')
433 if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
434 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n' in configlines and \
435 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
436 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL=y\n')
437 configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
438 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_TARBALL_LOCATION=""\n')
440 if 'BR2_TARGET_ARM_TRUSTED_FIRMWARE=y\n' in configlines and \
441 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n' in configlines and \
442 'BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n' in configlines:
443 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_GIT=y\n')
444 configlines.append('BR2_TARGET_ARM_TRUSTED_FIRMWARE_LATEST_VERSION=y\n')
445 configlines.remove('BR2_TARGET_ARM_TRUSTED_FIRMWARE_CUSTOM_REPO_URL=""\n')
447 if 'BR2_TARGET_AT91BOOTSTRAP3=y\n' in configlines and \
448 'BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n' in configlines:
449 configlines.remove('BR2_TARGET_AT91BOOTSTRAP3=y\n')
450 configlines.remove('BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n')
452 if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
453 'BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n' in configlines and \
454 'BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n' in configlines:
455 configlines.remove('BR2_TARGET_BAREBOX=y\n')
456 configlines.remove('BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n')
457 configlines.remove('BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n')
459 if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
460 'BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n' in configlines and \
461 'BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n' in configlines:
462 configlines.remove('BR2_TARGET_BAREBOX=y\n')
463 configlines.remove('BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n')
464 configlines.remove('BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n')
466 if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
467 'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n' in configlines and \
468 'BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
469 configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL=y\n')
470 configlines.append('BR2_TARGET_OPTEE_OS_LATEST=y\n')
471 configlines.remove('BR2_TARGET_OPTEE_OS_CUSTOM_TARBALL_LOCATION=""\n')
473 if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
474 'BR2_TARGET_OPTEE_OS_PLATFORM=""\n' in configlines:
475 configlines.remove('BR2_TARGET_OPTEE_OS=y\n')
476 configlines.remove('BR2_TARGET_OPTEE_OS_PLATFORM=""\n')
478 if 'BR2_TARGET_ROOTFS_EXT2=y\n' in configlines and \
479 'BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n' in configlines:
480 configlines.remove('BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n')
481 configlines.append('BR2_TARGET_ROOTFS_EXT2_SIZE="%s"\n' % ROOTFS_SIZE)
483 if 'BR2_TARGET_ROOTFS_F2FS=y\n' in configlines and \
484 'BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n' in configlines:
485 configlines.remove('BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n')
486 configlines.append('BR2_TARGET_ROOTFS_F2FS_SIZE="%s"\n' % ROOTFS_SIZE)
488 if 'BR2_TARGET_S500_BOOTLOADER=y\n' in configlines and \
489 'BR2_TARGET_S500_BOOTLOADER_BOARD=""\n' in configlines:
490 configlines.remove('BR2_TARGET_S500_BOOTLOADER=y\n')
491 configlines.remove('BR2_TARGET_S500_BOOTLOADER_BOARD=""\n')
493 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
494 'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
495 'BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n' in configlines and \
496 'BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n' in configlines:
497 configlines.remove('BR2_TARGET_UBOOT=y\n')
498 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
499 configlines.remove('BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n')
500 configlines.remove('BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n')
502 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
503 'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
504 'BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n' in configlines and \
505 'BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n' in configlines:
506 configlines.remove('BR2_TARGET_UBOOT=y\n')
507 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
508 configlines.remove('BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n')
509 configlines.remove('BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n')
511 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
512 'BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n' in configlines and \
513 'BR2_TARGET_UBOOT_BOARDNAME=""\n' in configlines:
514 configlines.remove('BR2_TARGET_UBOOT=y\n')
515 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n')
516 configlines.remove('BR2_TARGET_UBOOT_BOARDNAME=""\n')
518 if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
519 'BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n' in configlines and \
520 'BR2_TOOLCHAIN_EXTERNAL_PATH=""\n' in configlines:
521 configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
522 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n')
523 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PATH=""\n')
524 if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
527 if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
528 'BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n' in configlines and \
529 'BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n' in configlines and \
530 'BR2_TOOLCHAIN_EXTERNAL_URL=""\n' in configlines:
531 configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
532 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n')
533 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n')
534 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_URL=""\n')
535 if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
538 if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
539 'BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n' in configlines and \
540 'BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n' in configlines:
541 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_GIT=y\n')
542 configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
543 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_REPO_URL=""\n')
545 if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
546 'BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n' in configlines and \
547 'BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
548 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL=y\n')
549 configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
550 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_TARBALL_LOCATION=""\n')
552 if 'BR2_TARGET_OPENSBI=y\n' in configlines and \
553 'BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n' in configlines and \
554 'BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n' in configlines:
555 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION=y\n')
556 configlines.append('BR2_TARGET_OPENSBI_LATEST_VERSION=y\n')
557 configlines.remove('BR2_TARGET_OPENSBI_CUSTOM_VERSION_VALUE=""\n')
559 if 'BR2_PACKAGE_REFPOLICY=y\n' in configlines and \
560 'BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n' in configlines and \
561 'BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n' in configlines:
562 configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_GIT=y\n')
563 configlines.append('BR2_PACKAGE_REFPOLICY_UPSTREAM_VERSION=y\n')
564 configlines.remove('BR2_PACKAGE_REFPOLICY_CUSTOM_REPO_URL=""\n')
566 if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
567 'BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n' in configlines and \
568 'BR2_PACKAGE_XENOMAI_REPOSITORY=""\n' in configlines:
569 configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_GIT=y\n')
570 configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
571 configlines.remove('BR2_PACKAGE_XENOMAI_REPOSITORY=""\n')
573 if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
574 'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n' in configlines and \
575 'BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n' in configlines:
576 configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL=y\n')
577 configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
578 configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_TARBALL_URL=""\n')
580 if 'BR2_PACKAGE_XENOMAI=y\n' in configlines and \
581 'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n' in configlines and \
582 'BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n' in configlines:
583 configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION=y\n')
584 configlines.append('BR2_PACKAGE_XENOMAI_LATEST_VERSION=y\n')
585 configlines.remove('BR2_PACKAGE_XENOMAI_CUSTOM_VERSION_VALUE=""\n')
587 if 'BR2_PACKAGE_XVISOR=y\n' in configlines and \
588 'BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n' in configlines and \
589 'BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n' in configlines:
590 configlines.remove('BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n')
591 configlines.append('BR2_PACKAGE_XVISOR_USE_DEFCONFIG=y\n')
592 configlines.remove('BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n')
594 with open(configfile, "w+") as configf:
595 configf.writelines(configlines)
600 def gen_config(args):
601 """Generate a new random configuration
603 This function generates the configuration, by choosing a random
604 toolchain configuration and then generating a random selection of
608 sysinfo = SystemInfo()
610 if args.toolchains_csv:
611 # Select a random toolchain configuration
612 configs = get_toolchain_configs(args.toolchains_csv, args.buildrootdir)
614 i = randint(0, len(configs) - 1)
615 toolchainconfig = configs[i]
619 configlines = list(toolchainconfig)
621 # Combine with the minimal configuration
622 minimalconfigfile = os.path.join(args.buildrootdir,
623 'support/config-fragments/minimal.config')
624 with open(minimalconfigfile) as minimalf:
625 configlines += minimalf.readlines()
627 # Allow hosts with old certificates to download over https
628 configlines.append("BR2_WGET=\"wget --passive-ftp -nd -t 3 --no-check-certificate\"\n")
631 if randint(0, 15) == 0:
632 configlines.append("BR2_PER_PACKAGE_DIRECTORIES=y\n")
634 # Amend the configuration with a few things.
635 if randint(0, 20) == 0:
636 configlines.append("BR2_ENABLE_DEBUG=y\n")
637 if randint(0, 20) == 0:
638 configlines.append("BR2_ENABLE_RUNTIME_DEBUG=y\n")
639 if randint(0, 1) == 0:
640 configlines.append("BR2_INIT_BUSYBOX=y\n")
641 elif randint(0, 15) == 0:
642 configlines.append("BR2_INIT_SYSTEMD=y\n")
643 elif randint(0, 10) == 0:
644 configlines.append("BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y\n")
645 if randint(0, 20) == 0:
646 configlines.append("BR2_STATIC_LIBS=y\n")
647 if randint(0, 20) == 0:
648 configlines.append("BR2_PACKAGE_PYTHON3_PY_ONLY=y\n")
649 if randint(0, 5) == 0:
650 configlines.append("BR2_OPTIMIZE_2=y\n")
651 if randint(0, 4) == 0:
652 configlines.append("BR2_SYSTEM_ENABLE_NLS=y\n")
653 if randint(0, 4) == 0:
654 configlines.append("BR2_FORTIFY_SOURCE_2=y\n")
656 # Randomly enable BR2_REPRODUCIBLE 10% of times
657 # also enable tar filesystem images for testing
658 if sysinfo.has("diffoscope") and randint(0, 10) == 0:
659 configlines.append("BR2_REPRODUCIBLE=y\n")
660 configlines.append("BR2_TARGET_ROOTFS_TAR=y\n")
662 # Write out the configuration file
663 if not os.path.exists(args.outputdir):
664 os.makedirs(args.outputdir)
665 if args.outputdir == os.path.abspath(os.path.join(args.buildrootdir, "output")):
666 configfile = os.path.join(args.buildrootdir, ".config")
668 configfile = os.path.join(args.outputdir, ".config")
669 with open(configfile, "w+") as configf:
670 configf.writelines(configlines)
672 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
675 if not is_toolchain_usable(configfile, toolchainconfig):
678 # Now, generate the random selection of packages, and fixup
680 # Safe-guard, in case we can not quickly come to a valid
681 # configuration: allow at most 100 (arbitrary) iterations.
684 if bounded_loop == 0:
685 print("ERROR: cannot generate random configuration after 100 iterations",
690 "make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
691 "KCONFIG_SEED=0x%s" % hexlify(os.urandom(4)).decode("ascii").upper(),
692 "KCONFIG_PROBABILITY=%d" % randint(1, 20),
693 "randpackageconfig" if args.toolchains_csv else "randconfig"
695 subprocess.check_call(make_rand)
697 if fixup_config(sysinfo, configfile):
700 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
703 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
706 return subprocess.call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
710 if __name__ == '__main__':
712 parser = argparse.ArgumentParser(description="Generate a random configuration")
713 parser.add_argument("--outputdir", "-o",
714 help="Output directory (relative to current directory)",
715 type=str, default='output')
716 parser.add_argument("--buildrootdir", "-b",
717 help="Buildroot directory (relative to current directory)",
718 type=str, default='.')
720 toolchains_csv = parser.add_mutually_exclusive_group(required=False)
721 toolchains_csv.add_argument("--toolchains-csv",
722 dest="toolchains_csv",
723 help="Path of the toolchain configuration file",
725 toolchains_csv.add_argument("--no-toolchains-csv",
726 dest="toolchains_csv",
727 help="Generate random toolchain configuration",
728 action='store_false')
729 parser.set_defaults(toolchains_csv="support/config-fragments/autobuild/toolchain-configs.csv")
731 args = parser.parse_args()
733 # We need the absolute path to use with O=, because the relative
734 # path to the output directory here is not relative to the
735 # Buildroot sources, but to the current directory.
736 args.outputdir = os.path.abspath(args.outputdir)
739 ret = gen_config(args)
740 except Exception as e:
741 print(str(e), file=sys.stderr)