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{ 239cat <<'EOF' 240.PHONY: __default 241__default: 242 $(foreach m,$(obj-y) $(obj-m) $(obj-),$(foreach s, -objs -y -m -,$($(m:%.o=%$s))) $(m)) 243EOF 244echo "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 452