15a27c734SMasahiro Yamada#!/usr/bin/env python2 283d290c5STom Rini# SPDX-License-Identifier: GPL-2.0+ 35a27c734SMasahiro Yamada# 45a27c734SMasahiro Yamada# Author: Masahiro Yamada <yamada.masahiro@socionext.com> 55a27c734SMasahiro Yamada# 65a27c734SMasahiro Yamada 75a27c734SMasahiro Yamada""" 85a27c734SMasahiro YamadaMove config options from headers to defconfig files. 95a27c734SMasahiro Yamada 105a27c734SMasahiro YamadaSince Kconfig was introduced to U-Boot, we have worked on moving 115a27c734SMasahiro Yamadaconfig options from headers to Kconfig (defconfig). 125a27c734SMasahiro Yamada 135a27c734SMasahiro YamadaThis tool intends to help this tremendous work. 145a27c734SMasahiro Yamada 155a27c734SMasahiro Yamada 165a27c734SMasahiro YamadaUsage 175a27c734SMasahiro Yamada----- 185a27c734SMasahiro Yamada 19b6ef393aSMasahiro YamadaFirst, you must edit the Kconfig to add the menu entries for the configs 2096464badSJoe Hershbergeryou are moving. 2196464badSJoe Hershberger 22b6ef393aSMasahiro YamadaAnd then run this tool giving CONFIG names you want to move. 23b6ef393aSMasahiro YamadaFor example, if you want to move CONFIG_CMD_USB and CONFIG_SYS_TEXT_BASE, 24b6ef393aSMasahiro Yamadasimply type as follows: 255a27c734SMasahiro Yamada 26b6ef393aSMasahiro Yamada $ tools/moveconfig.py CONFIG_CMD_USB CONFIG_SYS_TEXT_BASE 275a27c734SMasahiro Yamada 28b6ef393aSMasahiro YamadaThe tool walks through all the defconfig files and move the given CONFIGs. 295a27c734SMasahiro Yamada 305a27c734SMasahiro YamadaThe log is also displayed on the terminal. 315a27c734SMasahiro Yamada 321d085568SMasahiro YamadaThe log is printed for each defconfig as follows: 335a27c734SMasahiro Yamada 341d085568SMasahiro Yamada<defconfig_name> 351d085568SMasahiro Yamada <action1> 361d085568SMasahiro Yamada <action2> 371d085568SMasahiro Yamada <action3> 381d085568SMasahiro Yamada ... 395a27c734SMasahiro Yamada 401d085568SMasahiro Yamada<defconfig_name> is the name of the defconfig. 411d085568SMasahiro Yamada 421d085568SMasahiro Yamada<action*> shows what the tool did for that defconfig. 43c21fc7e2SMasahiro YamadaIt looks like one of the following: 445a27c734SMasahiro Yamada 455a27c734SMasahiro Yamada - Move 'CONFIG_... ' 465a27c734SMasahiro Yamada This config option was moved to the defconfig 475a27c734SMasahiro Yamada 48cc008299SMasahiro Yamada - CONFIG_... is not defined in Kconfig. Do nothing. 49916224c3SMasahiro Yamada The entry for this CONFIG was not found in Kconfig. The option is not 50916224c3SMasahiro Yamada defined in the config header, either. So, this case can be just skipped. 51916224c3SMasahiro Yamada 52916224c3SMasahiro Yamada - CONFIG_... is not defined in Kconfig (suspicious). Do nothing. 53916224c3SMasahiro Yamada This option is defined in the config header, but its entry was not found 54916224c3SMasahiro Yamada in Kconfig. 55cc008299SMasahiro Yamada There are two common cases: 56cc008299SMasahiro Yamada - You forgot to create an entry for the CONFIG before running 57cc008299SMasahiro Yamada this tool, or made a typo in a CONFIG passed to this tool. 58cc008299SMasahiro Yamada - The entry was hidden due to unmet 'depends on'. 59916224c3SMasahiro Yamada The tool does not know if the result is reasonable, so please check it 60916224c3SMasahiro Yamada manually. 615a27c734SMasahiro Yamada 62cc008299SMasahiro Yamada - 'CONFIG_...' is the same as the define in Kconfig. Do nothing. 63cc008299SMasahiro Yamada The define in the config header matched the one in Kconfig. 64cc008299SMasahiro Yamada We do not need to touch it. 655a27c734SMasahiro Yamada 6690ed6cbaSMasahiro Yamada - Compiler is missing. Do nothing. 6790ed6cbaSMasahiro Yamada The compiler specified for this architecture was not found 6890ed6cbaSMasahiro Yamada in your PATH environment. 6990ed6cbaSMasahiro Yamada (If -e option is passed, the tool exits immediately.) 7090ed6cbaSMasahiro Yamada 7190ed6cbaSMasahiro Yamada - Failed to process. 725a27c734SMasahiro Yamada An error occurred during processing this defconfig. Skipped. 735a27c734SMasahiro Yamada (If -e option is passed, the tool exits immediately on error.) 745a27c734SMasahiro Yamada 755a27c734SMasahiro YamadaFinally, you will be asked, Clean up headers? [y/n]: 765a27c734SMasahiro Yamada 775a27c734SMasahiro YamadaIf you say 'y' here, the unnecessary config defines are removed 785a27c734SMasahiro Yamadafrom the config headers (include/configs/*.h). 795a27c734SMasahiro YamadaIt just uses the regex method, so you should not rely on it. 805a27c734SMasahiro YamadaJust in case, please do 'git diff' to see what happened. 815a27c734SMasahiro Yamada 825a27c734SMasahiro Yamada 83b6ef393aSMasahiro YamadaHow does it work? 84b6ef393aSMasahiro Yamada----------------- 855a27c734SMasahiro Yamada 865a27c734SMasahiro YamadaThis tool runs configuration and builds include/autoconf.mk for every 875a27c734SMasahiro Yamadadefconfig. The config options defined in Kconfig appear in the .config 885a27c734SMasahiro Yamadafile (unless they are hidden because of unmet dependency.) 895a27c734SMasahiro YamadaOn the other hand, the config options defined by board headers are seen 905a27c734SMasahiro Yamadain include/autoconf.mk. The tool looks for the specified options in both 91b6ef393aSMasahiro Yamadaof them to decide the appropriate action for the options. If the given 92b6ef393aSMasahiro Yamadaconfig option is found in the .config, but its value does not match the 93b6ef393aSMasahiro Yamadaone from the board header, the config option in the .config is replaced 94b6ef393aSMasahiro Yamadawith the define in the board header. Then, the .config is synced by 95b6ef393aSMasahiro Yamada"make savedefconfig" and the defconfig is updated with it. 965a27c734SMasahiro Yamada 975a27c734SMasahiro YamadaFor faster processing, this tool handles multi-threading. It creates 985a27c734SMasahiro Yamadaseparate build directories where the out-of-tree build is run. The 995a27c734SMasahiro Yamadatemporary build directories are automatically created and deleted as 1005a27c734SMasahiro Yamadaneeded. The number of threads are chosen based on the number of the CPU 1015a27c734SMasahiro Yamadacores of your system although you can change it via -j (--jobs) option. 1025a27c734SMasahiro Yamada 1035a27c734SMasahiro Yamada 1045a27c734SMasahiro YamadaToolchains 1055a27c734SMasahiro Yamada---------- 1065a27c734SMasahiro Yamada 1075a27c734SMasahiro YamadaAppropriate toolchain are necessary to generate include/autoconf.mk 1085a27c734SMasahiro Yamadafor all the architectures supported by U-Boot. Most of them are available 1096821a745SSimon Glassat the kernel.org site, some are not provided by kernel.org. This tool uses 1106821a745SSimon Glassthe same tools as buildman, so see that tool for setup (e.g. --fetch-arch). 1115a27c734SMasahiro Yamada 1125a27c734SMasahiro Yamada 113ddf91c64SSimon GlassTips and trips 114ddf91c64SSimon Glass-------------- 115ddf91c64SSimon Glass 116ddf91c64SSimon GlassTo sync only X86 defconfigs: 117ddf91c64SSimon Glass 118ddf91c64SSimon Glass ./tools/moveconfig.py -s -d <(grep -l X86 configs/*) 119ddf91c64SSimon Glass 120ddf91c64SSimon Glassor: 121ddf91c64SSimon Glass 122ddf91c64SSimon Glass grep -l X86 configs/* | ./tools/moveconfig.py -s -d - 123ddf91c64SSimon Glass 124ddf91c64SSimon GlassTo process CONFIG_CMD_FPGAD only for a subset of configs based on path match: 125ddf91c64SSimon Glass 126ddf91c64SSimon Glass ls configs/{hrcon*,iocon*,strider*} | \ 127ddf91c64SSimon Glass ./tools/moveconfig.py -Cy CONFIG_CMD_FPGAD -d - 128ddf91c64SSimon Glass 129ddf91c64SSimon Glass 13099b66605SSimon GlassFinding implied CONFIGs 13199b66605SSimon Glass----------------------- 13299b66605SSimon Glass 13399b66605SSimon GlassSome CONFIG options can be implied by others and this can help to reduce 13499b66605SSimon Glassthe size of the defconfig files. For example, CONFIG_X86 implies 13599b66605SSimon GlassCONFIG_CMD_IRQ, so we can put 'imply CMD_IRQ' under 'config X86' and 13699b66605SSimon Glassall x86 boards will have that option, avoiding adding CONFIG_CMD_IRQ to 13799b66605SSimon Glasseach of the x86 defconfig files. 13899b66605SSimon Glass 13999b66605SSimon GlassThis tool can help find such configs. To use it, first build a database: 14099b66605SSimon Glass 14199b66605SSimon Glass ./tools/moveconfig.py -b 14299b66605SSimon Glass 14399b66605SSimon GlassThen try to query it: 14499b66605SSimon Glass 14599b66605SSimon Glass ./tools/moveconfig.py -i CONFIG_CMD_IRQ 14699b66605SSimon Glass CONFIG_CMD_IRQ found in 311/2384 defconfigs 14799b66605SSimon Glass 44 : CONFIG_SYS_FSL_ERRATUM_IFC_A002769 14899b66605SSimon Glass 41 : CONFIG_SYS_FSL_ERRATUM_A007075 14999b66605SSimon Glass 31 : CONFIG_SYS_FSL_DDR_VER_44 15099b66605SSimon Glass 28 : CONFIG_ARCH_P1010 15199b66605SSimon Glass 28 : CONFIG_SYS_FSL_ERRATUM_P1010_A003549 15299b66605SSimon Glass 28 : CONFIG_SYS_FSL_ERRATUM_SEC_A003571 15399b66605SSimon Glass 28 : CONFIG_SYS_FSL_ERRATUM_IFC_A003399 15499b66605SSimon Glass 25 : CONFIG_SYS_FSL_ERRATUM_A008044 15599b66605SSimon Glass 22 : CONFIG_ARCH_P1020 15699b66605SSimon Glass 21 : CONFIG_SYS_FSL_DDR_VER_46 15799b66605SSimon Glass 20 : CONFIG_MAX_PIRQ_LINKS 15899b66605SSimon Glass 20 : CONFIG_HPET_ADDRESS 15999b66605SSimon Glass 20 : CONFIG_X86 16099b66605SSimon Glass 20 : CONFIG_PCIE_ECAM_SIZE 16199b66605SSimon Glass 20 : CONFIG_IRQ_SLOT_COUNT 16299b66605SSimon Glass 20 : CONFIG_I8259_PIC 16399b66605SSimon Glass 20 : CONFIG_CPU_ADDR_BITS 16499b66605SSimon Glass 20 : CONFIG_RAMBASE 16599b66605SSimon Glass 20 : CONFIG_SYS_FSL_ERRATUM_A005871 16699b66605SSimon Glass 20 : CONFIG_PCIE_ECAM_BASE 16799b66605SSimon Glass 20 : CONFIG_X86_TSC_TIMER 16899b66605SSimon Glass 20 : CONFIG_I8254_TIMER 16999b66605SSimon Glass 20 : CONFIG_CMD_GETTIME 17099b66605SSimon Glass 19 : CONFIG_SYS_FSL_ERRATUM_A005812 17199b66605SSimon Glass 18 : CONFIG_X86_RUN_32BIT 17299b66605SSimon Glass 17 : CONFIG_CMD_CHIP_CONFIG 17399b66605SSimon Glass ... 17499b66605SSimon Glass 17599b66605SSimon GlassThis shows a list of config options which might imply CONFIG_CMD_EEPROM along 17699b66605SSimon Glasswith how many defconfigs they cover. From this you can see that CONFIG_X86 17799b66605SSimon Glassimplies CONFIG_CMD_EEPROM. Therefore, instead of adding CONFIG_CMD_EEPROM to 17899b66605SSimon Glassthe defconfig of every x86 board, you could add a single imply line to the 17999b66605SSimon GlassKconfig file: 18099b66605SSimon Glass 18199b66605SSimon Glass config X86 18299b66605SSimon Glass bool "x86 architecture" 18399b66605SSimon Glass ... 18499b66605SSimon Glass imply CMD_EEPROM 18599b66605SSimon Glass 18699b66605SSimon GlassThat will cover 20 defconfigs. Many of the options listed are not suitable as 18799b66605SSimon Glassthey are not related. E.g. it would be odd for CONFIG_CMD_GETTIME to imply 18899b66605SSimon GlassCMD_EEPROM. 18999b66605SSimon Glass 19099b66605SSimon GlassUsing this search you can reduce the size of moveconfig patches. 19199b66605SSimon Glass 192cb008830SSimon GlassYou can automatically add 'imply' statements in the Kconfig with the -a 193cb008830SSimon Glassoption: 194cb008830SSimon Glass 195cb008830SSimon Glass ./tools/moveconfig.py -s -i CONFIG_SCSI \ 196cb008830SSimon Glass -a CONFIG_ARCH_LS1021A,CONFIG_ARCH_LS1043A 197cb008830SSimon Glass 198cb008830SSimon GlassThis will add 'imply SCSI' to the two CONFIG options mentioned, assuming that 199cb008830SSimon Glassthe database indicates that they do actually imply CONFIG_SCSI and do not 200cb008830SSimon Glassalready have an 'imply SCSI'. 201cb008830SSimon Glass 202cb008830SSimon GlassThe output shows where the imply is added: 203cb008830SSimon Glass 204cb008830SSimon Glass 18 : CONFIG_ARCH_LS1021A arch/arm/cpu/armv7/ls102xa/Kconfig:1 205cb008830SSimon Glass 13 : CONFIG_ARCH_LS1043A arch/arm/cpu/armv8/fsl-layerscape/Kconfig:11 206cb008830SSimon Glass 12 : CONFIG_ARCH_LS1046A arch/arm/cpu/armv8/fsl-layerscape/Kconfig:31 207cb008830SSimon Glass 208cb008830SSimon GlassThe first number is the number of boards which can avoid having a special 209cb008830SSimon GlassCONFIG_SCSI option in their defconfig file if this 'imply' is added. 210cb008830SSimon GlassThe location at the right is the Kconfig file and line number where the config 211cb008830SSimon Glassappears. For example, adding 'imply CONFIG_SCSI' to the 'config ARCH_LS1021A' 212cb008830SSimon Glassin arch/arm/cpu/armv7/ls102xa/Kconfig at line 1 will help 18 boards to reduce 213cb008830SSimon Glassthe size of their defconfig files. 214cb008830SSimon Glass 215cb008830SSimon GlassIf you want to add an 'imply' to every imply config in the list, you can use 216cb008830SSimon Glass 217cb008830SSimon Glass ./tools/moveconfig.py -s -i CONFIG_SCSI -a all 218cb008830SSimon Glass 219cb008830SSimon GlassTo control which ones are displayed, use -I <list> where list is a list of 220cb008830SSimon Glassoptions (use '-I help' to see possible options and their meaning). 221cb008830SSimon Glass 222cb008830SSimon GlassTo skip showing you options that already have an 'imply' attached, use -A. 223cb008830SSimon Glass 224cb008830SSimon GlassWhen you have finished adding 'imply' options you can regenerate the 225cb008830SSimon Glassdefconfig files for affected boards with something like: 226cb008830SSimon Glass 227cb008830SSimon Glass git show --stat | ./tools/moveconfig.py -s -d - 228cb008830SSimon Glass 229cb008830SSimon GlassThis will regenerate only those defconfigs changed in the current commit. 230cb008830SSimon GlassIf you start with (say) 100 defconfigs being changed in the commit, and add 231cb008830SSimon Glassa few 'imply' options as above, then regenerate, hopefully you can reduce the 232cb008830SSimon Glassnumber of defconfigs changed in the commit. 233cb008830SSimon Glass 23499b66605SSimon Glass 2355a27c734SMasahiro YamadaAvailable options 2365a27c734SMasahiro Yamada----------------- 2375a27c734SMasahiro Yamada 2385a27c734SMasahiro Yamada -c, --color 2395a27c734SMasahiro Yamada Surround each portion of the log with escape sequences to display it 2405a27c734SMasahiro Yamada in color on the terminal. 2415a27c734SMasahiro Yamada 2429ede2123SSimon Glass -C, --commit 2439ede2123SSimon Glass Create a git commit with the changes when the operation is complete. A 2449ede2123SSimon Glass standard commit message is used which may need to be edited. 2459ede2123SSimon Glass 24691040e85SJoe Hershberger -d, --defconfigs 2470dbc9b59SMasahiro Yamada Specify a file containing a list of defconfigs to move. The defconfig 248ddf91c64SSimon Glass files can be given with shell-style wildcards. Use '-' to read from stdin. 24991040e85SJoe Hershberger 2505a27c734SMasahiro Yamada -n, --dry-run 251b6ef393aSMasahiro Yamada Perform a trial run that does not make any changes. It is useful to 2525a27c734SMasahiro Yamada see what is going to happen before one actually runs it. 2535a27c734SMasahiro Yamada 2545a27c734SMasahiro Yamada -e, --exit-on-error 2555a27c734SMasahiro Yamada Exit immediately if Make exits with a non-zero status while processing 2565a27c734SMasahiro Yamada a defconfig file. 2575a27c734SMasahiro Yamada 2588513dc04SMasahiro Yamada -s, --force-sync 2598513dc04SMasahiro Yamada Do "make savedefconfig" forcibly for all the defconfig files. 2608513dc04SMasahiro Yamada If not specified, "make savedefconfig" only occurs for cases 2618513dc04SMasahiro Yamada where at least one CONFIG was moved. 2628513dc04SMasahiro Yamada 26307913d1eSMasahiro Yamada -S, --spl 26407913d1eSMasahiro Yamada Look for moved config options in spl/include/autoconf.mk instead of 26507913d1eSMasahiro Yamada include/autoconf.mk. This is useful for moving options for SPL build 26607913d1eSMasahiro Yamada because SPL related options (mostly prefixed with CONFIG_SPL_) are 26707913d1eSMasahiro Yamada sometimes blocked by CONFIG_SPL_BUILD ifdef conditionals. 26807913d1eSMasahiro Yamada 2692144f880SJoe Hershberger -H, --headers-only 2702144f880SJoe Hershberger Only cleanup the headers; skip the defconfig processing 2712144f880SJoe Hershberger 2725a27c734SMasahiro Yamada -j, --jobs 2735a27c734SMasahiro Yamada Specify the number of threads to run simultaneously. If not specified, 2745a27c734SMasahiro Yamada the number of threads is the same as the number of CPU cores. 2755a27c734SMasahiro Yamada 2766b96c1a1SJoe Hershberger -r, --git-ref 2776b96c1a1SJoe Hershberger Specify the git ref to clone for building the autoconf.mk. If unspecified 2786b96c1a1SJoe Hershberger use the CWD. This is useful for when changes to the Kconfig affect the 2796b96c1a1SJoe Hershberger default values and you want to capture the state of the defconfig from 2806b96c1a1SJoe Hershberger before that change was in effect. If in doubt, specify a ref pre-Kconfig 2816b96c1a1SJoe Hershberger changes (use HEAD if Kconfig changes are not committed). Worst case it will 2826b96c1a1SJoe Hershberger take a bit longer to run, but will always do the right thing. 2836b96c1a1SJoe Hershberger 28495bf9c7eSJoe Hershberger -v, --verbose 28595bf9c7eSJoe Hershberger Show any build errors as boards are built 28695bf9c7eSJoe Hershberger 2876b403dfdSSimon Glass -y, --yes 2886b403dfdSSimon Glass Instead of prompting, automatically go ahead with all operations. This 289ddf91c64SSimon Glass includes cleaning up headers, CONFIG_SYS_EXTRA_OPTIONS, the config whitelist 290ddf91c64SSimon Glass and the README. 2916b403dfdSSimon Glass 2925a27c734SMasahiro YamadaTo see the complete list of supported options, run 2935a27c734SMasahiro Yamada 2945a27c734SMasahiro Yamada $ tools/moveconfig.py -h 2955a27c734SMasahiro Yamada 2965a27c734SMasahiro Yamada""" 2975a27c734SMasahiro Yamada 29899b66605SSimon Glassimport collections 2998ba1f5deSMasahiro Yamadaimport copy 300f2f6981aSMasahiro Yamadaimport difflib 301c8e1b10dSMasahiro Yamadaimport filecmp 3025a27c734SMasahiro Yamadaimport fnmatch 3030dbc9b59SMasahiro Yamadaimport glob 3045a27c734SMasahiro Yamadaimport multiprocessing 3055a27c734SMasahiro Yamadaimport optparse 3065a27c734SMasahiro Yamadaimport os 307d73fcb12SSimon Glassimport Queue 3085a27c734SMasahiro Yamadaimport re 3095a27c734SMasahiro Yamadaimport shutil 3105a27c734SMasahiro Yamadaimport subprocess 3115a27c734SMasahiro Yamadaimport sys 3125a27c734SMasahiro Yamadaimport tempfile 313d73fcb12SSimon Glassimport threading 3145a27c734SMasahiro Yamadaimport time 3155a27c734SMasahiro Yamada 316cb008830SSimon Glasssys.path.append(os.path.join(os.path.dirname(__file__), 'buildman')) 3176821a745SSimon Glasssys.path.append(os.path.join(os.path.dirname(__file__), 'patman')) 3186821a745SSimon Glassimport bsettings 319cb008830SSimon Glassimport kconfiglib 3206821a745SSimon Glassimport toolchain 321cb008830SSimon Glass 3225a27c734SMasahiro YamadaSHOW_GNU_MAKE = 'scripts/show-gnu-make' 3235a27c734SMasahiro YamadaSLEEP_TIME=0.03 3245a27c734SMasahiro Yamada 3255a27c734SMasahiro YamadaSTATE_IDLE = 0 3265a27c734SMasahiro YamadaSTATE_DEFCONFIG = 1 3275a27c734SMasahiro YamadaSTATE_AUTOCONF = 2 32896464badSJoe HershbergerSTATE_SAVEDEFCONFIG = 3 3295a27c734SMasahiro Yamada 3305a27c734SMasahiro YamadaACTION_MOVE = 0 331cc008299SMasahiro YamadaACTION_NO_ENTRY = 1 332916224c3SMasahiro YamadaACTION_NO_ENTRY_WARN = 2 333916224c3SMasahiro YamadaACTION_NO_CHANGE = 3 3345a27c734SMasahiro Yamada 3355a27c734SMasahiro YamadaCOLOR_BLACK = '0;30' 3365a27c734SMasahiro YamadaCOLOR_RED = '0;31' 3375a27c734SMasahiro YamadaCOLOR_GREEN = '0;32' 3385a27c734SMasahiro YamadaCOLOR_BROWN = '0;33' 3395a27c734SMasahiro YamadaCOLOR_BLUE = '0;34' 3405a27c734SMasahiro YamadaCOLOR_PURPLE = '0;35' 3415a27c734SMasahiro YamadaCOLOR_CYAN = '0;36' 3425a27c734SMasahiro YamadaCOLOR_LIGHT_GRAY = '0;37' 3435a27c734SMasahiro YamadaCOLOR_DARK_GRAY = '1;30' 3445a27c734SMasahiro YamadaCOLOR_LIGHT_RED = '1;31' 3455a27c734SMasahiro YamadaCOLOR_LIGHT_GREEN = '1;32' 3465a27c734SMasahiro YamadaCOLOR_YELLOW = '1;33' 3475a27c734SMasahiro YamadaCOLOR_LIGHT_BLUE = '1;34' 3485a27c734SMasahiro YamadaCOLOR_LIGHT_PURPLE = '1;35' 3495a27c734SMasahiro YamadaCOLOR_LIGHT_CYAN = '1;36' 3505a27c734SMasahiro YamadaCOLOR_WHITE = '1;37' 3515a27c734SMasahiro Yamada 352f3b8e647SSimon GlassAUTO_CONF_PATH = 'include/config/auto.conf' 353d73fcb12SSimon GlassCONFIG_DATABASE = 'moveconfig.db' 354f3b8e647SSimon Glass 355cb008830SSimon GlassCONFIG_LEN = len('CONFIG_') 356f3b8e647SSimon Glass 3575a27c734SMasahiro Yamada### helper functions ### 3585a27c734SMasahiro Yamadadef get_devnull(): 3595a27c734SMasahiro Yamada """Get the file object of '/dev/null' device.""" 3605a27c734SMasahiro Yamada try: 3615a27c734SMasahiro Yamada devnull = subprocess.DEVNULL # py3k 3625a27c734SMasahiro Yamada except AttributeError: 3635a27c734SMasahiro Yamada devnull = open(os.devnull, 'wb') 3645a27c734SMasahiro Yamada return devnull 3655a27c734SMasahiro Yamada 3665a27c734SMasahiro Yamadadef check_top_directory(): 3675a27c734SMasahiro Yamada """Exit if we are not at the top of source directory.""" 3685a27c734SMasahiro Yamada for f in ('README', 'Licenses'): 3695a27c734SMasahiro Yamada if not os.path.exists(f): 3705a27c734SMasahiro Yamada sys.exit('Please run at the top of source directory.') 3715a27c734SMasahiro Yamada 372bd63e5baSMasahiro Yamadadef check_clean_directory(): 373bd63e5baSMasahiro Yamada """Exit if the source tree is not clean.""" 374bd63e5baSMasahiro Yamada for f in ('.config', 'include/config'): 375bd63e5baSMasahiro Yamada if os.path.exists(f): 376bd63e5baSMasahiro Yamada sys.exit("source tree is not clean, please run 'make mrproper'") 377bd63e5baSMasahiro Yamada 3785a27c734SMasahiro Yamadadef get_make_cmd(): 3795a27c734SMasahiro Yamada """Get the command name of GNU Make. 3805a27c734SMasahiro Yamada 3815a27c734SMasahiro Yamada U-Boot needs GNU Make for building, but the command name is not 3825a27c734SMasahiro Yamada necessarily "make". (for example, "gmake" on FreeBSD). 3835a27c734SMasahiro Yamada Returns the most appropriate command name on your system. 3845a27c734SMasahiro Yamada """ 3855a27c734SMasahiro Yamada process = subprocess.Popen([SHOW_GNU_MAKE], stdout=subprocess.PIPE) 3865a27c734SMasahiro Yamada ret = process.communicate() 3875a27c734SMasahiro Yamada if process.returncode: 3885a27c734SMasahiro Yamada sys.exit('GNU Make not found') 3895a27c734SMasahiro Yamada return ret[0].rstrip() 3905a27c734SMasahiro Yamada 39125f978cbSSimon Glassdef get_matched_defconfig(line): 39225f978cbSSimon Glass """Get the defconfig files that match a pattern 39325f978cbSSimon Glass 39425f978cbSSimon Glass Args: 39525f978cbSSimon Glass line: Path or filename to match, e.g. 'configs/snow_defconfig' or 39625f978cbSSimon Glass 'k2*_defconfig'. If no directory is provided, 'configs/' is 39725f978cbSSimon Glass prepended 39825f978cbSSimon Glass 39925f978cbSSimon Glass Returns: 40025f978cbSSimon Glass a list of matching defconfig files 40125f978cbSSimon Glass """ 40225f978cbSSimon Glass dirname = os.path.dirname(line) 40325f978cbSSimon Glass if dirname: 40425f978cbSSimon Glass pattern = line 40525f978cbSSimon Glass else: 40625f978cbSSimon Glass pattern = os.path.join('configs', line) 40725f978cbSSimon Glass return glob.glob(pattern) + glob.glob(pattern + '_defconfig') 40825f978cbSSimon Glass 4090dbc9b59SMasahiro Yamadadef get_matched_defconfigs(defconfigs_file): 410ee4e61bdSSimon Glass """Get all the defconfig files that match the patterns in a file. 411ee4e61bdSSimon Glass 412ee4e61bdSSimon Glass Args: 413ee4e61bdSSimon Glass defconfigs_file: File containing a list of defconfigs to process, or 414ee4e61bdSSimon Glass '-' to read the list from stdin 415ee4e61bdSSimon Glass 416ee4e61bdSSimon Glass Returns: 417ee4e61bdSSimon Glass A list of paths to defconfig files, with no duplicates 418ee4e61bdSSimon Glass """ 4190dbc9b59SMasahiro Yamada defconfigs = [] 420ee4e61bdSSimon Glass if defconfigs_file == '-': 421ee4e61bdSSimon Glass fd = sys.stdin 422ee4e61bdSSimon Glass defconfigs_file = 'stdin' 423ee4e61bdSSimon Glass else: 424ee4e61bdSSimon Glass fd = open(defconfigs_file) 425ee4e61bdSSimon Glass for i, line in enumerate(fd): 4260dbc9b59SMasahiro Yamada line = line.strip() 4270dbc9b59SMasahiro Yamada if not line: 4280dbc9b59SMasahiro Yamada continue # skip blank lines silently 4292ddd85dcSSimon Glass if ' ' in line: 4302ddd85dcSSimon Glass line = line.split(' ')[0] # handle 'git log' input 43125f978cbSSimon Glass matched = get_matched_defconfig(line) 4320dbc9b59SMasahiro Yamada if not matched: 4330dbc9b59SMasahiro Yamada print >> sys.stderr, "warning: %s:%d: no defconfig matched '%s'" % \ 4340dbc9b59SMasahiro Yamada (defconfigs_file, i + 1, line) 4350dbc9b59SMasahiro Yamada 4360dbc9b59SMasahiro Yamada defconfigs += matched 4370dbc9b59SMasahiro Yamada 4380dbc9b59SMasahiro Yamada # use set() to drop multiple matching 4390dbc9b59SMasahiro Yamada return [ defconfig[len('configs') + 1:] for defconfig in set(defconfigs) ] 4400dbc9b59SMasahiro Yamada 441684c306eSMasahiro Yamadadef get_all_defconfigs(): 442684c306eSMasahiro Yamada """Get all the defconfig files under the configs/ directory.""" 443684c306eSMasahiro Yamada defconfigs = [] 444684c306eSMasahiro Yamada for (dirpath, dirnames, filenames) in os.walk('configs'): 445684c306eSMasahiro Yamada dirpath = dirpath[len('configs') + 1:] 446684c306eSMasahiro Yamada for filename in fnmatch.filter(filenames, '*_defconfig'): 447684c306eSMasahiro Yamada defconfigs.append(os.path.join(dirpath, filename)) 448684c306eSMasahiro Yamada 449684c306eSMasahiro Yamada return defconfigs 450684c306eSMasahiro Yamada 4515a27c734SMasahiro Yamadadef color_text(color_enabled, color, string): 4525a27c734SMasahiro Yamada """Return colored string.""" 4535a27c734SMasahiro Yamada if color_enabled: 4541d085568SMasahiro Yamada # LF should not be surrounded by the escape sequence. 4551d085568SMasahiro Yamada # Otherwise, additional whitespace or line-feed might be printed. 4561d085568SMasahiro Yamada return '\n'.join([ '\033[' + color + 'm' + s + '\033[0m' if s else '' 4571d085568SMasahiro Yamada for s in string.split('\n') ]) 4585a27c734SMasahiro Yamada else: 4595a27c734SMasahiro Yamada return string 4605a27c734SMasahiro Yamada 461e9ea1221SMasahiro Yamadadef show_diff(a, b, file_path, color_enabled): 462f2f6981aSMasahiro Yamada """Show unidified diff. 463f2f6981aSMasahiro Yamada 464f2f6981aSMasahiro Yamada Arguments: 465f2f6981aSMasahiro Yamada a: A list of lines (before) 466f2f6981aSMasahiro Yamada b: A list of lines (after) 467f2f6981aSMasahiro Yamada file_path: Path to the file 468e9ea1221SMasahiro Yamada color_enabled: Display the diff in color 469f2f6981aSMasahiro Yamada """ 470f2f6981aSMasahiro Yamada 471f2f6981aSMasahiro Yamada diff = difflib.unified_diff(a, b, 472f2f6981aSMasahiro Yamada fromfile=os.path.join('a', file_path), 473f2f6981aSMasahiro Yamada tofile=os.path.join('b', file_path)) 474f2f6981aSMasahiro Yamada 475f2f6981aSMasahiro Yamada for line in diff: 476e9ea1221SMasahiro Yamada if line[0] == '-' and line[1] != '-': 477e9ea1221SMasahiro Yamada print color_text(color_enabled, COLOR_RED, line), 478e9ea1221SMasahiro Yamada elif line[0] == '+' and line[1] != '+': 479e9ea1221SMasahiro Yamada print color_text(color_enabled, COLOR_GREEN, line), 480e9ea1221SMasahiro Yamada else: 481f2f6981aSMasahiro Yamada print line, 482f2f6981aSMasahiro Yamada 4838ba1f5deSMasahiro Yamadadef extend_matched_lines(lines, matched, pre_patterns, post_patterns, extend_pre, 4848ba1f5deSMasahiro Yamada extend_post): 4858ba1f5deSMasahiro Yamada """Extend matched lines if desired patterns are found before/after already 4868ba1f5deSMasahiro Yamada matched lines. 4878ba1f5deSMasahiro Yamada 4888ba1f5deSMasahiro Yamada Arguments: 4898ba1f5deSMasahiro Yamada lines: A list of lines handled. 4908ba1f5deSMasahiro Yamada matched: A list of line numbers that have been already matched. 4918ba1f5deSMasahiro Yamada (will be updated by this function) 4928ba1f5deSMasahiro Yamada pre_patterns: A list of regular expression that should be matched as 4938ba1f5deSMasahiro Yamada preamble. 4948ba1f5deSMasahiro Yamada post_patterns: A list of regular expression that should be matched as 4958ba1f5deSMasahiro Yamada postamble. 4968ba1f5deSMasahiro Yamada extend_pre: Add the line number of matched preamble to the matched list. 4978ba1f5deSMasahiro Yamada extend_post: Add the line number of matched postamble to the matched list. 4988ba1f5deSMasahiro Yamada """ 4998ba1f5deSMasahiro Yamada extended_matched = [] 5008ba1f5deSMasahiro Yamada 5018ba1f5deSMasahiro Yamada j = matched[0] 5028ba1f5deSMasahiro Yamada 5038ba1f5deSMasahiro Yamada for i in matched: 5048ba1f5deSMasahiro Yamada if i == 0 or i < j: 5058ba1f5deSMasahiro Yamada continue 5068ba1f5deSMasahiro Yamada j = i 5078ba1f5deSMasahiro Yamada while j in matched: 5088ba1f5deSMasahiro Yamada j += 1 5098ba1f5deSMasahiro Yamada if j >= len(lines): 5108ba1f5deSMasahiro Yamada break 5118ba1f5deSMasahiro Yamada 5128ba1f5deSMasahiro Yamada for p in pre_patterns: 5138ba1f5deSMasahiro Yamada if p.search(lines[i - 1]): 5148ba1f5deSMasahiro Yamada break 5158ba1f5deSMasahiro Yamada else: 5168ba1f5deSMasahiro Yamada # not matched 5178ba1f5deSMasahiro Yamada continue 5188ba1f5deSMasahiro Yamada 5198ba1f5deSMasahiro Yamada for p in post_patterns: 5208ba1f5deSMasahiro Yamada if p.search(lines[j]): 5218ba1f5deSMasahiro Yamada break 5228ba1f5deSMasahiro Yamada else: 5238ba1f5deSMasahiro Yamada # not matched 5248ba1f5deSMasahiro Yamada continue 5258ba1f5deSMasahiro Yamada 5268ba1f5deSMasahiro Yamada if extend_pre: 5278ba1f5deSMasahiro Yamada extended_matched.append(i - 1) 5288ba1f5deSMasahiro Yamada if extend_post: 5298ba1f5deSMasahiro Yamada extended_matched.append(j) 5308ba1f5deSMasahiro Yamada 5318ba1f5deSMasahiro Yamada matched += extended_matched 5328ba1f5deSMasahiro Yamada matched.sort() 5338ba1f5deSMasahiro Yamada 53485edfc1fSChris Packhamdef confirm(options, prompt): 53585edfc1fSChris Packham if not options.yes: 53685edfc1fSChris Packham while True: 53785edfc1fSChris Packham choice = raw_input('{} [y/n]: '.format(prompt)) 53885edfc1fSChris Packham choice = choice.lower() 53985edfc1fSChris Packham print choice 54085edfc1fSChris Packham if choice == 'y' or choice == 'n': 54185edfc1fSChris Packham break 54285edfc1fSChris Packham 54385edfc1fSChris Packham if choice == 'n': 54485edfc1fSChris Packham return False 54585edfc1fSChris Packham 54685edfc1fSChris Packham return True 54785edfc1fSChris Packham 548*4d9dbb1fSChris Packhamdef cleanup_empty_blocks(header_path, options): 549*4d9dbb1fSChris Packham """Clean up empty conditional blocks 550*4d9dbb1fSChris Packham 551*4d9dbb1fSChris Packham Arguments: 552*4d9dbb1fSChris Packham header_path: path to the cleaned file. 553*4d9dbb1fSChris Packham options: option flags. 554*4d9dbb1fSChris Packham """ 555*4d9dbb1fSChris Packham pattern = re.compile(r'^\s*#\s*if.*$\n^\s*#\s*endif.*$\n*', flags=re.M) 556*4d9dbb1fSChris Packham with open(header_path) as f: 557*4d9dbb1fSChris Packham data = f.read() 558*4d9dbb1fSChris Packham 559*4d9dbb1fSChris Packham new_data = pattern.sub('\n', data) 560*4d9dbb1fSChris Packham 561*4d9dbb1fSChris Packham show_diff(data.splitlines(True), new_data.splitlines(True), header_path, 562*4d9dbb1fSChris Packham options.color) 563*4d9dbb1fSChris Packham 564*4d9dbb1fSChris Packham if options.dry_run: 565*4d9dbb1fSChris Packham return 566*4d9dbb1fSChris Packham 567*4d9dbb1fSChris Packham with open(header_path, 'w') as f: 568*4d9dbb1fSChris Packham f.write(new_data) 569*4d9dbb1fSChris Packham 570e9ea1221SMasahiro Yamadadef cleanup_one_header(header_path, patterns, options): 5715a27c734SMasahiro Yamada """Clean regex-matched lines away from a file. 5725a27c734SMasahiro Yamada 5735a27c734SMasahiro Yamada Arguments: 5745a27c734SMasahiro Yamada header_path: path to the cleaned file. 5755a27c734SMasahiro Yamada patterns: list of regex patterns. Any lines matching to these 5765a27c734SMasahiro Yamada patterns are deleted. 577e9ea1221SMasahiro Yamada options: option flags. 5785a27c734SMasahiro Yamada """ 5795a27c734SMasahiro Yamada with open(header_path) as f: 5805a27c734SMasahiro Yamada lines = f.readlines() 5815a27c734SMasahiro Yamada 5825a27c734SMasahiro Yamada matched = [] 5835a27c734SMasahiro Yamada for i, line in enumerate(lines): 584a3a779f7SMasahiro Yamada if i - 1 in matched and lines[i - 1][-2:] == '\\\n': 585a3a779f7SMasahiro Yamada matched.append(i) 586a3a779f7SMasahiro Yamada continue 5875a27c734SMasahiro Yamada for pattern in patterns: 5888ba1f5deSMasahiro Yamada if pattern.search(line): 5895a27c734SMasahiro Yamada matched.append(i) 5905a27c734SMasahiro Yamada break 5915a27c734SMasahiro Yamada 5928ba1f5deSMasahiro Yamada if not matched: 5938ba1f5deSMasahiro Yamada return 5948ba1f5deSMasahiro Yamada 5958ba1f5deSMasahiro Yamada # remove empty #ifdef ... #endif, successive blank lines 5968ba1f5deSMasahiro Yamada pattern_if = re.compile(r'#\s*if(def|ndef)?\W') # #if, #ifdef, #ifndef 5978ba1f5deSMasahiro Yamada pattern_elif = re.compile(r'#\s*el(if|se)\W') # #elif, #else 5988ba1f5deSMasahiro Yamada pattern_endif = re.compile(r'#\s*endif\W') # #endif 5998ba1f5deSMasahiro Yamada pattern_blank = re.compile(r'^\s*$') # empty line 6008ba1f5deSMasahiro Yamada 6018ba1f5deSMasahiro Yamada while True: 6028ba1f5deSMasahiro Yamada old_matched = copy.copy(matched) 6038ba1f5deSMasahiro Yamada extend_matched_lines(lines, matched, [pattern_if], 6048ba1f5deSMasahiro Yamada [pattern_endif], True, True) 6058ba1f5deSMasahiro Yamada extend_matched_lines(lines, matched, [pattern_elif], 6068ba1f5deSMasahiro Yamada [pattern_elif, pattern_endif], True, False) 6078ba1f5deSMasahiro Yamada extend_matched_lines(lines, matched, [pattern_if, pattern_elif], 6088ba1f5deSMasahiro Yamada [pattern_blank], False, True) 6098ba1f5deSMasahiro Yamada extend_matched_lines(lines, matched, [pattern_blank], 6108ba1f5deSMasahiro Yamada [pattern_elif, pattern_endif], True, False) 6118ba1f5deSMasahiro Yamada extend_matched_lines(lines, matched, [pattern_blank], 6128ba1f5deSMasahiro Yamada [pattern_blank], True, False) 6138ba1f5deSMasahiro Yamada if matched == old_matched: 6148ba1f5deSMasahiro Yamada break 6158ba1f5deSMasahiro Yamada 616f2f6981aSMasahiro Yamada tolines = copy.copy(lines) 617f2f6981aSMasahiro Yamada 618f2f6981aSMasahiro Yamada for i in reversed(matched): 619f2f6981aSMasahiro Yamada tolines.pop(i) 620f2f6981aSMasahiro Yamada 621e9ea1221SMasahiro Yamada show_diff(lines, tolines, header_path, options.color) 6228ba1f5deSMasahiro Yamada 623e9ea1221SMasahiro Yamada if options.dry_run: 6245a27c734SMasahiro Yamada return 6255a27c734SMasahiro Yamada 6265a27c734SMasahiro Yamada with open(header_path, 'w') as f: 627f2f6981aSMasahiro Yamada for line in tolines: 6285a27c734SMasahiro Yamada f.write(line) 6295a27c734SMasahiro Yamada 630e9ea1221SMasahiro Yamadadef cleanup_headers(configs, options): 6315a27c734SMasahiro Yamada """Delete config defines from board headers. 6325a27c734SMasahiro Yamada 6335a27c734SMasahiro Yamada Arguments: 634b134bc13SMasahiro Yamada configs: A list of CONFIGs to remove. 635e9ea1221SMasahiro Yamada options: option flags. 6365a27c734SMasahiro Yamada """ 63785edfc1fSChris Packham if not confirm(options, 'Clean up headers?'): 6385a27c734SMasahiro Yamada return 6395a27c734SMasahiro Yamada 6405a27c734SMasahiro Yamada patterns = [] 641b134bc13SMasahiro Yamada for config in configs: 6425a27c734SMasahiro Yamada patterns.append(re.compile(r'#\s*define\s+%s\W' % config)) 6435a27c734SMasahiro Yamada patterns.append(re.compile(r'#\s*undef\s+%s\W' % config)) 6445a27c734SMasahiro Yamada 64560727f51SJoe Hershberger for dir in 'include', 'arch', 'board': 64660727f51SJoe Hershberger for (dirpath, dirnames, filenames) in os.walk(dir): 647dc6de50bSMasahiro Yamada if dirpath == os.path.join('include', 'generated'): 648dc6de50bSMasahiro Yamada continue 6495a27c734SMasahiro Yamada for filename in filenames: 6505a27c734SMasahiro Yamada if not fnmatch.fnmatch(filename, '*~'): 651*4d9dbb1fSChris Packham header_path = os.path.join(dirpath, filename) 652*4d9dbb1fSChris Packham cleanup_one_header(header_path, patterns, options) 653*4d9dbb1fSChris Packham cleanup_empty_blocks(header_path, options) 6545a27c734SMasahiro Yamada 6559ab0296aSMasahiro Yamadadef cleanup_one_extra_option(defconfig_path, configs, options): 6569ab0296aSMasahiro Yamada """Delete config defines in CONFIG_SYS_EXTRA_OPTIONS in one defconfig file. 6579ab0296aSMasahiro Yamada 6589ab0296aSMasahiro Yamada Arguments: 6599ab0296aSMasahiro Yamada defconfig_path: path to the cleaned defconfig file. 6609ab0296aSMasahiro Yamada configs: A list of CONFIGs to remove. 6619ab0296aSMasahiro Yamada options: option flags. 6629ab0296aSMasahiro Yamada """ 6639ab0296aSMasahiro Yamada 6649ab0296aSMasahiro Yamada start = 'CONFIG_SYS_EXTRA_OPTIONS="' 6659ab0296aSMasahiro Yamada end = '"\n' 6669ab0296aSMasahiro Yamada 6679ab0296aSMasahiro Yamada with open(defconfig_path) as f: 6689ab0296aSMasahiro Yamada lines = f.readlines() 6699ab0296aSMasahiro Yamada 6709ab0296aSMasahiro Yamada for i, line in enumerate(lines): 6719ab0296aSMasahiro Yamada if line.startswith(start) and line.endswith(end): 6729ab0296aSMasahiro Yamada break 6739ab0296aSMasahiro Yamada else: 6749ab0296aSMasahiro Yamada # CONFIG_SYS_EXTRA_OPTIONS was not found in this defconfig 6759ab0296aSMasahiro Yamada return 6769ab0296aSMasahiro Yamada 6779ab0296aSMasahiro Yamada old_tokens = line[len(start):-len(end)].split(',') 6789ab0296aSMasahiro Yamada new_tokens = [] 6799ab0296aSMasahiro Yamada 6809ab0296aSMasahiro Yamada for token in old_tokens: 6819ab0296aSMasahiro Yamada pos = token.find('=') 6829ab0296aSMasahiro Yamada if not (token[:pos] if pos >= 0 else token) in configs: 6839ab0296aSMasahiro Yamada new_tokens.append(token) 6849ab0296aSMasahiro Yamada 6859ab0296aSMasahiro Yamada if new_tokens == old_tokens: 6869ab0296aSMasahiro Yamada return 6879ab0296aSMasahiro Yamada 6889ab0296aSMasahiro Yamada tolines = copy.copy(lines) 6899ab0296aSMasahiro Yamada 6909ab0296aSMasahiro Yamada if new_tokens: 6919ab0296aSMasahiro Yamada tolines[i] = start + ','.join(new_tokens) + end 6929ab0296aSMasahiro Yamada else: 6939ab0296aSMasahiro Yamada tolines.pop(i) 6949ab0296aSMasahiro Yamada 6959ab0296aSMasahiro Yamada show_diff(lines, tolines, defconfig_path, options.color) 6969ab0296aSMasahiro Yamada 6979ab0296aSMasahiro Yamada if options.dry_run: 6989ab0296aSMasahiro Yamada return 6999ab0296aSMasahiro Yamada 7009ab0296aSMasahiro Yamada with open(defconfig_path, 'w') as f: 7019ab0296aSMasahiro Yamada for line in tolines: 7029ab0296aSMasahiro Yamada f.write(line) 7039ab0296aSMasahiro Yamada 7049ab0296aSMasahiro Yamadadef cleanup_extra_options(configs, options): 7059ab0296aSMasahiro Yamada """Delete config defines in CONFIG_SYS_EXTRA_OPTIONS in defconfig files. 7069ab0296aSMasahiro Yamada 7079ab0296aSMasahiro Yamada Arguments: 7089ab0296aSMasahiro Yamada configs: A list of CONFIGs to remove. 7099ab0296aSMasahiro Yamada options: option flags. 7109ab0296aSMasahiro Yamada """ 71185edfc1fSChris Packham if not confirm(options, 'Clean up CONFIG_SYS_EXTRA_OPTIONS?'): 7129ab0296aSMasahiro Yamada return 7139ab0296aSMasahiro Yamada 7149ab0296aSMasahiro Yamada configs = [ config[len('CONFIG_'):] for config in configs ] 7159ab0296aSMasahiro Yamada 7169ab0296aSMasahiro Yamada defconfigs = get_all_defconfigs() 7179ab0296aSMasahiro Yamada 7189ab0296aSMasahiro Yamada for defconfig in defconfigs: 7199ab0296aSMasahiro Yamada cleanup_one_extra_option(os.path.join('configs', defconfig), configs, 7209ab0296aSMasahiro Yamada options) 7219ab0296aSMasahiro Yamada 722ca43834dSChris Packhamdef cleanup_whitelist(configs, options): 723ca43834dSChris Packham """Delete config whitelist entries 724ca43834dSChris Packham 725ca43834dSChris Packham Arguments: 726ca43834dSChris Packham configs: A list of CONFIGs to remove. 727ca43834dSChris Packham options: option flags. 728ca43834dSChris Packham """ 729ca43834dSChris Packham if not confirm(options, 'Clean up whitelist entries?'): 730ca43834dSChris Packham return 731ca43834dSChris Packham 732ca43834dSChris Packham with open(os.path.join('scripts', 'config_whitelist.txt')) as f: 733ca43834dSChris Packham lines = f.readlines() 734ca43834dSChris Packham 735ca43834dSChris Packham lines = [x for x in lines if x.strip() not in configs] 736ca43834dSChris Packham 737ca43834dSChris Packham with open(os.path.join('scripts', 'config_whitelist.txt'), 'w') as f: 738ca43834dSChris Packham f.write(''.join(lines)) 739ca43834dSChris Packham 740f90df596SChris Packhamdef find_matching(patterns, line): 741f90df596SChris Packham for pat in patterns: 742f90df596SChris Packham if pat.search(line): 743f90df596SChris Packham return True 744f90df596SChris Packham return False 745f90df596SChris Packham 746f90df596SChris Packhamdef cleanup_readme(configs, options): 747f90df596SChris Packham """Delete config description in README 748f90df596SChris Packham 749f90df596SChris Packham Arguments: 750f90df596SChris Packham configs: A list of CONFIGs to remove. 751f90df596SChris Packham options: option flags. 752f90df596SChris Packham """ 753f90df596SChris Packham if not confirm(options, 'Clean up README?'): 754f90df596SChris Packham return 755f90df596SChris Packham 756f90df596SChris Packham patterns = [] 757f90df596SChris Packham for config in configs: 758f90df596SChris Packham patterns.append(re.compile(r'^\s+%s' % config)) 759f90df596SChris Packham 760f90df596SChris Packham with open('README') as f: 761f90df596SChris Packham lines = f.readlines() 762f90df596SChris Packham 763f90df596SChris Packham found = False 764f90df596SChris Packham newlines = [] 765f90df596SChris Packham for line in lines: 766f90df596SChris Packham if not found: 767f90df596SChris Packham found = find_matching(patterns, line) 768f90df596SChris Packham if found: 769f90df596SChris Packham continue 770f90df596SChris Packham 771f90df596SChris Packham if found and re.search(r'^\s+CONFIG', line): 772f90df596SChris Packham found = False 773f90df596SChris Packham 774f90df596SChris Packham if not found: 775f90df596SChris Packham newlines.append(line) 776f90df596SChris Packham 777f90df596SChris Packham with open('README', 'w') as f: 778f90df596SChris Packham f.write(''.join(newlines)) 779f90df596SChris Packham 780ca43834dSChris Packham 7815a27c734SMasahiro Yamada### classes ### 782c5e60fd4SMasahiro Yamadaclass Progress: 783c5e60fd4SMasahiro Yamada 784c5e60fd4SMasahiro Yamada """Progress Indicator""" 785c5e60fd4SMasahiro Yamada 786c5e60fd4SMasahiro Yamada def __init__(self, total): 787c5e60fd4SMasahiro Yamada """Create a new progress indicator. 788c5e60fd4SMasahiro Yamada 789c5e60fd4SMasahiro Yamada Arguments: 790c5e60fd4SMasahiro Yamada total: A number of defconfig files to process. 791c5e60fd4SMasahiro Yamada """ 792c5e60fd4SMasahiro Yamada self.current = 0 793c5e60fd4SMasahiro Yamada self.total = total 794c5e60fd4SMasahiro Yamada 795c5e60fd4SMasahiro Yamada def inc(self): 796c5e60fd4SMasahiro Yamada """Increment the number of processed defconfig files.""" 797c5e60fd4SMasahiro Yamada 798c5e60fd4SMasahiro Yamada self.current += 1 799c5e60fd4SMasahiro Yamada 800c5e60fd4SMasahiro Yamada def show(self): 801c5e60fd4SMasahiro Yamada """Display the progress.""" 802c5e60fd4SMasahiro Yamada print ' %d defconfigs out of %d\r' % (self.current, self.total), 803c5e60fd4SMasahiro Yamada sys.stdout.flush() 804c5e60fd4SMasahiro Yamada 805cb008830SSimon Glass 806cb008830SSimon Glassclass KconfigScanner: 807cb008830SSimon Glass """Kconfig scanner.""" 808cb008830SSimon Glass 809cb008830SSimon Glass def __init__(self): 810cb008830SSimon Glass """Scan all the Kconfig files and create a Config object.""" 811cb008830SSimon Glass # Define environment variables referenced from Kconfig 812cb008830SSimon Glass os.environ['srctree'] = os.getcwd() 813cb008830SSimon Glass os.environ['UBOOTVERSION'] = 'dummy' 814cb008830SSimon Glass os.environ['KCONFIG_OBJDIR'] = '' 815cb008830SSimon Glass self.conf = kconfiglib.Config() 816cb008830SSimon Glass 817cb008830SSimon Glass 8185a27c734SMasahiro Yamadaclass KconfigParser: 8195a27c734SMasahiro Yamada 8205a27c734SMasahiro Yamada """A parser of .config and include/autoconf.mk.""" 8215a27c734SMasahiro Yamada 8225a27c734SMasahiro Yamada re_arch = re.compile(r'CONFIG_SYS_ARCH="(.*)"') 8235a27c734SMasahiro Yamada re_cpu = re.compile(r'CONFIG_SYS_CPU="(.*)"') 8245a27c734SMasahiro Yamada 825522e8dcbSMasahiro Yamada def __init__(self, configs, options, build_dir): 8265a27c734SMasahiro Yamada """Create a new parser. 8275a27c734SMasahiro Yamada 8285a27c734SMasahiro Yamada Arguments: 829b134bc13SMasahiro Yamada configs: A list of CONFIGs to move. 8305a27c734SMasahiro Yamada options: option flags. 8315a27c734SMasahiro Yamada build_dir: Build directory. 8325a27c734SMasahiro Yamada """ 833b134bc13SMasahiro Yamada self.configs = configs 8345a27c734SMasahiro Yamada self.options = options 8351f16992eSMasahiro Yamada self.dotconfig = os.path.join(build_dir, '.config') 8361f16992eSMasahiro Yamada self.autoconf = os.path.join(build_dir, 'include', 'autoconf.mk') 83707913d1eSMasahiro Yamada self.spl_autoconf = os.path.join(build_dir, 'spl', 'include', 83807913d1eSMasahiro Yamada 'autoconf.mk') 839f3b8e647SSimon Glass self.config_autoconf = os.path.join(build_dir, AUTO_CONF_PATH) 8405da4f857SMasahiro Yamada self.defconfig = os.path.join(build_dir, 'defconfig') 8415a27c734SMasahiro Yamada 8426821a745SSimon Glass def get_arch(self): 8436821a745SSimon Glass """Parse .config file and return the architecture. 8445a27c734SMasahiro Yamada 8455a27c734SMasahiro Yamada Returns: 8466821a745SSimon Glass Architecture name (e.g. 'arm'). 8475a27c734SMasahiro Yamada """ 8485a27c734SMasahiro Yamada arch = '' 8495a27c734SMasahiro Yamada cpu = '' 8501f16992eSMasahiro Yamada for line in open(self.dotconfig): 8515a27c734SMasahiro Yamada m = self.re_arch.match(line) 8525a27c734SMasahiro Yamada if m: 8535a27c734SMasahiro Yamada arch = m.group(1) 8545a27c734SMasahiro Yamada continue 8555a27c734SMasahiro Yamada m = self.re_cpu.match(line) 8565a27c734SMasahiro Yamada if m: 8575a27c734SMasahiro Yamada cpu = m.group(1) 8585a27c734SMasahiro Yamada 85990ed6cbaSMasahiro Yamada if not arch: 86090ed6cbaSMasahiro Yamada return None 8615a27c734SMasahiro Yamada 8625a27c734SMasahiro Yamada # fix-up for aarch64 8635a27c734SMasahiro Yamada if arch == 'arm' and cpu == 'armv8': 8645a27c734SMasahiro Yamada arch = 'aarch64' 8655a27c734SMasahiro Yamada 8666821a745SSimon Glass return arch 8675a27c734SMasahiro Yamada 868b134bc13SMasahiro Yamada def parse_one_config(self, config, dotconfig_lines, autoconf_lines): 8695a27c734SMasahiro Yamada """Parse .config, defconfig, include/autoconf.mk for one config. 8705a27c734SMasahiro Yamada 8715a27c734SMasahiro Yamada This function looks for the config options in the lines from 8725a27c734SMasahiro Yamada defconfig, .config, and include/autoconf.mk in order to decide 8735a27c734SMasahiro Yamada which action should be taken for this defconfig. 8745a27c734SMasahiro Yamada 8755a27c734SMasahiro Yamada Arguments: 876b134bc13SMasahiro Yamada config: CONFIG name to parse. 877cc008299SMasahiro Yamada dotconfig_lines: lines from the .config file. 8785a27c734SMasahiro Yamada autoconf_lines: lines from the include/autoconf.mk file. 8795a27c734SMasahiro Yamada 8805a27c734SMasahiro Yamada Returns: 8815a27c734SMasahiro Yamada A tupple of the action for this defconfig and the line 8825a27c734SMasahiro Yamada matched for the config. 8835a27c734SMasahiro Yamada """ 8845a27c734SMasahiro Yamada not_set = '# %s is not set' % config 8855a27c734SMasahiro Yamada 8865a27c734SMasahiro Yamada for line in autoconf_lines: 8875a27c734SMasahiro Yamada line = line.rstrip() 8885a27c734SMasahiro Yamada if line.startswith(config + '='): 889cc008299SMasahiro Yamada new_val = line 8905a27c734SMasahiro Yamada break 8915a27c734SMasahiro Yamada else: 892cc008299SMasahiro Yamada new_val = not_set 8935a27c734SMasahiro Yamada 894916224c3SMasahiro Yamada for line in dotconfig_lines: 895916224c3SMasahiro Yamada line = line.rstrip() 896916224c3SMasahiro Yamada if line.startswith(config + '=') or line == not_set: 897916224c3SMasahiro Yamada old_val = line 898916224c3SMasahiro Yamada break 899916224c3SMasahiro Yamada else: 900916224c3SMasahiro Yamada if new_val == not_set: 901916224c3SMasahiro Yamada return (ACTION_NO_ENTRY, config) 902916224c3SMasahiro Yamada else: 903916224c3SMasahiro Yamada return (ACTION_NO_ENTRY_WARN, config) 904916224c3SMasahiro Yamada 905cc008299SMasahiro Yamada # If this CONFIG is neither bool nor trisate 906cc008299SMasahiro Yamada if old_val[-2:] != '=y' and old_val[-2:] != '=m' and old_val != not_set: 907cc008299SMasahiro Yamada # tools/scripts/define2mk.sed changes '1' to 'y'. 908cc008299SMasahiro Yamada # This is a problem if the CONFIG is int type. 909cc008299SMasahiro Yamada # Check the type in Kconfig and handle it correctly. 910cc008299SMasahiro Yamada if new_val[-2:] == '=y': 911cc008299SMasahiro Yamada new_val = new_val[:-1] + '1' 912cc008299SMasahiro Yamada 9135030159eSMasahiro Yamada return (ACTION_NO_CHANGE if old_val == new_val else ACTION_MOVE, 9145030159eSMasahiro Yamada new_val) 9155a27c734SMasahiro Yamada 9161d085568SMasahiro Yamada def update_dotconfig(self): 9176ff36d21SMasahiro Yamada """Parse files for the config options and update the .config. 9185a27c734SMasahiro Yamada 919cc008299SMasahiro Yamada This function parses the generated .config and include/autoconf.mk 920cc008299SMasahiro Yamada searching the target options. 9216ff36d21SMasahiro Yamada Move the config option(s) to the .config as needed. 9225a27c734SMasahiro Yamada 9235a27c734SMasahiro Yamada Arguments: 9245a27c734SMasahiro Yamada defconfig: defconfig name. 925522e8dcbSMasahiro Yamada 926522e8dcbSMasahiro Yamada Returns: 9277fb0bacdSMasahiro Yamada Return a tuple of (updated flag, log string). 9287fb0bacdSMasahiro Yamada The "updated flag" is True if the .config was updated, False 9297fb0bacdSMasahiro Yamada otherwise. The "log string" shows what happend to the .config. 9305a27c734SMasahiro Yamada """ 9315a27c734SMasahiro Yamada 9325a27c734SMasahiro Yamada results = [] 9337fb0bacdSMasahiro Yamada updated = False 934916224c3SMasahiro Yamada suspicious = False 93507913d1eSMasahiro Yamada rm_files = [self.config_autoconf, self.autoconf] 93607913d1eSMasahiro Yamada 93707913d1eSMasahiro Yamada if self.options.spl: 93807913d1eSMasahiro Yamada if os.path.exists(self.spl_autoconf): 93907913d1eSMasahiro Yamada autoconf_path = self.spl_autoconf 94007913d1eSMasahiro Yamada rm_files.append(self.spl_autoconf) 94107913d1eSMasahiro Yamada else: 94207913d1eSMasahiro Yamada for f in rm_files: 94307913d1eSMasahiro Yamada os.remove(f) 94407913d1eSMasahiro Yamada return (updated, suspicious, 94507913d1eSMasahiro Yamada color_text(self.options.color, COLOR_BROWN, 94607913d1eSMasahiro Yamada "SPL is not enabled. Skipped.") + '\n') 94707913d1eSMasahiro Yamada else: 94807913d1eSMasahiro Yamada autoconf_path = self.autoconf 9495a27c734SMasahiro Yamada 9501f16992eSMasahiro Yamada with open(self.dotconfig) as f: 951cc008299SMasahiro Yamada dotconfig_lines = f.readlines() 9525a27c734SMasahiro Yamada 95307913d1eSMasahiro Yamada with open(autoconf_path) as f: 9545a27c734SMasahiro Yamada autoconf_lines = f.readlines() 9555a27c734SMasahiro Yamada 956b134bc13SMasahiro Yamada for config in self.configs: 957b134bc13SMasahiro Yamada result = self.parse_one_config(config, dotconfig_lines, 95896464badSJoe Hershberger autoconf_lines) 9595a27c734SMasahiro Yamada results.append(result) 9605a27c734SMasahiro Yamada 9615a27c734SMasahiro Yamada log = '' 9625a27c734SMasahiro Yamada 9635a27c734SMasahiro Yamada for (action, value) in results: 9645a27c734SMasahiro Yamada if action == ACTION_MOVE: 9655a27c734SMasahiro Yamada actlog = "Move '%s'" % value 9665a27c734SMasahiro Yamada log_color = COLOR_LIGHT_GREEN 967cc008299SMasahiro Yamada elif action == ACTION_NO_ENTRY: 968cc008299SMasahiro Yamada actlog = "%s is not defined in Kconfig. Do nothing." % value 9695a27c734SMasahiro Yamada log_color = COLOR_LIGHT_BLUE 970916224c3SMasahiro Yamada elif action == ACTION_NO_ENTRY_WARN: 971916224c3SMasahiro Yamada actlog = "%s is not defined in Kconfig (suspicious). Do nothing." % value 972916224c3SMasahiro Yamada log_color = COLOR_YELLOW 973916224c3SMasahiro Yamada suspicious = True 974cc008299SMasahiro Yamada elif action == ACTION_NO_CHANGE: 975cc008299SMasahiro Yamada actlog = "'%s' is the same as the define in Kconfig. Do nothing." \ 976cc008299SMasahiro Yamada % value 9775a27c734SMasahiro Yamada log_color = COLOR_LIGHT_PURPLE 97807913d1eSMasahiro Yamada elif action == ACTION_SPL_NOT_EXIST: 97907913d1eSMasahiro Yamada actlog = "SPL is not enabled for this defconfig. Skip." 98007913d1eSMasahiro Yamada log_color = COLOR_PURPLE 9815a27c734SMasahiro Yamada else: 9825a27c734SMasahiro Yamada sys.exit("Internal Error. This should not happen.") 9835a27c734SMasahiro Yamada 9841d085568SMasahiro Yamada log += color_text(self.options.color, log_color, actlog) + '\n' 9855a27c734SMasahiro Yamada 9861f16992eSMasahiro Yamada with open(self.dotconfig, 'a') as f: 9875a27c734SMasahiro Yamada for (action, value) in results: 9885a27c734SMasahiro Yamada if action == ACTION_MOVE: 9895a27c734SMasahiro Yamada f.write(value + '\n') 9907fb0bacdSMasahiro Yamada updated = True 9915a27c734SMasahiro Yamada 9925da4f857SMasahiro Yamada self.results = results 99307913d1eSMasahiro Yamada for f in rm_files: 99407913d1eSMasahiro Yamada os.remove(f) 9955a27c734SMasahiro Yamada 996916224c3SMasahiro Yamada return (updated, suspicious, log) 997522e8dcbSMasahiro Yamada 9985da4f857SMasahiro Yamada def check_defconfig(self): 9995da4f857SMasahiro Yamada """Check the defconfig after savedefconfig 10005da4f857SMasahiro Yamada 10015da4f857SMasahiro Yamada Returns: 10025da4f857SMasahiro Yamada Return additional log if moved CONFIGs were removed again by 10035da4f857SMasahiro Yamada 'make savedefconfig'. 10045da4f857SMasahiro Yamada """ 10055da4f857SMasahiro Yamada 10065da4f857SMasahiro Yamada log = '' 10075da4f857SMasahiro Yamada 10085da4f857SMasahiro Yamada with open(self.defconfig) as f: 10095da4f857SMasahiro Yamada defconfig_lines = f.readlines() 10105da4f857SMasahiro Yamada 10115da4f857SMasahiro Yamada for (action, value) in self.results: 10125da4f857SMasahiro Yamada if action != ACTION_MOVE: 10135da4f857SMasahiro Yamada continue 10145da4f857SMasahiro Yamada if not value + '\n' in defconfig_lines: 10155da4f857SMasahiro Yamada log += color_text(self.options.color, COLOR_YELLOW, 10165da4f857SMasahiro Yamada "'%s' was removed by savedefconfig.\n" % 10175da4f857SMasahiro Yamada value) 10185da4f857SMasahiro Yamada 10195da4f857SMasahiro Yamada return log 10205da4f857SMasahiro Yamada 1021d73fcb12SSimon Glass 1022d73fcb12SSimon Glassclass DatabaseThread(threading.Thread): 1023d73fcb12SSimon Glass """This thread processes results from Slot threads. 1024d73fcb12SSimon Glass 1025d73fcb12SSimon Glass It collects the data in the master config directary. There is only one 1026d73fcb12SSimon Glass result thread, and this helps to serialise the build output. 1027d73fcb12SSimon Glass """ 1028d73fcb12SSimon Glass def __init__(self, config_db, db_queue): 1029d73fcb12SSimon Glass """Set up a new result thread 1030d73fcb12SSimon Glass 1031d73fcb12SSimon Glass Args: 1032d73fcb12SSimon Glass builder: Builder which will be sent each result 1033d73fcb12SSimon Glass """ 1034d73fcb12SSimon Glass threading.Thread.__init__(self) 1035d73fcb12SSimon Glass self.config_db = config_db 1036d73fcb12SSimon Glass self.db_queue= db_queue 1037d73fcb12SSimon Glass 1038d73fcb12SSimon Glass def run(self): 1039d73fcb12SSimon Glass """Called to start up the result thread. 1040d73fcb12SSimon Glass 1041d73fcb12SSimon Glass We collect the next result job and pass it on to the build. 1042d73fcb12SSimon Glass """ 1043d73fcb12SSimon Glass while True: 1044d73fcb12SSimon Glass defconfig, configs = self.db_queue.get() 1045d73fcb12SSimon Glass self.config_db[defconfig] = configs 1046d73fcb12SSimon Glass self.db_queue.task_done() 1047d73fcb12SSimon Glass 1048d73fcb12SSimon Glass 10495a27c734SMasahiro Yamadaclass Slot: 10505a27c734SMasahiro Yamada 10515a27c734SMasahiro Yamada """A slot to store a subprocess. 10525a27c734SMasahiro Yamada 10535a27c734SMasahiro Yamada Each instance of this class handles one subprocess. 10545a27c734SMasahiro Yamada This class is useful to control multiple threads 10555a27c734SMasahiro Yamada for faster processing. 10565a27c734SMasahiro Yamada """ 10575a27c734SMasahiro Yamada 10586821a745SSimon Glass def __init__(self, toolchains, configs, options, progress, devnull, 10596821a745SSimon Glass make_cmd, reference_src_dir, db_queue): 10605a27c734SMasahiro Yamada """Create a new process slot. 10615a27c734SMasahiro Yamada 10625a27c734SMasahiro Yamada Arguments: 10636821a745SSimon Glass toolchains: Toolchains object containing toolchains. 1064b134bc13SMasahiro Yamada configs: A list of CONFIGs to move. 10655a27c734SMasahiro Yamada options: option flags. 1066c5e60fd4SMasahiro Yamada progress: A progress indicator. 10675a27c734SMasahiro Yamada devnull: A file object of '/dev/null'. 10685a27c734SMasahiro Yamada make_cmd: command name of GNU Make. 10696b96c1a1SJoe Hershberger reference_src_dir: Determine the true starting config state from this 10706b96c1a1SJoe Hershberger source tree. 1071d73fcb12SSimon Glass db_queue: output queue to write config info for the database 10725a27c734SMasahiro Yamada """ 10736821a745SSimon Glass self.toolchains = toolchains 10745a27c734SMasahiro Yamada self.options = options 1075c5e60fd4SMasahiro Yamada self.progress = progress 10765a27c734SMasahiro Yamada self.build_dir = tempfile.mkdtemp() 10775a27c734SMasahiro Yamada self.devnull = devnull 10785a27c734SMasahiro Yamada self.make_cmd = (make_cmd, 'O=' + self.build_dir) 10796b96c1a1SJoe Hershberger self.reference_src_dir = reference_src_dir 1080d73fcb12SSimon Glass self.db_queue = db_queue 1081522e8dcbSMasahiro Yamada self.parser = KconfigParser(configs, options, self.build_dir) 10825a27c734SMasahiro Yamada self.state = STATE_IDLE 108309c6c066SMasahiro Yamada self.failed_boards = set() 108409c6c066SMasahiro Yamada self.suspicious_boards = set() 10855a27c734SMasahiro Yamada 10865a27c734SMasahiro Yamada def __del__(self): 10875a27c734SMasahiro Yamada """Delete the working directory 10885a27c734SMasahiro Yamada 10895a27c734SMasahiro Yamada This function makes sure the temporary directory is cleaned away 10905a27c734SMasahiro Yamada even if Python suddenly dies due to error. It should be done in here 1091f2dae751SJoe Hershberger because it is guaranteed the destructor is always invoked when the 10925a27c734SMasahiro Yamada instance of the class gets unreferenced. 10935a27c734SMasahiro Yamada 10945a27c734SMasahiro Yamada If the subprocess is still running, wait until it finishes. 10955a27c734SMasahiro Yamada """ 10965a27c734SMasahiro Yamada if self.state != STATE_IDLE: 10975a27c734SMasahiro Yamada while self.ps.poll() == None: 10985a27c734SMasahiro Yamada pass 10995a27c734SMasahiro Yamada shutil.rmtree(self.build_dir) 11005a27c734SMasahiro Yamada 1101c5e60fd4SMasahiro Yamada def add(self, defconfig): 11025a27c734SMasahiro Yamada """Assign a new subprocess for defconfig and add it to the slot. 11035a27c734SMasahiro Yamada 11045a27c734SMasahiro Yamada If the slot is vacant, create a new subprocess for processing the 11055a27c734SMasahiro Yamada given defconfig and add it to the slot. Just returns False if 11065a27c734SMasahiro Yamada the slot is occupied (i.e. the current subprocess is still running). 11075a27c734SMasahiro Yamada 11085a27c734SMasahiro Yamada Arguments: 11095a27c734SMasahiro Yamada defconfig: defconfig name. 11105a27c734SMasahiro Yamada 11115a27c734SMasahiro Yamada Returns: 11125a27c734SMasahiro Yamada Return True on success or False on failure 11135a27c734SMasahiro Yamada """ 11145a27c734SMasahiro Yamada if self.state != STATE_IDLE: 11155a27c734SMasahiro Yamada return False 1116e307fa9dSMasahiro Yamada 11175a27c734SMasahiro Yamada self.defconfig = defconfig 11181d085568SMasahiro Yamada self.log = '' 1119f432c33fSMasahiro Yamada self.current_src_dir = self.reference_src_dir 1120e307fa9dSMasahiro Yamada self.do_defconfig() 11215a27c734SMasahiro Yamada return True 11225a27c734SMasahiro Yamada 11235a27c734SMasahiro Yamada def poll(self): 11245a27c734SMasahiro Yamada """Check the status of the subprocess and handle it as needed. 11255a27c734SMasahiro Yamada 11265a27c734SMasahiro Yamada Returns True if the slot is vacant (i.e. in idle state). 11275a27c734SMasahiro Yamada If the configuration is successfully finished, assign a new 11285a27c734SMasahiro Yamada subprocess to build include/autoconf.mk. 11295a27c734SMasahiro Yamada If include/autoconf.mk is generated, invoke the parser to 11307fb0bacdSMasahiro Yamada parse the .config and the include/autoconf.mk, moving 11317fb0bacdSMasahiro Yamada config options to the .config as needed. 11327fb0bacdSMasahiro Yamada If the .config was updated, run "make savedefconfig" to sync 11337fb0bacdSMasahiro Yamada it, update the original defconfig, and then set the slot back 11347fb0bacdSMasahiro Yamada to the idle state. 11355a27c734SMasahiro Yamada 11365a27c734SMasahiro Yamada Returns: 11375a27c734SMasahiro Yamada Return True if the subprocess is terminated, False otherwise 11385a27c734SMasahiro Yamada """ 11395a27c734SMasahiro Yamada if self.state == STATE_IDLE: 11405a27c734SMasahiro Yamada return True 11415a27c734SMasahiro Yamada 11425a27c734SMasahiro Yamada if self.ps.poll() == None: 11435a27c734SMasahiro Yamada return False 11445a27c734SMasahiro Yamada 11455a27c734SMasahiro Yamada if self.ps.poll() != 0: 1146e307fa9dSMasahiro Yamada self.handle_error() 1147e307fa9dSMasahiro Yamada elif self.state == STATE_DEFCONFIG: 1148f432c33fSMasahiro Yamada if self.reference_src_dir and not self.current_src_dir: 11496b96c1a1SJoe Hershberger self.do_savedefconfig() 11506b96c1a1SJoe Hershberger else: 1151e307fa9dSMasahiro Yamada self.do_autoconf() 1152e307fa9dSMasahiro Yamada elif self.state == STATE_AUTOCONF: 1153f432c33fSMasahiro Yamada if self.current_src_dir: 1154f432c33fSMasahiro Yamada self.current_src_dir = None 11556b96c1a1SJoe Hershberger self.do_defconfig() 1156d73fcb12SSimon Glass elif self.options.build_db: 1157d73fcb12SSimon Glass self.do_build_db() 11586b96c1a1SJoe Hershberger else: 1159e307fa9dSMasahiro Yamada self.do_savedefconfig() 1160e307fa9dSMasahiro Yamada elif self.state == STATE_SAVEDEFCONFIG: 1161e307fa9dSMasahiro Yamada self.update_defconfig() 1162e307fa9dSMasahiro Yamada else: 1163e307fa9dSMasahiro Yamada sys.exit("Internal Error. This should not happen.") 1164e307fa9dSMasahiro Yamada 1165e307fa9dSMasahiro Yamada return True if self.state == STATE_IDLE else False 1166e307fa9dSMasahiro Yamada 1167e307fa9dSMasahiro Yamada def handle_error(self): 1168e307fa9dSMasahiro Yamada """Handle error cases.""" 1169e307fa9dSMasahiro Yamada 11701d085568SMasahiro Yamada self.log += color_text(self.options.color, COLOR_LIGHT_RED, 11711d085568SMasahiro Yamada "Failed to process.\n") 117295bf9c7eSJoe Hershberger if self.options.verbose: 11731d085568SMasahiro Yamada self.log += color_text(self.options.color, COLOR_LIGHT_CYAN, 117490ed6cbaSMasahiro Yamada self.ps.stderr.read()) 11754efef998SMasahiro Yamada self.finish(False) 11765a27c734SMasahiro Yamada 1177e307fa9dSMasahiro Yamada def do_defconfig(self): 1178e307fa9dSMasahiro Yamada """Run 'make <board>_defconfig' to create the .config file.""" 1179e307fa9dSMasahiro Yamada 1180e307fa9dSMasahiro Yamada cmd = list(self.make_cmd) 1181e307fa9dSMasahiro Yamada cmd.append(self.defconfig) 1182e307fa9dSMasahiro Yamada self.ps = subprocess.Popen(cmd, stdout=self.devnull, 1183f432c33fSMasahiro Yamada stderr=subprocess.PIPE, 1184f432c33fSMasahiro Yamada cwd=self.current_src_dir) 1185e307fa9dSMasahiro Yamada self.state = STATE_DEFCONFIG 1186e307fa9dSMasahiro Yamada 1187e307fa9dSMasahiro Yamada def do_autoconf(self): 1188f3b8e647SSimon Glass """Run 'make AUTO_CONF_PATH'.""" 1189e307fa9dSMasahiro Yamada 11906821a745SSimon Glass arch = self.parser.get_arch() 11916821a745SSimon Glass try: 11926821a745SSimon Glass toolchain = self.toolchains.Select(arch) 11936821a745SSimon Glass except ValueError: 1194e307fa9dSMasahiro Yamada self.log += color_text(self.options.color, COLOR_YELLOW, 1195ce3ba458SChris Packham "Tool chain for '%s' is missing. Do nothing.\n" % arch) 1196e307fa9dSMasahiro Yamada self.finish(False) 1197e307fa9dSMasahiro Yamada return 11986821a745SSimon Glass env = toolchain.MakeEnvironment(False) 1199e307fa9dSMasahiro Yamada 1200e307fa9dSMasahiro Yamada cmd = list(self.make_cmd) 1201e307fa9dSMasahiro Yamada cmd.append('KCONFIG_IGNORE_DUPLICATES=1') 1202f3b8e647SSimon Glass cmd.append(AUTO_CONF_PATH) 12036821a745SSimon Glass self.ps = subprocess.Popen(cmd, stdout=self.devnull, env=env, 1204f432c33fSMasahiro Yamada stderr=subprocess.PIPE, 1205f432c33fSMasahiro Yamada cwd=self.current_src_dir) 1206e307fa9dSMasahiro Yamada self.state = STATE_AUTOCONF 1207e307fa9dSMasahiro Yamada 1208d73fcb12SSimon Glass def do_build_db(self): 1209d73fcb12SSimon Glass """Add the board to the database""" 1210d73fcb12SSimon Glass configs = {} 1211d73fcb12SSimon Glass with open(os.path.join(self.build_dir, AUTO_CONF_PATH)) as fd: 1212d73fcb12SSimon Glass for line in fd.readlines(): 1213d73fcb12SSimon Glass if line.startswith('CONFIG'): 1214d73fcb12SSimon Glass config, value = line.split('=', 1) 1215d73fcb12SSimon Glass configs[config] = value.rstrip() 1216d73fcb12SSimon Glass self.db_queue.put([self.defconfig, configs]) 1217d73fcb12SSimon Glass self.finish(True) 1218d73fcb12SSimon Glass 1219e307fa9dSMasahiro Yamada def do_savedefconfig(self): 1220e307fa9dSMasahiro Yamada """Update the .config and run 'make savedefconfig'.""" 1221e307fa9dSMasahiro Yamada 1222916224c3SMasahiro Yamada (updated, suspicious, log) = self.parser.update_dotconfig() 1223916224c3SMasahiro Yamada if suspicious: 1224916224c3SMasahiro Yamada self.suspicious_boards.add(self.defconfig) 12257fb0bacdSMasahiro Yamada self.log += log 122696464badSJoe Hershberger 12278513dc04SMasahiro Yamada if not self.options.force_sync and not updated: 12287fb0bacdSMasahiro Yamada self.finish(True) 1229e307fa9dSMasahiro Yamada return 12308513dc04SMasahiro Yamada if updated: 1231c1c4d0f0SMasahiro Yamada self.log += color_text(self.options.color, COLOR_LIGHT_GREEN, 1232c1c4d0f0SMasahiro Yamada "Syncing by savedefconfig...\n") 12338513dc04SMasahiro Yamada else: 12348513dc04SMasahiro Yamada self.log += "Syncing by savedefconfig (forced by option)...\n" 12358513dc04SMasahiro Yamada 123696464badSJoe Hershberger cmd = list(self.make_cmd) 123796464badSJoe Hershberger cmd.append('savedefconfig') 123896464badSJoe Hershberger self.ps = subprocess.Popen(cmd, stdout=self.devnull, 123925400090SJoe Hershberger stderr=subprocess.PIPE) 124096464badSJoe Hershberger self.state = STATE_SAVEDEFCONFIG 124196464badSJoe Hershberger 1242e307fa9dSMasahiro Yamada def update_defconfig(self): 1243e307fa9dSMasahiro Yamada """Update the input defconfig and go back to the idle state.""" 1244e307fa9dSMasahiro Yamada 1245fc2661eeSMasahiro Yamada log = self.parser.check_defconfig() 1246fc2661eeSMasahiro Yamada if log: 124709c6c066SMasahiro Yamada self.suspicious_boards.add(self.defconfig) 1248fc2661eeSMasahiro Yamada self.log += log 1249c8e1b10dSMasahiro Yamada orig_defconfig = os.path.join('configs', self.defconfig) 1250c8e1b10dSMasahiro Yamada new_defconfig = os.path.join(self.build_dir, 'defconfig') 1251c8e1b10dSMasahiro Yamada updated = not filecmp.cmp(orig_defconfig, new_defconfig) 1252c8e1b10dSMasahiro Yamada 1253c8e1b10dSMasahiro Yamada if updated: 125406cc1d36SJoe Hershberger self.log += color_text(self.options.color, COLOR_LIGHT_BLUE, 1255c8e1b10dSMasahiro Yamada "defconfig was updated.\n") 1256c8e1b10dSMasahiro Yamada 1257c8e1b10dSMasahiro Yamada if not self.options.dry_run and updated: 1258c8e1b10dSMasahiro Yamada shutil.move(new_defconfig, orig_defconfig) 12594efef998SMasahiro Yamada self.finish(True) 12605a27c734SMasahiro Yamada 12614efef998SMasahiro Yamada def finish(self, success): 12624efef998SMasahiro Yamada """Display log along with progress and go to the idle state. 12631d085568SMasahiro Yamada 12641d085568SMasahiro Yamada Arguments: 12654efef998SMasahiro Yamada success: Should be True when the defconfig was processed 12664efef998SMasahiro Yamada successfully, or False when it fails. 12671d085568SMasahiro Yamada """ 12681d085568SMasahiro Yamada # output at least 30 characters to hide the "* defconfigs out of *". 12691d085568SMasahiro Yamada log = self.defconfig.ljust(30) + '\n' 12701d085568SMasahiro Yamada 12711d085568SMasahiro Yamada log += '\n'.join([ ' ' + s for s in self.log.split('\n') ]) 12721d085568SMasahiro Yamada # Some threads are running in parallel. 12731d085568SMasahiro Yamada # Print log atomically to not mix up logs from different threads. 12744efef998SMasahiro Yamada print >> (sys.stdout if success else sys.stderr), log 12754efef998SMasahiro Yamada 12764efef998SMasahiro Yamada if not success: 12774efef998SMasahiro Yamada if self.options.exit_on_error: 12784efef998SMasahiro Yamada sys.exit("Exit on error.") 12794efef998SMasahiro Yamada # If --exit-on-error flag is not set, skip this board and continue. 12804efef998SMasahiro Yamada # Record the failed board. 128109c6c066SMasahiro Yamada self.failed_boards.add(self.defconfig) 12824efef998SMasahiro Yamada 12831d085568SMasahiro Yamada self.progress.inc() 12841d085568SMasahiro Yamada self.progress.show() 12854efef998SMasahiro Yamada self.state = STATE_IDLE 12861d085568SMasahiro Yamada 12875a27c734SMasahiro Yamada def get_failed_boards(self): 128809c6c066SMasahiro Yamada """Returns a set of failed boards (defconfigs) in this slot. 12895a27c734SMasahiro Yamada """ 12905a27c734SMasahiro Yamada return self.failed_boards 12915a27c734SMasahiro Yamada 1292fc2661eeSMasahiro Yamada def get_suspicious_boards(self): 129309c6c066SMasahiro Yamada """Returns a set of boards (defconfigs) with possible misconversion. 1294fc2661eeSMasahiro Yamada """ 1295916224c3SMasahiro Yamada return self.suspicious_boards - self.failed_boards 1296fc2661eeSMasahiro Yamada 12975a27c734SMasahiro Yamadaclass Slots: 12985a27c734SMasahiro Yamada 12995a27c734SMasahiro Yamada """Controller of the array of subprocess slots.""" 13005a27c734SMasahiro Yamada 13016821a745SSimon Glass def __init__(self, toolchains, configs, options, progress, 13026821a745SSimon Glass reference_src_dir, db_queue): 13035a27c734SMasahiro Yamada """Create a new slots controller. 13045a27c734SMasahiro Yamada 13055a27c734SMasahiro Yamada Arguments: 13066821a745SSimon Glass toolchains: Toolchains object containing toolchains. 1307b134bc13SMasahiro Yamada configs: A list of CONFIGs to move. 13085a27c734SMasahiro Yamada options: option flags. 1309c5e60fd4SMasahiro Yamada progress: A progress indicator. 13106b96c1a1SJoe Hershberger reference_src_dir: Determine the true starting config state from this 13116b96c1a1SJoe Hershberger source tree. 1312d73fcb12SSimon Glass db_queue: output queue to write config info for the database 13135a27c734SMasahiro Yamada """ 13145a27c734SMasahiro Yamada self.options = options 13155a27c734SMasahiro Yamada self.slots = [] 13165a27c734SMasahiro Yamada devnull = get_devnull() 13175a27c734SMasahiro Yamada make_cmd = get_make_cmd() 13185a27c734SMasahiro Yamada for i in range(options.jobs): 13196821a745SSimon Glass self.slots.append(Slot(toolchains, configs, options, progress, 13206821a745SSimon Glass devnull, make_cmd, reference_src_dir, 13216821a745SSimon Glass db_queue)) 13225a27c734SMasahiro Yamada 1323c5e60fd4SMasahiro Yamada def add(self, defconfig): 13245a27c734SMasahiro Yamada """Add a new subprocess if a vacant slot is found. 13255a27c734SMasahiro Yamada 13265a27c734SMasahiro Yamada Arguments: 13275a27c734SMasahiro Yamada defconfig: defconfig name to be put into. 13285a27c734SMasahiro Yamada 13295a27c734SMasahiro Yamada Returns: 13305a27c734SMasahiro Yamada Return True on success or False on failure 13315a27c734SMasahiro Yamada """ 13325a27c734SMasahiro Yamada for slot in self.slots: 1333c5e60fd4SMasahiro Yamada if slot.add(defconfig): 13345a27c734SMasahiro Yamada return True 13355a27c734SMasahiro Yamada return False 13365a27c734SMasahiro Yamada 13375a27c734SMasahiro Yamada def available(self): 13385a27c734SMasahiro Yamada """Check if there is a vacant slot. 13395a27c734SMasahiro Yamada 13405a27c734SMasahiro Yamada Returns: 13415a27c734SMasahiro Yamada Return True if at lease one vacant slot is found, False otherwise. 13425a27c734SMasahiro Yamada """ 13435a27c734SMasahiro Yamada for slot in self.slots: 13445a27c734SMasahiro Yamada if slot.poll(): 13455a27c734SMasahiro Yamada return True 13465a27c734SMasahiro Yamada return False 13475a27c734SMasahiro Yamada 13485a27c734SMasahiro Yamada def empty(self): 13495a27c734SMasahiro Yamada """Check if all slots are vacant. 13505a27c734SMasahiro Yamada 13515a27c734SMasahiro Yamada Returns: 13525a27c734SMasahiro Yamada Return True if all the slots are vacant, False otherwise. 13535a27c734SMasahiro Yamada """ 13545a27c734SMasahiro Yamada ret = True 13555a27c734SMasahiro Yamada for slot in self.slots: 13565a27c734SMasahiro Yamada if not slot.poll(): 13575a27c734SMasahiro Yamada ret = False 13585a27c734SMasahiro Yamada return ret 13595a27c734SMasahiro Yamada 13605a27c734SMasahiro Yamada def show_failed_boards(self): 13615a27c734SMasahiro Yamada """Display all of the failed boards (defconfigs).""" 136209c6c066SMasahiro Yamada boards = set() 136396dccd97SMasahiro Yamada output_file = 'moveconfig.failed' 13645a27c734SMasahiro Yamada 13655a27c734SMasahiro Yamada for slot in self.slots: 136609c6c066SMasahiro Yamada boards |= slot.get_failed_boards() 13675a27c734SMasahiro Yamada 136896dccd97SMasahiro Yamada if boards: 136996dccd97SMasahiro Yamada boards = '\n'.join(boards) + '\n' 137096dccd97SMasahiro Yamada msg = "The following boards were not processed due to error:\n" 137196dccd97SMasahiro Yamada msg += boards 137296dccd97SMasahiro Yamada msg += "(the list has been saved in %s)\n" % output_file 137396dccd97SMasahiro Yamada print >> sys.stderr, color_text(self.options.color, COLOR_LIGHT_RED, 137496dccd97SMasahiro Yamada msg) 13755a27c734SMasahiro Yamada 137696dccd97SMasahiro Yamada with open(output_file, 'w') as f: 137796dccd97SMasahiro Yamada f.write(boards) 13782559cd89SJoe Hershberger 1379fc2661eeSMasahiro Yamada def show_suspicious_boards(self): 1380fc2661eeSMasahiro Yamada """Display all boards (defconfigs) with possible misconversion.""" 138109c6c066SMasahiro Yamada boards = set() 1382fc2661eeSMasahiro Yamada output_file = 'moveconfig.suspicious' 1383fc2661eeSMasahiro Yamada 1384fc2661eeSMasahiro Yamada for slot in self.slots: 138509c6c066SMasahiro Yamada boards |= slot.get_suspicious_boards() 1386fc2661eeSMasahiro Yamada 1387fc2661eeSMasahiro Yamada if boards: 1388fc2661eeSMasahiro Yamada boards = '\n'.join(boards) + '\n' 1389fc2661eeSMasahiro Yamada msg = "The following boards might have been converted incorrectly.\n" 1390fc2661eeSMasahiro Yamada msg += "It is highly recommended to check them manually:\n" 1391fc2661eeSMasahiro Yamada msg += boards 1392fc2661eeSMasahiro Yamada msg += "(the list has been saved in %s)\n" % output_file 1393fc2661eeSMasahiro Yamada print >> sys.stderr, color_text(self.options.color, COLOR_YELLOW, 1394fc2661eeSMasahiro Yamada msg) 1395fc2661eeSMasahiro Yamada 1396fc2661eeSMasahiro Yamada with open(output_file, 'w') as f: 1397fc2661eeSMasahiro Yamada f.write(boards) 1398fc2661eeSMasahiro Yamada 13995cc42a51SMasahiro Yamadaclass ReferenceSource: 14005cc42a51SMasahiro Yamada 14015cc42a51SMasahiro Yamada """Reference source against which original configs should be parsed.""" 14025cc42a51SMasahiro Yamada 14035cc42a51SMasahiro Yamada def __init__(self, commit): 14045cc42a51SMasahiro Yamada """Create a reference source directory based on a specified commit. 14055cc42a51SMasahiro Yamada 14065cc42a51SMasahiro Yamada Arguments: 14075cc42a51SMasahiro Yamada commit: commit to git-clone 14085cc42a51SMasahiro Yamada """ 14095cc42a51SMasahiro Yamada self.src_dir = tempfile.mkdtemp() 14105cc42a51SMasahiro Yamada print "Cloning git repo to a separate work directory..." 14115cc42a51SMasahiro Yamada subprocess.check_output(['git', 'clone', os.getcwd(), '.'], 14125cc42a51SMasahiro Yamada cwd=self.src_dir) 14135cc42a51SMasahiro Yamada print "Checkout '%s' to build the original autoconf.mk." % \ 14145cc42a51SMasahiro Yamada subprocess.check_output(['git', 'rev-parse', '--short', commit]).strip() 14155cc42a51SMasahiro Yamada subprocess.check_output(['git', 'checkout', commit], 14165cc42a51SMasahiro Yamada stderr=subprocess.STDOUT, cwd=self.src_dir) 14176b96c1a1SJoe Hershberger 14186b96c1a1SJoe Hershberger def __del__(self): 14195cc42a51SMasahiro Yamada """Delete the reference source directory 14206b96c1a1SJoe Hershberger 14216b96c1a1SJoe Hershberger This function makes sure the temporary directory is cleaned away 14226b96c1a1SJoe Hershberger even if Python suddenly dies due to error. It should be done in here 14236b96c1a1SJoe Hershberger because it is guaranteed the destructor is always invoked when the 14246b96c1a1SJoe Hershberger instance of the class gets unreferenced. 14256b96c1a1SJoe Hershberger """ 14265cc42a51SMasahiro Yamada shutil.rmtree(self.src_dir) 14276b96c1a1SJoe Hershberger 14285cc42a51SMasahiro Yamada def get_dir(self): 14295cc42a51SMasahiro Yamada """Return the absolute path to the reference source directory.""" 14305cc42a51SMasahiro Yamada 14315cc42a51SMasahiro Yamada return self.src_dir 14326b96c1a1SJoe Hershberger 14336821a745SSimon Glassdef move_config(toolchains, configs, options, db_queue): 14345a27c734SMasahiro Yamada """Move config options to defconfig files. 14355a27c734SMasahiro Yamada 14365a27c734SMasahiro Yamada Arguments: 1437b134bc13SMasahiro Yamada configs: A list of CONFIGs to move. 14385a27c734SMasahiro Yamada options: option flags 14395a27c734SMasahiro Yamada """ 1440b134bc13SMasahiro Yamada if len(configs) == 0: 14416a9f79f7SMasahiro Yamada if options.force_sync: 14426a9f79f7SMasahiro Yamada print 'No CONFIG is specified. You are probably syncing defconfigs.', 1443d73fcb12SSimon Glass elif options.build_db: 1444d73fcb12SSimon Glass print 'Building %s database' % CONFIG_DATABASE 14456a9f79f7SMasahiro Yamada else: 14466a9f79f7SMasahiro Yamada print 'Neither CONFIG nor --force-sync is specified. Nothing will happen.', 14476a9f79f7SMasahiro Yamada else: 14486a9f79f7SMasahiro Yamada print 'Move ' + ', '.join(configs), 14496a9f79f7SMasahiro Yamada print '(jobs: %d)\n' % options.jobs 14505a27c734SMasahiro Yamada 14516b96c1a1SJoe Hershberger if options.git_ref: 14525cc42a51SMasahiro Yamada reference_src = ReferenceSource(options.git_ref) 14535cc42a51SMasahiro Yamada reference_src_dir = reference_src.get_dir() 14545cc42a51SMasahiro Yamada else: 1455f432c33fSMasahiro Yamada reference_src_dir = None 14566b96c1a1SJoe Hershberger 145791040e85SJoe Hershberger if options.defconfigs: 14580dbc9b59SMasahiro Yamada defconfigs = get_matched_defconfigs(options.defconfigs) 145991040e85SJoe Hershberger else: 1460684c306eSMasahiro Yamada defconfigs = get_all_defconfigs() 14615a27c734SMasahiro Yamada 1462c5e60fd4SMasahiro Yamada progress = Progress(len(defconfigs)) 14636821a745SSimon Glass slots = Slots(toolchains, configs, options, progress, reference_src_dir, 14646821a745SSimon Glass db_queue) 14655a27c734SMasahiro Yamada 14665a27c734SMasahiro Yamada # Main loop to process defconfig files: 14675a27c734SMasahiro Yamada # Add a new subprocess into a vacant slot. 14685a27c734SMasahiro Yamada # Sleep if there is no available slot. 1469c5e60fd4SMasahiro Yamada for defconfig in defconfigs: 1470c5e60fd4SMasahiro Yamada while not slots.add(defconfig): 14715a27c734SMasahiro Yamada while not slots.available(): 14725a27c734SMasahiro Yamada # No available slot: sleep for a while 14735a27c734SMasahiro Yamada time.sleep(SLEEP_TIME) 14745a27c734SMasahiro Yamada 14755a27c734SMasahiro Yamada # wait until all the subprocesses finish 14765a27c734SMasahiro Yamada while not slots.empty(): 14775a27c734SMasahiro Yamada time.sleep(SLEEP_TIME) 14785a27c734SMasahiro Yamada 14792e2ce6c0SJoe Hershberger print '' 14805a27c734SMasahiro Yamada slots.show_failed_boards() 1481fc2661eeSMasahiro Yamada slots.show_suspicious_boards() 14825a27c734SMasahiro Yamada 1483cb008830SSimon Glassdef find_kconfig_rules(kconf, config, imply_config): 1484cb008830SSimon Glass """Check whether a config has a 'select' or 'imply' keyword 1485cb008830SSimon Glass 1486cb008830SSimon Glass Args: 1487cb008830SSimon Glass kconf: Kconfig.Config object 1488cb008830SSimon Glass config: Name of config to check (without CONFIG_ prefix) 1489cb008830SSimon Glass imply_config: Implying config (without CONFIG_ prefix) which may or 1490cb008830SSimon Glass may not have an 'imply' for 'config') 1491cb008830SSimon Glass 1492cb008830SSimon Glass Returns: 1493cb008830SSimon Glass Symbol object for 'config' if found, else None 1494cb008830SSimon Glass """ 1495cb008830SSimon Glass sym = kconf.get_symbol(imply_config) 1496cb008830SSimon Glass if sym: 14974e1102f6SUlf Magnusson for sel in sym.get_selected_symbols() | sym.get_implied_symbols(): 1498cb008830SSimon Glass if sel.get_name() == config: 1499cb008830SSimon Glass return sym 1500cb008830SSimon Glass return None 1501cb008830SSimon Glass 1502cb008830SSimon Glassdef check_imply_rule(kconf, config, imply_config): 1503cb008830SSimon Glass """Check if we can add an 'imply' option 1504cb008830SSimon Glass 1505cb008830SSimon Glass This finds imply_config in the Kconfig and looks to see if it is possible 1506cb008830SSimon Glass to add an 'imply' for 'config' to that part of the Kconfig. 1507cb008830SSimon Glass 1508cb008830SSimon Glass Args: 1509cb008830SSimon Glass kconf: Kconfig.Config object 1510cb008830SSimon Glass config: Name of config to check (without CONFIG_ prefix) 1511cb008830SSimon Glass imply_config: Implying config (without CONFIG_ prefix) which may or 1512cb008830SSimon Glass may not have an 'imply' for 'config') 1513cb008830SSimon Glass 1514cb008830SSimon Glass Returns: 1515cb008830SSimon Glass tuple: 1516cb008830SSimon Glass filename of Kconfig file containing imply_config, or None if none 1517cb008830SSimon Glass line number within the Kconfig file, or 0 if none 1518cb008830SSimon Glass message indicating the result 1519cb008830SSimon Glass """ 1520cb008830SSimon Glass sym = kconf.get_symbol(imply_config) 1521cb008830SSimon Glass if not sym: 1522cb008830SSimon Glass return 'cannot find sym' 1523cb008830SSimon Glass locs = sym.get_def_locations() 1524cb008830SSimon Glass if len(locs) != 1: 1525cb008830SSimon Glass return '%d locations' % len(locs) 1526cb008830SSimon Glass fname, linenum = locs[0] 1527cb008830SSimon Glass cwd = os.getcwd() 1528cb008830SSimon Glass if cwd and fname.startswith(cwd): 1529cb008830SSimon Glass fname = fname[len(cwd) + 1:] 1530cb008830SSimon Glass file_line = ' at %s:%d' % (fname, linenum) 1531cb008830SSimon Glass with open(fname) as fd: 1532cb008830SSimon Glass data = fd.read().splitlines() 1533cb008830SSimon Glass if data[linenum - 1] != 'config %s' % imply_config: 1534cb008830SSimon Glass return None, 0, 'bad sym format %s%s' % (data[linenum], file_line) 1535cb008830SSimon Glass return fname, linenum, 'adding%s' % file_line 1536cb008830SSimon Glass 1537cb008830SSimon Glassdef add_imply_rule(config, fname, linenum): 1538cb008830SSimon Glass """Add a new 'imply' option to a Kconfig 1539cb008830SSimon Glass 1540cb008830SSimon Glass Args: 1541cb008830SSimon Glass config: config option to add an imply for (without CONFIG_ prefix) 1542cb008830SSimon Glass fname: Kconfig filename to update 1543cb008830SSimon Glass linenum: Line number to place the 'imply' before 1544cb008830SSimon Glass 1545cb008830SSimon Glass Returns: 1546cb008830SSimon Glass Message indicating the result 1547cb008830SSimon Glass """ 1548cb008830SSimon Glass file_line = ' at %s:%d' % (fname, linenum) 1549cb008830SSimon Glass data = open(fname).read().splitlines() 1550cb008830SSimon Glass linenum -= 1 1551cb008830SSimon Glass 1552cb008830SSimon Glass for offset, line in enumerate(data[linenum:]): 1553cb008830SSimon Glass if line.strip().startswith('help') or not line: 1554cb008830SSimon Glass data.insert(linenum + offset, '\timply %s' % config) 1555cb008830SSimon Glass with open(fname, 'w') as fd: 1556cb008830SSimon Glass fd.write('\n'.join(data) + '\n') 1557cb008830SSimon Glass return 'added%s' % file_line 1558cb008830SSimon Glass 1559cb008830SSimon Glass return 'could not insert%s' 1560cb008830SSimon Glass 1561cb008830SSimon Glass(IMPLY_MIN_2, IMPLY_TARGET, IMPLY_CMD, IMPLY_NON_ARCH_BOARD) = ( 1562cb008830SSimon Glass 1, 2, 4, 8) 15639b2a2e87SSimon Glass 15649b2a2e87SSimon GlassIMPLY_FLAGS = { 15659b2a2e87SSimon Glass 'min2': [IMPLY_MIN_2, 'Show options which imply >2 boards (normally >5)'], 15669b2a2e87SSimon Glass 'target': [IMPLY_TARGET, 'Allow CONFIG_TARGET_... options to imply'], 15679b2a2e87SSimon Glass 'cmd': [IMPLY_CMD, 'Allow CONFIG_CMD_... to imply'], 1568cb008830SSimon Glass 'non-arch-board': [ 1569cb008830SSimon Glass IMPLY_NON_ARCH_BOARD, 1570cb008830SSimon Glass 'Allow Kconfig options outside arch/ and /board/ to imply'], 15719b2a2e87SSimon Glass}; 15729b2a2e87SSimon Glass 1573cb008830SSimon Glassdef do_imply_config(config_list, add_imply, imply_flags, skip_added, 1574cb008830SSimon Glass check_kconfig=True, find_superset=False): 157599b66605SSimon Glass """Find CONFIG options which imply those in the list 157699b66605SSimon Glass 157799b66605SSimon Glass Some CONFIG options can be implied by others and this can help to reduce 157899b66605SSimon Glass the size of the defconfig files. For example, CONFIG_X86 implies 157999b66605SSimon Glass CONFIG_CMD_IRQ, so we can put 'imply CMD_IRQ' under 'config X86' and 158099b66605SSimon Glass all x86 boards will have that option, avoiding adding CONFIG_CMD_IRQ to 158199b66605SSimon Glass each of the x86 defconfig files. 158299b66605SSimon Glass 158399b66605SSimon Glass This function uses the moveconfig database to find such options. It 158499b66605SSimon Glass displays a list of things that could possibly imply those in the list. 158599b66605SSimon Glass The algorithm ignores any that start with CONFIG_TARGET since these 158699b66605SSimon Glass typically refer to only a few defconfigs (often one). It also does not 158799b66605SSimon Glass display a config with less than 5 defconfigs. 158899b66605SSimon Glass 158999b66605SSimon Glass The algorithm works using sets. For each target config in config_list: 159099b66605SSimon Glass - Get the set 'defconfigs' which use that target config 159199b66605SSimon Glass - For each config (from a list of all configs): 159299b66605SSimon Glass - Get the set 'imply_defconfig' of defconfigs which use that config 159399b66605SSimon Glass - 159499b66605SSimon Glass - If imply_defconfigs contains anything not in defconfigs then 159599b66605SSimon Glass this config does not imply the target config 159699b66605SSimon Glass 159799b66605SSimon Glass Params: 159899b66605SSimon Glass config_list: List of CONFIG options to check (each a string) 1599cb008830SSimon Glass add_imply: Automatically add an 'imply' for each config. 16009b2a2e87SSimon Glass imply_flags: Flags which control which implying configs are allowed 16019b2a2e87SSimon Glass (IMPLY_...) 1602cb008830SSimon Glass skip_added: Don't show options which already have an imply added. 1603cb008830SSimon Glass check_kconfig: Check if implied symbols already have an 'imply' or 1604cb008830SSimon Glass 'select' for the target config, and show this information if so. 160599b66605SSimon Glass find_superset: True to look for configs which are a superset of those 160699b66605SSimon Glass already found. So for example if CONFIG_EXYNOS5 implies an option, 160799b66605SSimon Glass but CONFIG_EXYNOS covers a larger set of defconfigs and also 160899b66605SSimon Glass implies that option, this will drop the former in favour of the 160999b66605SSimon Glass latter. In practice this option has not proved very used. 161099b66605SSimon Glass 161199b66605SSimon Glass Note the terminoloy: 161299b66605SSimon Glass config - a CONFIG_XXX options (a string, e.g. 'CONFIG_CMD_EEPROM') 161399b66605SSimon Glass defconfig - a defconfig file (a string, e.g. 'configs/snow_defconfig') 161499b66605SSimon Glass """ 1615cb008830SSimon Glass kconf = KconfigScanner().conf if check_kconfig else None 1616cb008830SSimon Glass if add_imply and add_imply != 'all': 1617cb008830SSimon Glass add_imply = add_imply.split() 1618cb008830SSimon Glass 161999b66605SSimon Glass # key is defconfig name, value is dict of (CONFIG_xxx, value) 162099b66605SSimon Glass config_db = {} 162199b66605SSimon Glass 162299b66605SSimon Glass # Holds a dict containing the set of defconfigs that contain each config 162399b66605SSimon Glass # key is config, value is set of defconfigs using that config 162499b66605SSimon Glass defconfig_db = collections.defaultdict(set) 162599b66605SSimon Glass 162699b66605SSimon Glass # Set of all config options we have seen 162799b66605SSimon Glass all_configs = set() 162899b66605SSimon Glass 162999b66605SSimon Glass # Set of all defconfigs we have seen 163099b66605SSimon Glass all_defconfigs = set() 163199b66605SSimon Glass 163299b66605SSimon Glass # Read in the database 163399b66605SSimon Glass configs = {} 163499b66605SSimon Glass with open(CONFIG_DATABASE) as fd: 163599b66605SSimon Glass for line in fd.readlines(): 163699b66605SSimon Glass line = line.rstrip() 163799b66605SSimon Glass if not line: # Separator between defconfigs 163899b66605SSimon Glass config_db[defconfig] = configs 163999b66605SSimon Glass all_defconfigs.add(defconfig) 164099b66605SSimon Glass configs = {} 164199b66605SSimon Glass elif line[0] == ' ': # CONFIG line 164299b66605SSimon Glass config, value = line.strip().split('=', 1) 164399b66605SSimon Glass configs[config] = value 164499b66605SSimon Glass defconfig_db[config].add(defconfig) 164599b66605SSimon Glass all_configs.add(config) 164699b66605SSimon Glass else: # New defconfig 164799b66605SSimon Glass defconfig = line 164899b66605SSimon Glass 164999b66605SSimon Glass # Work through each target config option in tern, independently 165099b66605SSimon Glass for config in config_list: 165199b66605SSimon Glass defconfigs = defconfig_db.get(config) 165299b66605SSimon Glass if not defconfigs: 165399b66605SSimon Glass print '%s not found in any defconfig' % config 165499b66605SSimon Glass continue 165599b66605SSimon Glass 165699b66605SSimon Glass # Get the set of defconfigs without this one (since a config cannot 165799b66605SSimon Glass # imply itself) 165899b66605SSimon Glass non_defconfigs = all_defconfigs - defconfigs 165999b66605SSimon Glass num_defconfigs = len(defconfigs) 166099b66605SSimon Glass print '%s found in %d/%d defconfigs' % (config, num_defconfigs, 166199b66605SSimon Glass len(all_configs)) 166299b66605SSimon Glass 166399b66605SSimon Glass # This will hold the results: key=config, value=defconfigs containing it 166499b66605SSimon Glass imply_configs = {} 166599b66605SSimon Glass rest_configs = all_configs - set([config]) 166699b66605SSimon Glass 166799b66605SSimon Glass # Look at every possible config, except the target one 166899b66605SSimon Glass for imply_config in rest_configs: 16699b2a2e87SSimon Glass if 'ERRATUM' in imply_config: 16709b2a2e87SSimon Glass continue 16719b2a2e87SSimon Glass if not (imply_flags & IMPLY_CMD): 16729b2a2e87SSimon Glass if 'CONFIG_CMD' in imply_config: 16739b2a2e87SSimon Glass continue 16749b2a2e87SSimon Glass if not (imply_flags & IMPLY_TARGET): 167599b66605SSimon Glass if 'CONFIG_TARGET' in imply_config: 167699b66605SSimon Glass continue 167799b66605SSimon Glass 167899b66605SSimon Glass # Find set of defconfigs that have this config 167999b66605SSimon Glass imply_defconfig = defconfig_db[imply_config] 168099b66605SSimon Glass 168199b66605SSimon Glass # Get the intersection of this with defconfigs containing the 168299b66605SSimon Glass # target config 168399b66605SSimon Glass common_defconfigs = imply_defconfig & defconfigs 168499b66605SSimon Glass 168599b66605SSimon Glass # Get the set of defconfigs containing this config which DO NOT 168699b66605SSimon Glass # also contain the taret config. If this set is non-empty it means 168799b66605SSimon Glass # that this config affects other defconfigs as well as (possibly) 168899b66605SSimon Glass # the ones affected by the target config. This means it implies 168999b66605SSimon Glass # things we don't want to imply. 169099b66605SSimon Glass not_common_defconfigs = imply_defconfig & non_defconfigs 169199b66605SSimon Glass if not_common_defconfigs: 169299b66605SSimon Glass continue 169399b66605SSimon Glass 169499b66605SSimon Glass # If there are common defconfigs, imply_config may be useful 169599b66605SSimon Glass if common_defconfigs: 169699b66605SSimon Glass skip = False 169799b66605SSimon Glass if find_superset: 169899b66605SSimon Glass for prev in imply_configs.keys(): 169999b66605SSimon Glass prev_count = len(imply_configs[prev]) 170099b66605SSimon Glass count = len(common_defconfigs) 170199b66605SSimon Glass if (prev_count > count and 170299b66605SSimon Glass (imply_configs[prev] & common_defconfigs == 170399b66605SSimon Glass common_defconfigs)): 170499b66605SSimon Glass # skip imply_config because prev is a superset 170599b66605SSimon Glass skip = True 170699b66605SSimon Glass break 170799b66605SSimon Glass elif count > prev_count: 170899b66605SSimon Glass # delete prev because imply_config is a superset 170999b66605SSimon Glass del imply_configs[prev] 171099b66605SSimon Glass if not skip: 171199b66605SSimon Glass imply_configs[imply_config] = common_defconfigs 171299b66605SSimon Glass 171399b66605SSimon Glass # Now we have a dict imply_configs of configs which imply each config 171499b66605SSimon Glass # The value of each dict item is the set of defconfigs containing that 171599b66605SSimon Glass # config. Rank them so that we print the configs that imply the largest 171699b66605SSimon Glass # number of defconfigs first. 1717cb008830SSimon Glass ranked_iconfigs = sorted(imply_configs, 171899b66605SSimon Glass key=lambda k: len(imply_configs[k]), reverse=True) 1719cb008830SSimon Glass kconfig_info = '' 1720cb008830SSimon Glass cwd = os.getcwd() 1721cb008830SSimon Glass add_list = collections.defaultdict(list) 1722cb008830SSimon Glass for iconfig in ranked_iconfigs: 1723cb008830SSimon Glass num_common = len(imply_configs[iconfig]) 172499b66605SSimon Glass 172599b66605SSimon Glass # Don't bother if there are less than 5 defconfigs affected. 17269b2a2e87SSimon Glass if num_common < (2 if imply_flags & IMPLY_MIN_2 else 5): 172799b66605SSimon Glass continue 1728cb008830SSimon Glass missing = defconfigs - imply_configs[iconfig] 172999b66605SSimon Glass missing_str = ', '.join(missing) if missing else 'all' 173099b66605SSimon Glass missing_str = '' 1731cb008830SSimon Glass show = True 1732cb008830SSimon Glass if kconf: 1733cb008830SSimon Glass sym = find_kconfig_rules(kconf, config[CONFIG_LEN:], 1734cb008830SSimon Glass iconfig[CONFIG_LEN:]) 1735cb008830SSimon Glass kconfig_info = '' 1736cb008830SSimon Glass if sym: 1737cb008830SSimon Glass locs = sym.get_def_locations() 1738cb008830SSimon Glass if len(locs) == 1: 1739cb008830SSimon Glass fname, linenum = locs[0] 1740cb008830SSimon Glass if cwd and fname.startswith(cwd): 1741cb008830SSimon Glass fname = fname[len(cwd) + 1:] 1742cb008830SSimon Glass kconfig_info = '%s:%d' % (fname, linenum) 1743cb008830SSimon Glass if skip_added: 1744cb008830SSimon Glass show = False 1745cb008830SSimon Glass else: 1746cb008830SSimon Glass sym = kconf.get_symbol(iconfig[CONFIG_LEN:]) 1747cb008830SSimon Glass fname = '' 1748cb008830SSimon Glass if sym: 1749cb008830SSimon Glass locs = sym.get_def_locations() 1750cb008830SSimon Glass if len(locs) == 1: 1751cb008830SSimon Glass fname, linenum = locs[0] 1752cb008830SSimon Glass if cwd and fname.startswith(cwd): 1753cb008830SSimon Glass fname = fname[len(cwd) + 1:] 1754cb008830SSimon Glass in_arch_board = not sym or (fname.startswith('arch') or 1755cb008830SSimon Glass fname.startswith('board')) 1756cb008830SSimon Glass if (not in_arch_board and 1757cb008830SSimon Glass not (imply_flags & IMPLY_NON_ARCH_BOARD)): 1758cb008830SSimon Glass continue 1759cb008830SSimon Glass 1760cb008830SSimon Glass if add_imply and (add_imply == 'all' or 1761cb008830SSimon Glass iconfig in add_imply): 1762cb008830SSimon Glass fname, linenum, kconfig_info = (check_imply_rule(kconf, 1763cb008830SSimon Glass config[CONFIG_LEN:], iconfig[CONFIG_LEN:])) 1764cb008830SSimon Glass if fname: 1765cb008830SSimon Glass add_list[fname].append(linenum) 1766cb008830SSimon Glass 1767cb008830SSimon Glass if show and kconfig_info != 'skip': 1768cb008830SSimon Glass print '%5d : %-30s%-25s %s' % (num_common, iconfig.ljust(30), 1769cb008830SSimon Glass kconfig_info, missing_str) 1770cb008830SSimon Glass 1771cb008830SSimon Glass # Having collected a list of things to add, now we add them. We process 1772cb008830SSimon Glass # each file from the largest line number to the smallest so that 1773cb008830SSimon Glass # earlier additions do not affect our line numbers. E.g. if we added an 1774cb008830SSimon Glass # imply at line 20 it would change the position of each line after 1775cb008830SSimon Glass # that. 1776cb008830SSimon Glass for fname, linenums in add_list.iteritems(): 1777cb008830SSimon Glass for linenum in sorted(linenums, reverse=True): 1778cb008830SSimon Glass add_imply_rule(config[CONFIG_LEN:], fname, linenum) 177999b66605SSimon Glass 178099b66605SSimon Glass 17815a27c734SMasahiro Yamadadef main(): 17825a27c734SMasahiro Yamada try: 17835a27c734SMasahiro Yamada cpu_count = multiprocessing.cpu_count() 17845a27c734SMasahiro Yamada except NotImplementedError: 17855a27c734SMasahiro Yamada cpu_count = 1 17865a27c734SMasahiro Yamada 17875a27c734SMasahiro Yamada parser = optparse.OptionParser() 17885a27c734SMasahiro Yamada # Add options here 1789cb008830SSimon Glass parser.add_option('-a', '--add-imply', type='string', default='', 1790cb008830SSimon Glass help='comma-separated list of CONFIG options to add ' 1791cb008830SSimon Glass "an 'imply' statement to for the CONFIG in -i") 1792cb008830SSimon Glass parser.add_option('-A', '--skip-added', action='store_true', default=False, 1793cb008830SSimon Glass help="don't show options which are already marked as " 1794cb008830SSimon Glass 'implying others') 1795d73fcb12SSimon Glass parser.add_option('-b', '--build-db', action='store_true', default=False, 1796d73fcb12SSimon Glass help='build a CONFIG database') 17975a27c734SMasahiro Yamada parser.add_option('-c', '--color', action='store_true', default=False, 17985a27c734SMasahiro Yamada help='display the log in color') 17999ede2123SSimon Glass parser.add_option('-C', '--commit', action='store_true', default=False, 18009ede2123SSimon Glass help='Create a git commit for the operation') 180191040e85SJoe Hershberger parser.add_option('-d', '--defconfigs', type='string', 1802ee4e61bdSSimon Glass help='a file containing a list of defconfigs to move, ' 1803ee4e61bdSSimon Glass "one per line (for example 'snow_defconfig') " 1804ee4e61bdSSimon Glass "or '-' to read from stdin") 180599b66605SSimon Glass parser.add_option('-i', '--imply', action='store_true', default=False, 180699b66605SSimon Glass help='find options which imply others') 18079b2a2e87SSimon Glass parser.add_option('-I', '--imply-flags', type='string', default='', 18089b2a2e87SSimon Glass help="control the -i option ('help' for help") 18095a27c734SMasahiro Yamada parser.add_option('-n', '--dry-run', action='store_true', default=False, 18105a27c734SMasahiro Yamada help='perform a trial run (show log with no changes)') 18115a27c734SMasahiro Yamada parser.add_option('-e', '--exit-on-error', action='store_true', 18125a27c734SMasahiro Yamada default=False, 18135a27c734SMasahiro Yamada help='exit immediately on any error') 18148513dc04SMasahiro Yamada parser.add_option('-s', '--force-sync', action='store_true', default=False, 18158513dc04SMasahiro Yamada help='force sync by savedefconfig') 181607913d1eSMasahiro Yamada parser.add_option('-S', '--spl', action='store_true', default=False, 181707913d1eSMasahiro Yamada help='parse config options defined for SPL build') 18182144f880SJoe Hershberger parser.add_option('-H', '--headers-only', dest='cleanup_headers_only', 18192144f880SJoe Hershberger action='store_true', default=False, 18202144f880SJoe Hershberger help='only cleanup the headers') 18215a27c734SMasahiro Yamada parser.add_option('-j', '--jobs', type='int', default=cpu_count, 18225a27c734SMasahiro Yamada help='the number of jobs to run simultaneously') 18236b96c1a1SJoe Hershberger parser.add_option('-r', '--git-ref', type='string', 18246b96c1a1SJoe Hershberger help='the git ref to clone for building the autoconf.mk') 18256b403dfdSSimon Glass parser.add_option('-y', '--yes', action='store_true', default=False, 18266b403dfdSSimon Glass help="respond 'yes' to any prompts") 182795bf9c7eSJoe Hershberger parser.add_option('-v', '--verbose', action='store_true', default=False, 182895bf9c7eSJoe Hershberger help='show any build errors as boards are built') 1829b6ef393aSMasahiro Yamada parser.usage += ' CONFIG ...' 18305a27c734SMasahiro Yamada 1831b6ef393aSMasahiro Yamada (options, configs) = parser.parse_args() 18325a27c734SMasahiro Yamada 183399b66605SSimon Glass if len(configs) == 0 and not any((options.force_sync, options.build_db, 183499b66605SSimon Glass options.imply)): 18355a27c734SMasahiro Yamada parser.print_usage() 18365a27c734SMasahiro Yamada sys.exit(1) 18375a27c734SMasahiro Yamada 1838b6ef393aSMasahiro Yamada # prefix the option name with CONFIG_ if missing 1839b6ef393aSMasahiro Yamada configs = [ config if config.startswith('CONFIG_') else 'CONFIG_' + config 1840b6ef393aSMasahiro Yamada for config in configs ] 18415a27c734SMasahiro Yamada 18422144f880SJoe Hershberger check_top_directory() 18432144f880SJoe Hershberger 184499b66605SSimon Glass if options.imply: 18459b2a2e87SSimon Glass imply_flags = 0 1846dee36c74SSimon Glass if options.imply_flags == 'all': 1847dee36c74SSimon Glass imply_flags = -1 1848dee36c74SSimon Glass 1849dee36c74SSimon Glass elif options.imply_flags: 1850dee36c74SSimon Glass for flag in options.imply_flags.split(','): 1851dee36c74SSimon Glass bad = flag not in IMPLY_FLAGS 1852dee36c74SSimon Glass if bad: 1853dee36c74SSimon Glass print "Invalid flag '%s'" % flag 1854dee36c74SSimon Glass if flag == 'help' or bad: 18559b2a2e87SSimon Glass print "Imply flags: (separate with ',')" 18569b2a2e87SSimon Glass for name, info in IMPLY_FLAGS.iteritems(): 18579b2a2e87SSimon Glass print ' %-15s: %s' % (name, info[1]) 18589b2a2e87SSimon Glass parser.print_usage() 18599b2a2e87SSimon Glass sys.exit(1) 18609b2a2e87SSimon Glass imply_flags |= IMPLY_FLAGS[flag][0] 18619b2a2e87SSimon Glass 1862cb008830SSimon Glass do_imply_config(configs, options.add_imply, imply_flags, 1863cb008830SSimon Glass options.skip_added) 186499b66605SSimon Glass return 186599b66605SSimon Glass 1866d73fcb12SSimon Glass config_db = {} 1867d73fcb12SSimon Glass db_queue = Queue.Queue() 1868d73fcb12SSimon Glass t = DatabaseThread(config_db, db_queue) 1869d73fcb12SSimon Glass t.setDaemon(True) 1870d73fcb12SSimon Glass t.start() 1871d73fcb12SSimon Glass 18722144f880SJoe Hershberger if not options.cleanup_headers_only: 1873f7536f79SMasahiro Yamada check_clean_directory() 18746821a745SSimon Glass bsettings.Setup('') 18756821a745SSimon Glass toolchains = toolchain.Toolchains() 18766821a745SSimon Glass toolchains.GetSettings() 18776821a745SSimon Glass toolchains.Scan(verbose=False) 18786821a745SSimon Glass move_config(toolchains, configs, options, db_queue) 1879d73fcb12SSimon Glass db_queue.join() 18805a27c734SMasahiro Yamada 18816a9f79f7SMasahiro Yamada if configs: 1882e9ea1221SMasahiro Yamada cleanup_headers(configs, options) 18839ab0296aSMasahiro Yamada cleanup_extra_options(configs, options) 1884ca43834dSChris Packham cleanup_whitelist(configs, options) 1885f90df596SChris Packham cleanup_readme(configs, options) 18862144f880SJoe Hershberger 18879ede2123SSimon Glass if options.commit: 18889ede2123SSimon Glass subprocess.call(['git', 'add', '-u']) 18899ede2123SSimon Glass if configs: 18909ede2123SSimon Glass msg = 'Convert %s %sto Kconfig' % (configs[0], 18919ede2123SSimon Glass 'et al ' if len(configs) > 1 else '') 18929ede2123SSimon Glass msg += ('\n\nThis converts the following to Kconfig:\n %s\n' % 18939ede2123SSimon Glass '\n '.join(configs)) 18949ede2123SSimon Glass else: 18959ede2123SSimon Glass msg = 'configs: Resync with savedefconfig' 18969ede2123SSimon Glass msg += '\n\nRsync all defconfig files using moveconfig.py' 18979ede2123SSimon Glass subprocess.call(['git', 'commit', '-s', '-m', msg]) 18989ede2123SSimon Glass 1899d73fcb12SSimon Glass if options.build_db: 1900d73fcb12SSimon Glass with open(CONFIG_DATABASE, 'w') as fd: 1901d73fcb12SSimon Glass for defconfig, configs in config_db.iteritems(): 1902c79d18c4SSimon Glass fd.write('%s\n' % defconfig) 1903d73fcb12SSimon Glass for config in sorted(configs.keys()): 1904c79d18c4SSimon Glass fd.write(' %s=%s\n' % (config, configs[config])) 1905c79d18c4SSimon Glass fd.write('\n') 1906d73fcb12SSimon Glass 19075a27c734SMasahiro Yamadaif __name__ == '__main__': 19085a27c734SMasahiro Yamada main() 1909