Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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