Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kbuild: add Kbuild bash completion

Kernel build commands can sometimes be long, particularly when
cross-compiling, making them tedious to type and prone to mistypes.

This commit introduces bash completion support for common variables
and targets in Kbuild.

For installation instructions, please refer to the documentation in
Documentation/kbuild/bash-completion.rst.

The following examples demonstrate how this saves typing.

[Example 1] a long command line for cross-compiling

$ make A<TAB>
-> completes 'A' to 'ARCH='

$ make ARCH=<TAB>
-> displays all supported architectures

$ make ARCH=arm64 CR<TAB>
-> completes 'CR' to 'CROSS_COMPILE='

$ make ARCH=arm64 CROSS_COMPILE=<TAB>
-> displays installed toolchains

$ make ARCH=arm64 CROSS_COMPILE=aa<TAB>
-> completes 'CROSS_COMPILE=aa' to 'CROSS_COMPILE=aarch64-linux-gnu-'

$ make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- def<TAB>
-> completes 'def' to 'defconfig'

[Example 2] a single build target

$ make f<TAB>
-> completes 'f' to 'fs/'

$ make fs/<TAB>
-> displays objects and sub-directories in fs/

$ make fs/xf<TAB>
-> completes 'fs/xf' to 'fs/xfs/'

$ make fs/xfs/l<TAB>
-> completes 'fs/xfs/l' to 'fs/xfs/libxfs/xfs_'

$ make fs/xfs/libxfs/xfs_g<TAB>
-> completes 'fs/xfs/libxfs/xfs_g' to 'fs/xfs/libxfs/xfs_group.o'

This does not aim to provide a complete list of variables and targets,
as there are too many. However, it covers variables and targets used
in common scenarios, and I hope this is useful enough.

Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nicolas Schier <n.schier@avm.de>
Tested-by: Nicolas Schier <n.schier@avm.de>

+519
+65
Documentation/kbuild/bash-completion.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0-only 2 + 3 + ========================== 4 + Bash completion for Kbuild 5 + ========================== 6 + 7 + The kernel build system is written using Makefiles, and Bash completion 8 + for the `make` command is available through the `bash-completion`_ project. 9 + 10 + However, the Makefiles for the kernel build are complex. The generic completion 11 + rules for the `make` command do not provide meaningful suggestions for the 12 + kernel build system, except for the options of the `make` command itself. 13 + 14 + To enhance completion for various variables and targets, the kernel source 15 + includes its own completion script at `scripts/bash-completion/make`. 16 + 17 + This script provides additional completions when working within the kernel tree. 18 + Outside the kernel tree, it defaults to the generic completion rules for the 19 + `make` command. 20 + 21 + Prerequisites 22 + ============= 23 + 24 + The script relies on helper functions provided by `bash-completion`_ project. 25 + Please ensure it is installed on your system. On most distributions, you can 26 + install the `bash-completion` package through the standard package manager. 27 + 28 + How to use 29 + ========== 30 + 31 + You can source the script directly:: 32 + 33 + $ source scripts/bash-completion/make 34 + 35 + Or, you can copy it into the search path for Bash completion scripts. 36 + For example:: 37 + 38 + $ mkdir -p ~/.local/share/bash-completion/completions 39 + $ cp scripts/bash-completion/make ~/.local/share/bash-completion/completions/ 40 + 41 + Details 42 + ======= 43 + 44 + The additional completion for Kbuild is enabled in the following cases: 45 + 46 + - You are in the root directory of the kernel source. 47 + - You are in the top-level build directory created by the O= option 48 + (checked via the `source` symlink pointing to the kernel source). 49 + - The -C make option specifies the kernel source or build directory. 50 + - The -f make option specifies a file in the kernel source or build directory. 51 + 52 + If none of the above are met, it falls back to the generic completion rules. 53 + 54 + The completion supports: 55 + 56 + - Commonly used targets, such as `all`, `menuconfig`, `dtbs`, etc. 57 + - Make (or environment) variables, such as `ARCH`, `LLVM`, etc. 58 + - Single-target builds (`foo/bar/baz.o`) 59 + - Configuration files (`*_defconfig` and `*.config`) 60 + 61 + Some variables offer intelligent behavior. For instance, `CROSS_COMPILE=` 62 + followed by a TAB displays installed toolchains. The list of defconfig files 63 + shown depends on the value of the `ARCH=` variable. 64 + 65 + .. _bash-completion: https://github.com/scop/bash-completion/
+2
Documentation/kbuild/index.rst
··· 23 23 llvm 24 24 gendwarfksyms 25 25 26 + bash-completion 27 + 26 28 .. only:: subproject and html 27 29 28 30 Indices
+1
MAINTAINERS
··· 12566 12566 F: scripts/*vmlinux* 12567 12567 F: scripts/Kbuild* 12568 12568 F: scripts/Makefile* 12569 + F: scripts/bash-completion/ 12569 12570 F: scripts/basic/ 12570 12571 F: scripts/clang-tools/ 12571 12572 F: scripts/dummy-tools/
+451
scripts/bash-completion/make
··· 1 + # SPDX-License-Identifier: GPL-2.0-only 2 + # bash completion for GNU make with kbuild extension -*- shell-script -*- 3 + 4 + # Load the default completion script for make. It is typically located at 5 + # /usr/share/bash-completion/completions/make, but we do not rely on it. 6 + __kbuild_load_default_make_completion() 7 + { 8 + local -a dirs=("${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions") 9 + local ifs=$IFS IFS=: dir compfile this_dir 10 + 11 + for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share}; do 12 + dirs+=("$dir"/bash-completion/completions) 13 + done 14 + IFS=$ifs 15 + 16 + this_dir="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" 17 + 18 + for dir in "${dirs[@]}"; do 19 + if [[ ! -d ${dir} || ${dir} = "${this_dir}" ]]; then 20 + continue 21 + fi 22 + 23 + for compfile in make make.bash _make; do 24 + compfile=$dir/$compfile 25 + # Avoid trying to source dirs; https://bugzilla.redhat.com/903540 26 + if [[ -f ${compfile} ]] && . "${compfile}" &>/dev/null; then 27 + 28 + __kbuild_default_make_completion=$( 29 + # shellcheck disable=SC2046 # word splitting is the point here 30 + set -- $(complete -p make) 31 + 32 + while [[ $# -gt 1 && "$1" != -F ]]; do 33 + shift 34 + done 35 + 36 + if [[ "$1" = -F ]]; then 37 + echo "$2" 38 + fi 39 + ) 40 + 41 + return 42 + fi 43 + done 44 + done 45 + } 46 + 47 + __kbuild_load_default_make_completion 48 + 49 + __kbuild_handle_variable() 50 + { 51 + local var=${1%%=*} 52 + local cur=${cur#"${var}"=} 53 + local srctree=$2 54 + local keywords=() 55 + 56 + case $var in 57 + ARCH) 58 + # sub-directories under arch/ 59 + keywords+=($(find "${srctree}/arch" -mindepth 1 -maxdepth 1 -type d -printf '%P\n')) 60 + # architectures hard-coded in the top Makefile 61 + keywords+=(i386 x86_64 sparc32 sparc64 parisc64) 62 + ;; 63 + CROSS_COMPILE) 64 + # toolchains with a full path 65 + local cross_compile=() 66 + local c c2 67 + _filedir 68 + 69 + for c in "${COMPREPLY[@]}"; do 70 + # eval for tilde expansion 71 + # suppress error, as this fails when it contains a space 72 + eval "c2=${c}" 2>/dev/null || continue 73 + if [[ ${c} == *-elfedit && ! -d ${c2} && -x ${c2} ]]; then 74 + cross_compile+=("${c%elfedit}") 75 + fi 76 + done 77 + 78 + # toolchains in the PATH environment 79 + while read -r c; do 80 + if [[ ${c} == *-elfedit ]]; then 81 + keywords+=("${c%elfedit}") 82 + fi 83 + done < <(compgen -c) 84 + 85 + COMPREPLY=() 86 + _filedir -d 87 + 88 + # Add cross_compile directly without passing it to compgen. 89 + # Otherwise, toolchain paths with a tilde do not work. 90 + # e.g.) 91 + # CROSS_COMPILE=~/0day/gcc-14.2.0-nolibc/aarch64-linux/bin/aarch64-linux- 92 + COMPREPLY+=("${cross_compile[@]}") 93 + ;; 94 + LLVM) 95 + # LLVM=1 uses the default 'clang' etc. 96 + keywords+=(1) 97 + 98 + # suffix for a particular version. LLVM=-18 uses 'clang-18' etc. 99 + while read -r c; do 100 + if [[ ${c} == clang-[0-9]* ]]; then 101 + keywords+=("${c#clang}") 102 + fi 103 + done < <(compgen -c) 104 + 105 + # directory path to LLVM toolchains 106 + _filedir -d 107 + ;; 108 + KCONFIG_ALLCONFIG) 109 + # KCONFIG_ALLCONFIG=1 selects the default fragment 110 + keywords+=(1) 111 + # or the path to a fragment file 112 + _filedir 113 + ;; 114 + C | KBUILD_CHECKSRC) 115 + keywords+=(1 2) 116 + ;; 117 + V | KBUILD_VERBOSE) 118 + keywords+=({,1}{,2}) 119 + ;; 120 + W | KBUILD_EXTRA_WARN) 121 + keywords+=({,1}{,2}{,3}{,c}{,e}) 122 + ;; 123 + KBUILD_ABS_SRCTREE | KBUILD_MODPOST_NOFINAL | KBUILD_MODPOST_WARN | \ 124 + CLIPPY | KBUILD_CLIPPY | KCONFIG_NOSILENTUPDATE | \ 125 + KCONFIG_OVERWRITECONFIG | KCONFIG_WARN_UNKNOWN_SYMBOL | \ 126 + KCONFIG_WERROR ) 127 + keywords+=(1) 128 + ;; 129 + INSTALL_MOD_STRIP) 130 + keywords+=(1 --strip-debug --strip-unneeded) 131 + ;; 132 + O | KBUILD_OUTPUT | M | KBUILD_EXTMOD | MO | KBUILD_EXTMOD_OUTPUT | *_PATH) 133 + # variables that take a directory. 134 + _filedir -d 135 + return 136 + ;; 137 + KBUILD_EXTRA_SYMBOL | KBUILD_KCONFIG | KCONFIG_CONFIG) 138 + # variables that take a file. 139 + _filedir 140 + return 141 + esac 142 + 143 + COMPREPLY+=($(compgen -W "${keywords[*]}" -- "${cur}")) 144 + } 145 + 146 + # Check the -C, -f options and 'source' symlink. Return the source tree we are 147 + # working in. 148 + __kbuild_get_srctree() 149 + { 150 + local words=("$@") 151 + local cwd makef_dir 152 + 153 + # see if a path was specified with -C/--directory 154 + for ((i = 1; i < ${#words[@]}; i++)); do 155 + if [[ ${words[i]} == -@(C|-directory) ]]; then 156 + # eval for tilde expansion. 157 + # suppress error, as this fails when it contains a space 158 + eval "cwd=${words[i + 1]}" 2>/dev/null 159 + break 160 + fi 161 + done 162 + 163 + if [[ -z ${cwd} ]]; then 164 + cwd=. 165 + fi 166 + 167 + # see if a Makefile was specified with -f/--file/--makefile 168 + for ((i = 1; i < ${#words[@]}; i++)); do 169 + if [[ ${words[i]} == -@(f|-?(make)file) ]]; then 170 + # eval for tilde expansion 171 + # suppress error, as this fails when it contains a space 172 + eval "makef_dir=${words[i + 1]%/*}" 2>/dev/null 173 + break 174 + fi 175 + done 176 + 177 + if [ -z "${makef_dir}" ]; then 178 + makef_dir=${cwd} 179 + elif [[ ${makef_dir} != /* ]]; then 180 + makef_dir=${cwd}/${makef_dir} 181 + fi 182 + 183 + # If ${makef_dir} is a build directory created by the O= option, there 184 + # is a symbolic link 'source', which points to the kernel source tree. 185 + if [[ -L ${makef_dir}/source ]]; then 186 + makef_dir=$(readlink "${makef_dir}/source") 187 + fi 188 + 189 + echo "${makef_dir}" 190 + } 191 + 192 + # Get SRCARCH to do a little more clever things 193 + __kbuild_get_srcarch() 194 + { 195 + local words=("$@") 196 + local arch srcarch uname_m 197 + 198 + # see if ARCH= is explicitly specified 199 + for ((i = 1; i < ${#words[@]}; i++)); do 200 + if [[ ${words[i]} == ARCH=* ]]; then 201 + arch=${words[i]#ARCH=} 202 + break 203 + fi 204 + done 205 + 206 + # If ARCH= is not specified, check the build marchine's architecture 207 + if [[ -z ${arch} ]]; then 208 + uname_m=$(uname -m) 209 + 210 + # shellcheck disable=SC2209 # 'sh' is SuperH, not a shell command 211 + case ${uname_m} in 212 + arm64 | aarch64*) arch=arm64 ;; 213 + arm* | sa110) arch=arm ;; 214 + i?86 | x86_64) arch=x86 ;; 215 + loongarch*) arch=loongarch ;; 216 + mips*) arch=mips ;; 217 + ppc*) arch=powerpc ;; 218 + riscv*) arch=riscv ;; 219 + s390x) arch=s390 ;; 220 + sh[234]*) arch=sh ;; 221 + sun4u) arch=sparc64 ;; 222 + *) arch=${uname_m} ;; 223 + esac 224 + fi 225 + 226 + case ${arch} in 227 + parisc64) srcarch=parisc ;; 228 + sparc32 | sparc64) srcarch=sparc ;; 229 + i386 | x86_64) srcarch=x86 ;; 230 + *) srcarch=${arch} ;; 231 + esac 232 + 233 + echo "$srcarch" 234 + } 235 + 236 + # small Makefile to parse obj-* syntax 237 + __kbuild_tmp_makefile() 238 + { 239 + cat <<'EOF' 240 + .PHONY: __default 241 + __default: 242 + $(foreach m,$(obj-y) $(obj-m) $(obj-),$(foreach s, -objs -y -m -,$($(m:%.o=%$s))) $(m)) 243 + EOF 244 + echo "include ${1}" 245 + } 246 + 247 + _make_for_kbuild () 248 + { 249 + # shellcheck disable=SC2034 # these are set by _init_completion 250 + local cur prev words cword split 251 + _init_completion -s || return 252 + 253 + local srctree 254 + srctree=$(__kbuild_get_srctree "${words[@]}") 255 + 256 + # If 'kernel' and 'Documentation' directories are found, we assume this 257 + # is a kernel tree. Otherwise, we fall back to the generic rule provided 258 + # by the bash-completion project. 259 + if [[ ! -d ${srctree}/kernel || ! -d ${srctree}/Documentation ]]; then 260 + if [ -n "${__kbuild_default_make_completion}" ]; then 261 + "${__kbuild_default_make_completion}" "$@" 262 + fi 263 + return 264 + fi 265 + 266 + # make options with a parameter (copied from the bash-completion project) 267 + case ${prev} in 268 + --file | --makefile | --old-file | --assume-old | --what-if | --new-file | \ 269 + --assume-new | -!(-*)[foW]) 270 + _filedir 271 + return 272 + ;; 273 + --include-dir | --directory | -!(-*)[ICm]) 274 + _filedir -d 275 + return 276 + ;; 277 + -!(-*)E) 278 + COMPREPLY=($(compgen -v -- "$cur")) 279 + return 280 + ;; 281 + --eval | -!(-*)[DVx]) 282 + return 283 + ;; 284 + --jobs | -!(-*)j) 285 + COMPREPLY=($(compgen -W "{1..$(($(_ncpus) * 2))}" -- "$cur")) 286 + return 287 + ;; 288 + esac 289 + 290 + local keywords=() 291 + 292 + case ${cur} in 293 + -*) 294 + # make options (copied from the bash-completion project) 295 + local opts 296 + opts="$(_parse_help "$1")" 297 + COMPREPLY=($(compgen -W "${opts:-$(_parse_usage "$1")}" -- "$cur")) 298 + if [[ ${COMPREPLY-} == *= ]]; then 299 + compopt -o nospace 300 + fi 301 + return 302 + ;; 303 + *=*) 304 + __kbuild_handle_variable "${cur}" "${srctree}" 305 + return 306 + ;; 307 + KBUILD_*) 308 + # There are many variables prefixed with 'KBUILD_'. 309 + # Display them only when 'KBUILD_' is entered. 310 + # shellcheck disable=SC2191 # '=' is appended for variables 311 + keywords+=( 312 + KBUILD_{CHECKSRC,EXTMOD,EXTMOD_OUTPUT,OUTPUT,VERBOSE,EXTRA_WARN,CLIPPY}= 313 + KBUILD_BUILD_{USER,HOST,TIMESTAMP}= 314 + KBUILD_MODPOST_{NOFINAL,WARN}= 315 + KBUILD_{ABS_SRCTREE,EXTRA_SYMBOLS,KCONFIG}= 316 + ) 317 + ;; 318 + KCONFIG_*) 319 + # There are many variables prefixed with 'KCONFIG_'. 320 + # Display them only when 'KCONFIG_' is entered. 321 + # shellcheck disable=SC2191 # '=' is appended for variables 322 + keywords+=( 323 + KCONFIG_{CONFIG,ALLCONFIG,NOSILENTUPDATE,OVERWRITECONFIG}= 324 + KCONFIG_{SEED,PROBABILITY}= 325 + KCONFIG_WARN_UNKNOWN_SYMBOL= 326 + KCONFIG_WERROR= 327 + ) 328 + ;; 329 + *) 330 + # By default, hide KBUILD_* and KCONFIG_* variables. 331 + # Instead, display only the prefix parts. 332 + keywords+=(KBUILD_ KCONFIG_) 333 + ;; 334 + esac 335 + 336 + if [[ ${cur} != /* && ${cur} != *//* ]]; then 337 + local dir srcarch kbuild_file tmp 338 + srcarch=$(__kbuild_get_srcarch "${words[@]}") 339 + 340 + # single build 341 + dir=${cur} 342 + while true; do 343 + if [[ ${dir} == */* ]]; then 344 + dir=${dir%/*} 345 + else 346 + dir=. 347 + fi 348 + 349 + # Search for 'Kbuild' or 'Makefile' in the parent 350 + # directories (may not be a direct parent) 351 + if [[ -f ${srctree}/${dir}/Kbuild ]]; then 352 + kbuild_file=${srctree}/${dir}/Kbuild 353 + break 354 + fi 355 + if [[ -f ${srctree}/${dir}/Makefile ]]; then 356 + kbuild_file=${srctree}/${dir}/Makefile 357 + break 358 + fi 359 + 360 + if [[ ${dir} == . ]]; then 361 + break 362 + fi 363 + done 364 + 365 + if [[ -n ${kbuild_file} ]]; then 366 + tmp=($(__kbuild_tmp_makefile "${kbuild_file}" | 367 + SRCARCH=${srcarch} obj=${dir} src=${srctree}/${dir} \ 368 + "${1}" -n -f - 2>/dev/null)) 369 + 370 + # Add $(obj)/ prefix 371 + if [[ ${dir} != . ]]; then 372 + tmp=("${tmp[@]/#/${dir}\/}") 373 + fi 374 + 375 + keywords+=("${tmp[@]}") 376 + fi 377 + 378 + # *_defconfig and *.config files. These might be grouped into 379 + # subdirectories, e.g., arch/powerpc/configs/*/*_defconfig. 380 + if [[ ${cur} == */* ]]; then 381 + dir=${cur%/*} 382 + else 383 + dir=. 384 + fi 385 + 386 + tmp=($(find "${srctree}/arch/${srcarch}/configs/${dir}" \ 387 + "${srctree}/kernel/configs/${dir}" \ 388 + -mindepth 1 -maxdepth 1 -type d -printf '%P/\n' \ 389 + -o -printf '%P\n' 2>/dev/null)) 390 + 391 + if [[ ${dir} != . ]]; then 392 + tmp=("${tmp[@]/#/${dir}\/}") 393 + fi 394 + 395 + keywords+=("${tmp[@]}") 396 + fi 397 + 398 + # shellcheck disable=SC2191 # '=' is appended for variables 399 + keywords+=( 400 + # 401 + # variables (append =) 402 + # 403 + ARCH= 404 + CROSS_COMPILE= 405 + LLVM= 406 + C= M= MO= O= V= W= 407 + INSTALL{,_MOD,_HDR,_DTBS}_PATH= 408 + KERNELRELEASE= 409 + 410 + # 411 + # targets 412 + # 413 + all help 414 + clean mrproper distclean 415 + clang-{tidy,analyzer} compile_commands.json 416 + coccicheck 417 + dtbs{,_check,_install} dt_binding_{check,schemas} 418 + headers{,_install} 419 + vmlinux install 420 + modules{,_prepare,_install,_sign} 421 + vdso_install 422 + tags TAGS cscope gtags 423 + rust{available,fmt,fmtcheck} 424 + kernel{version,release} image_name 425 + kselftest{,-all,-install,-clean,-merge} 426 + 427 + # configuration 428 + {,old,olddef,sync,def,savedef,rand,listnew,helpnew,test,tiny}config 429 + {,build_}{menu,n,g,x}config 430 + local{mod,yes}config 431 + all{no,yes,mod,def}config 432 + {yes2mod,mod2yes,mod2no}config 433 + 434 + # docs 435 + {html,textinfo,info,latex,pdf,epub,xml,linkcheck,refcheck,clean}docs 436 + 437 + # package 438 + {,bin,src}{rpm,deb}-pkg 439 + {pacman,dir,tar}-pkg 440 + tar{,gz,bz2,xz,zst}-pkg 441 + perf-tar{,gz,bz2,xz,zst}-src-pkg 442 + ) 443 + 444 + COMPREPLY=($(compgen -W "${keywords[*]}" -- "${cur}")) 445 + 446 + # Do not append a space for variables, subdirs, "KBUILD_", "KCONFIG_". 447 + if [[ ${COMPREPLY-} == *[=/] || ${COMPREPLY-} =~ ^(KBUILD|KCONFIG)_$ ]]; then 448 + compopt -o nospace 449 + fi 450 + 451 + } && complete -F _make_for_kbuild make