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.
24 from random import randint
27 from distutils.version import StrictVersion
30 if sys.hexversion >= 0x3000000:
31 import urllib.request as _urllib
33 import urllib2 as _urllib
36 def urlopen_closing(uri):
37 return contextlib.closing(_urllib.urlopen(uri))
41 DEFAULT_NEEDED_PROGS = ["make", "git", "gcc", "timeout"]
42 DEFAULT_OPTIONAL_PROGS = ["bzr", "java", "javac", "jar", "diffoscope"]
45 self.needed_progs = list(self.__class__.DEFAULT_NEEDED_PROGS)
46 self.optional_progs = list(self.__class__.DEFAULT_OPTIONAL_PROGS)
49 def find_prog(self, name, flags=os.X_OK, env=os.environ):
50 if not name or name[0] == os.sep:
51 raise ValueError(name)
53 prog_path = env.get("PATH", None)
54 # for windows compatibility, we'd need to take PATHEXT into account
57 for prog_dir in filter(None, prog_path.split(os.pathsep)):
58 # os.join() not necessary: non-empty prog_dir
59 # and name[0] != os.sep
60 prog = prog_dir + os.sep + name
61 if os.access(prog, flags):
67 """Checks whether a program is available.
68 Lazily evaluates missing entries.
70 Returns: None if prog not found, else path to the program [evaluates
74 return self.progs[prog]
78 have_it = self.find_prog(prog)
79 # java[c] needs special care
80 if have_it and prog in ('java', 'javac'):
81 with open(os.devnull, "w") as devnull:
82 if subprocess.call("%s -version | grep gcj" % prog,
84 stdout=devnull, stderr=devnull) != 1:
87 self.progs[prog] = have_it
90 def check_requirements(self):
91 """Checks program dependencies.
93 Returns: True if all mandatory programs are present, else False.
95 do_check_has_prog = self.has
97 missing_requirements = False
98 for prog in self.needed_progs:
99 if not do_check_has_prog(prog):
100 print("ERROR: your system lacks the '%s' program" % prog)
101 missing_requirements = True
103 # check optional programs here,
104 # else they'd get checked by each worker instance
105 for prog in self.optional_progs:
106 do_check_has_prog(prog)
108 return not missing_requirements
111 def get_toolchain_configs(toolchains_csv, buildrootdir):
112 """Fetch and return the possible toolchain configurations
114 This function returns an array of toolchain configurations. Each
115 toolchain configuration is itself an array of lines of the defconfig.
118 with open(toolchains_csv) as r:
119 # filter empty lines and comments
120 lines = [t for t in r.readlines() if len(t.strip()) > 0 and t[0] != '#']
124 (_, _, _, _, hostarch) = os.uname()
125 # ~2015 distros report x86 when on a 32bit install
126 if hostarch == 'i686' or hostarch == 'i386' or hostarch == 'x86':
129 for row in csv.reader(toolchains):
132 config_hostarch = row[1]
135 # Keep all toolchain configs that work regardless of the host
137 if config_hostarch == "any":
140 # Keep all toolchain configs that can work on the current host
142 if hostarch == config_hostarch:
145 # Assume that x86 32 bits toolchains work on x86_64 build
147 if hostarch == 'x86_64' and config_hostarch == "x86":
153 if not os.path.isabs(configfile):
154 configfile = os.path.join(buildrootdir, configfile)
156 with open(configfile) as r:
157 config = r.readlines()
158 configs.append(config)
162 def is_toolchain_usable(configfile, config):
163 """Check if the toolchain is actually usable."""
165 with open(configfile) as configf:
166 configlines = configf.readlines()
168 # Check that the toolchain configuration is still present
169 for toolchainline in config:
170 if toolchainline not in configlines:
171 print("WARN: toolchain can't be used", file=sys.stderr)
172 print(" Missing: %s" % toolchainline.strip(), file=sys.stderr)
175 # The latest Linaro toolchains on x86-64 hosts requires glibc
177 if platform.machine() == 'x86_64':
178 if 'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARM=y\n' in configlines or \
179 'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64=y\n' in configlines or \
180 'BR2_TOOLCHAIN_EXTERNAL_LINARO_AARCH64_BE=y\n' in configlines or \
181 'BR2_TOOLCHAIN_EXTERNAL_LINARO_ARMEB=y\n' in configlines:
182 ldd_version_output = subprocess.check_output(['ldd', '--version'])
183 glibc_version = ldd_version_output.splitlines()[0].split()[-1]
184 if StrictVersion('2.14') > StrictVersion(glibc_version):
185 print("WARN: ignoring the Linaro ARM toolchains because too old host glibc", file=sys.stderr)
191 def fixup_config(sysinfo, configfile):
192 """Finalize the configuration and reject any problematic combinations
194 This function returns 'True' when the configuration has been
195 accepted, and 'False' when the configuration has not been accepted because
196 it is known to fail (in which case another random configuration will be
200 with open(configfile) as configf:
201 configlines = configf.readlines()
205 BR2_TOOLCHAIN_EXTERNAL_URL = 'BR2_TOOLCHAIN_EXTERNAL_URL="http://autobuild.buildroot.org/toolchains/tarballs/'
207 if "BR2_NEEDS_HOST_JAVA=y\n" in configlines and not sysinfo.has("java"):
209 # The ctng toolchain is affected by PR58854
210 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
211 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
213 # The ctng toolchain tigger an assembler error with guile package when compiled with -Os (same issue as for CS ARM 2014.05-29)
214 if 'BR2_PACKAGE_GUILE=y\n' in configlines and \
215 'BR2_OPTIMIZE_S=y\n' in configlines and \
216 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv5-ctng-linux-gnueabi.tar.xz"\n' in configlines:
218 # The ctng toolchain is affected by PR58854
219 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
220 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv6-ctng-linux-uclibcgnueabi.tar.xz"\n' in configlines:
222 # The ctng toolchain is affected by PR58854
223 if 'BR2_PACKAGE_LTTNG_TOOLS=y\n' in configlines and \
224 BR2_TOOLCHAIN_EXTERNAL_URL + 'armv7-ctng-linux-gnueabihf.tar.xz"\n' in configlines:
226 # The ctng toolchain is affected by PR60155
227 if 'BR2_PACKAGE_SDL=y\n' in configlines and \
228 BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
230 # The ctng toolchain is affected by PR60155
231 if 'BR2_PACKAGE_LIBMPEG2=y\n' in configlines and \
232 BR2_TOOLCHAIN_EXTERNAL_URL + 'powerpc-ctng-linux-uclibc.tar.xz"\n' in configlines:
234 # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
235 if 'BR2_PACKAGE_STRONGSWAN=y\n' in configlines and \
236 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
238 # This MIPS toolchain uses eglibc-2.18 which lacks SYS_getdents64
239 if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
240 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
242 # libffi not available on ARMv7-M, but propagating libffi arch
243 # dependencies in Buildroot is really too much work, so we handle
245 if 'BR2_ARM_CPU_ARMV7M=y\n' in configlines and \
246 'BR2_PACKAGE_LIBFFI=y\n' in configlines:
248 if 'BR2_nds32=y\n' in configlines and \
249 'BR2_PACKAGE_LIBFFI=y\n' in configlines:
251 if 'BR2_PACKAGE_SUNXI_BOARDS=y\n' in configlines:
252 configlines.remove('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE=""\n')
253 configlines.append('BR2_PACKAGE_SUNXI_BOARDS_FEX_FILE="a10/hackberry.fex"\n')
254 # This MIPS uClibc toolchain fails to build the gdb package
255 if 'BR2_PACKAGE_GDB=y\n' in configlines and \
256 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
258 # This MIPS uClibc toolchain fails to build the rt-tests package
259 if 'BR2_PACKAGE_RT_TESTS=y\n' in configlines and \
260 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
262 # This MIPS uClibc toolchain fails to build the civetweb package
263 if 'BR2_PACKAGE_CIVETWEB=y\n' in configlines and \
264 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
266 # This MIPS ctng toolchain fails to build the python3 package
267 if 'BR2_PACKAGE_PYTHON3=y\n' in configlines and \
268 BR2_TOOLCHAIN_EXTERNAL_URL + 'mips64el-ctng_n64-linux-gnu.tar.xz"\n' in configlines:
270 # This MIPS uClibc toolchain fails to build the strace package
271 if 'BR2_PACKAGE_STRACE=y\n' in configlines and \
272 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
274 # This MIPS uClibc toolchain fails to build the cdrkit package
275 if 'BR2_PACKAGE_CDRKIT=y\n' in configlines and \
276 'BR2_STATIC_LIBS=y\n' in configlines and \
277 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
279 # uClibc vfork static linking issue
280 if 'BR2_PACKAGE_ALSA_LIB=y\n' in configlines and \
281 'BR2_STATIC_LIBS=y\n' in configlines and \
282 BR2_TOOLCHAIN_EXTERNAL_URL + 'i486-ctng-linux-uclibc.tar.xz"\n' in configlines:
284 # This MIPS uClibc toolchain fails to build the weston package
285 if 'BR2_PACKAGE_WESTON=y\n' in configlines and \
286 BR2_TOOLCHAIN_EXTERNAL_URL + 'mipsel-ctng-linux-uclibc.tar.xz"\n' in configlines:
288 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
289 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
290 'BR2_PACKAGE_BOOST=y\n' in configlines:
292 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
293 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
294 'BR2_PACKAGE_QT5BASE_GUI=y\n' in configlines:
296 # The cs nios2 2017.02 toolchain is affected by binutils PR19405
297 if 'BR2_TOOLCHAIN_EXTERNAL_CODESOURCERY_NIOSII=y\n' in configlines and \
298 'BR2_PACKAGE_FLANN=y\n' in configlines:
301 if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE=y\n' in configlines:
302 bootenv = os.path.join(args.outputdir, "boot_env.txt")
303 with open(bootenv, "w+") as bootenvf:
304 bootenvf.write("prop=value")
305 configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE=""\n')
306 configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SOURCE="%s"\n' % bootenv)
307 configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE=""\n')
308 configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_ENVIMAGE_SIZE="0x1000"\n')
310 if 'BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT=y\n' in configlines:
311 bootscr = os.path.join(args.outputdir, "boot_script.txt")
312 with open(bootscr, "w+") as bootscrf:
313 bootscrf.write("prop=value")
314 configlines.remove('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE=""\n')
315 configlines.append('BR2_PACKAGE_HOST_UBOOT_TOOLS_BOOT_SCRIPT_SOURCE="%s"\n' % bootscr)
317 if 'BR2_ROOTFS_SKELETON_CUSTOM=y\n' in configlines and \
318 'BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n' in configlines:
319 configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM=y\n')
320 configlines.remove('BR2_ROOTFS_SKELETON_CUSTOM_PATH=""\n')
322 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
323 'BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n' in configlines and \
324 'BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n' in configlines:
325 configlines.remove('BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\n')
326 configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
327 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=""\n')
329 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
330 'BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n' in configlines and \
331 'BR2_LINUX_KERNEL_DEFCONFIG=""\n' in configlines:
332 configlines.remove('BR2_LINUX_KERNEL_USE_DEFCONFIG=y\n')
333 configlines.append('BR2_LINUX_KERNEL_USE_ARCH_DEFAULT_CONFIG=y\n')
334 configlines.remove('BR2_LINUX_KERNEL_DEFCONFIG=""\n')
336 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
337 'BR2_LINUX_KERNEL_CUSTOM_GIT=y\n' in configlines and \
338 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
339 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_GIT=y\n')
340 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
341 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
343 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
344 'BR2_LINUX_KERNEL_CUSTOM_HG=y\n' in configlines and \
345 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
346 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_HG=y\n')
347 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
348 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
350 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
351 'BR2_LINUX_KERNEL_CUSTOM_SVN=y\n' in configlines and \
352 'BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n' in configlines:
353 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_SVN=y\n')
354 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
355 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_REPO_URL=""\n')
357 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
358 'BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n' in configlines and \
359 'BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
360 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL=y\n')
361 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
362 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_TARBALL_LOCATION=""\n')
364 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
365 'BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n' in configlines and \
366 'BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n' in configlines:
367 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION=y\n')
368 configlines.append('BR2_LINUX_KERNEL_LATEST_VERSION=y\n')
369 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE=""\n')
371 if 'BR2_LINUX_KERNEL=y\n' in configlines and \
372 'BR2_LINUX_KERNEL_DTS_SUPPORT=y\n' in configlines and \
373 'BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n' in configlines and \
374 'BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n' in configlines:
375 configlines.remove('BR2_LINUX_KERNEL_DTS_SUPPORT=y\n')
376 configlines.remove('BR2_LINUX_KERNEL_INTREE_DTS_NAME=""\n')
377 configlines.remove('BR2_LINUX_KERNEL_CUSTOM_DTS_PATH=""\n')
378 if 'BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n' in configlines:
379 configlines.remove('BR2_LINUX_KERNEL_APPENDED_UIMAGE=y\n')
380 configlines.append('BR2_LINUX_KERNEL_UIMAGE=y\n')
381 if 'BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n' in configlines:
382 configlines.remove('BR2_LINUX_KERNEL_APPENDED_ZIMAGE=y\n')
383 configlines.append('BR2_LINUX_KERNEL_ZIMAGE=y\n')
384 if 'BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n' in configlines:
385 configlines.remove('BR2_LINUX_KERNEL_SIMPLEIMAGE=y\n')
386 configlines.append('BR2_LINUX_KERNEL_VMLINUX=y\n')
388 if 'BR2_LINUX_KERNEL_EXT_AUFS=y\n' in configlines and \
389 'BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n' in configlines:
390 configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS=y\n')
391 configlines.remove('BR2_LINUX_KERNEL_EXT_AUFS_VERSION=""\n')
393 if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
394 'BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n' in configlines and \
395 'BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n' in configlines:
396 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
397 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_CUSTOM_CONFIG=y\n')
398 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_CUSTOM_CONFIG_FILE=""\n')
400 if 'BR2_PACKAGE_LINUX_BACKPORTS=y\n' in configlines and \
401 'BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n' in configlines and \
402 'BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n' in configlines:
403 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS=y\n')
404 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_USE_DEFCONFIG=y\n')
405 configlines.remove('BR2_PACKAGE_LINUX_BACKPORTS_DEFCONFIG=""\n')
407 if 'BR2_KERNEL_HEADERS_VERSION=y\n' in configlines and \
408 'BR2_DEFAULT_KERNEL_VERSION=""\n' in configlines:
409 configlines.remove('BR2_KERNEL_HEADERS_VERSION=y\n')
410 configlines.remove('BR2_DEFAULT_KERNEL_VERSION=""\n')
412 if 'BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n' in configlines and \
413 'BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n':
414 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_GIT=y\n')
415 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_REPO_URL=""\n')
417 if 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n' in configlines and \
418 'BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n' in configlines:
419 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL=y\n')
420 configlines.remove('BR2_KERNEL_HEADERS_CUSTOM_TARBALL_LOCATION=""\n')
422 if 'BR2_TARGET_AT91BOOTSTRAP3=y\n' in configlines and \
423 'BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n' in configlines:
424 configlines.remove('BR2_TARGET_AT91BOOTSTRAP3=y\n')
425 configlines.remove('BR2_TARGET_AT91BOOTSTRAP3_DEFCONFIG=""\n')
427 if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
428 'BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n' in configlines and \
429 'BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n' in configlines:
430 configlines.remove('BR2_TARGET_BAREBOX=y\n')
431 configlines.remove('BR2_TARGET_BAREBOX_USE_CUSTOM_CONFIG=y\n')
432 configlines.remove('BR2_TARGET_BAREBOX_CUSTOM_CONFIG_FILE=""\n')
434 if 'BR2_TARGET_BAREBOX=y\n' in configlines and \
435 'BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n' in configlines and \
436 'BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n' in configlines:
437 configlines.remove('BR2_TARGET_BAREBOX=y\n')
438 configlines.remove('BR2_TARGET_BAREBOX_USE_DEFCONFIG=y\n')
439 configlines.remove('BR2_TARGET_BAREBOX_BOARD_DEFCONFIG=""\n')
441 if 'BR2_TARGET_OPTEE_OS=y\n' in configlines and \
442 'BR2_TARGET_OPTEE_OS_PLATFORM=""\n' in configlines:
443 configlines.remove('BR2_TARGET_OPTEE_OS=y\n')
444 configlines.remove('BR2_TARGET_OPTEE_OS_PLATFORM=""\n')
446 if 'BR2_TARGET_ROOTFS_EXT2=y\n' in configlines and \
447 'BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n' in configlines:
448 configlines.remove('BR2_TARGET_ROOTFS_EXT2_SIZE="60M"\n')
449 configlines.append('BR2_TARGET_ROOTFS_EXT2_SIZE="%s"\n' % ROOTFS_SIZE)
451 if 'BR2_TARGET_ROOTFS_F2FS=y\n' in configlines and \
452 'BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n' in configlines:
453 configlines.remove('BR2_TARGET_ROOTFS_F2FS_SIZE="100M"\n')
454 configlines.append('BR2_TARGET_ROOTFS_F2FS_SIZE="%s"\n' % ROOTFS_SIZE)
456 if 'BR2_TARGET_S500_BOOTLOADER=y\n' in configlines and \
457 'BR2_TARGET_S500_BOOTLOADER_BOARD=""\n' in configlines:
458 configlines.remove('BR2_TARGET_S500_BOOTLOADER=y\n')
459 configlines.remove('BR2_TARGET_S500_BOOTLOADER_BOARD=""\n')
461 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
462 'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
463 'BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n' in configlines and \
464 'BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n' in configlines:
465 configlines.remove('BR2_TARGET_UBOOT=y\n')
466 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
467 configlines.remove('BR2_TARGET_UBOOT_USE_CUSTOM_CONFIG=y\n')
468 configlines.remove('BR2_TARGET_UBOOT_CUSTOM_CONFIG_FILE=""\n')
470 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
471 'BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n' in configlines and \
472 'BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n' in configlines and \
473 'BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n' in configlines:
474 configlines.remove('BR2_TARGET_UBOOT=y\n')
475 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_KCONFIG=y\n')
476 configlines.remove('BR2_TARGET_UBOOT_USE_DEFCONFIG=y\n')
477 configlines.remove('BR2_TARGET_UBOOT_BOARD_DEFCONFIG=""\n')
479 if 'BR2_TARGET_UBOOT=y\n' in configlines and \
480 'BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n' in configlines and \
481 'BR2_TARGET_UBOOT_BOARDNAME=""\n' in configlines:
482 configlines.remove('BR2_TARGET_UBOOT=y\n')
483 configlines.remove('BR2_TARGET_UBOOT_BUILD_SYSTEM_LEGACY=y\n')
484 configlines.remove('BR2_TARGET_UBOOT_BOARDNAME=""\n')
486 if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
487 'BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n' in configlines and \
488 'BR2_TOOLCHAIN_EXTERNAL_PATH=""\n' in configlines:
489 configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
490 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PREINSTALLED=y\n')
491 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_PATH=""\n')
492 if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
495 if 'BR2_TOOLCHAIN_EXTERNAL=y\n' in configlines and \
496 'BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n' in configlines and \
497 'BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n' in configlines and \
498 'BR2_TOOLCHAIN_EXTERNAL_URL=""\n' in configlines:
499 configlines.remove('BR2_TOOLCHAIN_EXTERNAL=y\n')
500 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_CUSTOM=y\n')
501 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_DOWNLOAD=y\n')
502 configlines.remove('BR2_TOOLCHAIN_EXTERNAL_URL=""\n')
503 if 'BR2_ARCH_HAS_NO_TOOLCHAIN_BUILDROOT=y\n' in configlines:
506 if 'BR2_PACKAGE_XVISOR=y\n' in configlines and \
507 'BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n' in configlines and \
508 'BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n' in configlines:
509 configlines.remove('BR2_PACKAGE_XVISOR_USE_CUSTOM_CONFIG=y\n')
510 configlines.append('BR2_PACKAGE_XVISOR_USE_DEFCONFIG=y\n')
511 configlines.remove('BR2_PACKAGE_XVISOR_CUSTOM_CONFIG_FILE=""\n')
513 with open(configfile, "w+") as configf:
514 configf.writelines(configlines)
519 def gen_config(args):
520 """Generate a new random configuration
522 This function generates the configuration, by choosing a random
523 toolchain configuration and then generating a random selection of
527 sysinfo = SystemInfo()
529 if args.toolchains_csv:
530 # Select a random toolchain configuration
531 configs = get_toolchain_configs(args.toolchains_csv, args.buildrootdir)
533 i = randint(0, len(configs) - 1)
534 toolchainconfig = configs[i]
538 configlines = list(toolchainconfig)
540 # Combine with the minimal configuration
541 minimalconfigfile = os.path.join(args.buildrootdir,
542 'support/config-fragments/minimal.config')
543 with open(minimalconfigfile) as minimalf:
544 configlines += minimalf.readlines()
546 # Allow hosts with old certificates to download over https
547 configlines.append("BR2_WGET=\"wget --passive-ftp -nd -t 3 --no-check-certificate\"\n")
550 if randint(0, 15) == 0:
551 configlines.append("BR2_PER_PACKAGE_DIRECTORIES=y\n")
553 # Amend the configuration with a few things.
554 if randint(0, 20) == 0:
555 configlines.append("BR2_ENABLE_DEBUG=y\n")
556 if randint(0, 20) == 0:
557 configlines.append("BR2_ENABLE_RUNTIME_DEBUG=y\n")
558 if randint(0, 1) == 0:
559 configlines.append("BR2_INIT_BUSYBOX=y\n")
560 elif randint(0, 15) == 0:
561 configlines.append("BR2_INIT_SYSTEMD=y\n")
562 elif randint(0, 10) == 0:
563 configlines.append("BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y\n")
564 if randint(0, 20) == 0:
565 configlines.append("BR2_STATIC_LIBS=y\n")
566 if randint(0, 20) == 0:
567 configlines.append("BR2_PACKAGE_PYTHON3_PY_ONLY=y\n")
568 if randint(0, 5) == 0:
569 configlines.append("BR2_OPTIMIZE_2=y\n")
570 if randint(0, 4) == 0:
571 configlines.append("BR2_SYSTEM_ENABLE_NLS=y\n")
572 if randint(0, 4) == 0:
573 configlines.append("BR2_FORTIFY_SOURCE_2=y\n")
575 # Randomly enable BR2_REPRODUCIBLE 10% of times
576 # also enable tar filesystem images for testing
577 if sysinfo.has("diffoscope") and randint(0, 10) == 0:
578 configlines.append("BR2_REPRODUCIBLE=y\n")
579 configlines.append("BR2_TARGET_ROOTFS_TAR=y\n")
581 # Write out the configuration file
582 if not os.path.exists(args.outputdir):
583 os.makedirs(args.outputdir)
584 if args.outputdir == os.path.abspath(os.path.join(args.buildrootdir, "output")):
585 configfile = os.path.join(args.buildrootdir, ".config")
587 configfile = os.path.join(args.outputdir, ".config")
588 with open(configfile, "w+") as configf:
589 configf.writelines(configlines)
591 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
594 if not is_toolchain_usable(configfile, toolchainconfig):
597 # Now, generate the random selection of packages, and fixup
599 # Safe-guard, in case we can not quickly come to a valid
600 # configuration: allow at most 100 (arbitrary) iterations.
603 if bounded_loop == 0:
604 print("ERROR: cannot generate random configuration after 100 iterations",
608 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
609 "KCONFIG_PROBABILITY=%d" % randint(1, 20),
610 "randpackageconfig" if args.toolchains_csv else "randconfig"])
612 if fixup_config(sysinfo, configfile):
615 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
618 subprocess.check_call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
621 return subprocess.call(["make", "O=%s" % args.outputdir, "-C", args.buildrootdir,
625 if __name__ == '__main__':
627 parser = argparse.ArgumentParser(description="Generate a random configuration")
628 parser.add_argument("--outputdir", "-o",
629 help="Output directory (relative to current directory)",
630 type=str, default='output')
631 parser.add_argument("--buildrootdir", "-b",
632 help="Buildroot directory (relative to current directory)",
633 type=str, default='.')
635 toolchains_csv = parser.add_mutually_exclusive_group(required=False)
636 toolchains_csv.add_argument("--toolchains-csv",
637 dest="toolchains_csv",
638 help="Path of the toolchain configuration file",
640 toolchains_csv.add_argument("--no-toolchains-csv",
641 dest="toolchains_csv",
642 help="Generate random toolchain configuration",
643 action='store_false')
644 parser.set_defaults(toolchains_csv="support/config-fragments/autobuild/toolchain-configs.csv")
646 args = parser.parse_args()
648 # We need the absolute path to use with O=, because the relative
649 # path to the output directory here is not relative to the
650 # Buildroot sources, but to the current directory.
651 args.outputdir = os.path.abspath(args.outputdir)
654 ret = gen_config(args)
655 except Exception as e:
656 print(str(e), file=sys.stderr)