Bash autocompletion of CMake targets

I guess it is caused by the special cmake sub commands like –build, or –install

bash-5.3$ cmake --help | grep -- '-tr'
  --debug-trycompile           = Do not delete the try_compile build tree.
  --trace                      = Put cmake in trace mode.
  --trace-expand               = Put cmake in trace mode with variable
  --trace-format=<human|json-v1>
  --trace-source=<file>        = Trace only this CMake file/module.  Multiple
  --trace-redirect=<file>      = Redirect trace output to a file instead of
                                 Supported formats: google-trace
bash-5.3$ cmake --build
Usage: cmake --build <dir>             [options] [-- [native-options]]
       cmake --build --preset <preset> [options] [-- [native-options]]
Options:
  <dir>          = Project binary directory to be built.
  --preset <preset>, --preset=<preset>
                 = Specify a build preset.
  --list-presets[=<type>]
                 = List available build presets.
  --parallel [<jobs>], -j [<jobs>]
                 = Build in parallel using the given number of jobs. 
                   If <jobs> is omitted the native build tool's 
                   default number is used.
                   The CMAKE_BUILD_PARALLEL_LEVEL environment variable
                   specifies a default parallel level when this option
                   is not given.
  -t <tgt>..., --target <tgt>...
                 = Build <tgt> instead of default targets.
  --config <cfg> = For multi-configuration tools, choose <cfg>.
  --clean-first  = Build target 'clean' first, then build.
                   (To clean only, use --target 'clean'.)
  --resolve-package-references={on|only|off}
                 = Restore/resolve package references during build.
  -v, --verbose  = Enable verbose output - if supported - including
                   the build commands to be executed. 
  --             = Pass remaining options to the native tool.
bash-5.3$ 

I just merged this version that Yves posted here, into my local (I am on OpenSuse and cmake 4.2.3, so the files had a few other differences) /usr/local/share/bash-completion/completions/cmake.

And tried it out, I works for me:

cmake --build ./build/GccRelease/ --target ==> gave me the selection of targets I have in my project, and when giving the first characters and it gave the correct filtered list.

Great job Yves :smile:

I think this doesn’t work with all generators ?

I tried with make generator, will also test with Ninja

UPDATE : my little test project: worked with Ninja too.

one thing which is not working is having –tar becoming –target (the moment a build dir has been specified after –build), when doing cmake –build –tar –> –target

Alex, why would you think this would not work with other generators, since the ‘list of targets’ is derived without knowledge of the generator (cmake –build build_dir –target help –> and processing that output) ?

Lieven, the cmake --build … --target help is redirected to the underlying build system, meaning that the generated output is not the same for any generator.
I only tested it for Unix Makefiles and Ninja generators, since those are the only ones of interest to me

bash-5.3$ cmake --build build/ --target help
Command line invocation:
    /Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild -project RRCP-client.xcodeproj build -configuration Debug -parallelizeTargets -hideShellScriptEnvironment -target help

User defaults from command line:
    HideShellScriptEnvironment = YES
    IDEPackageSupportUseBuiltinSCM = YES

2026-03-04 10:56:29.552 xcodebuild[19157:2083907] Writing error result bundle to /var/folders/wb/ckvxxgls5db7qyhqq4y5_l1c0000gq/T/ResultBundle_2026-04-03_10-56-0029.xcresult
xcodebuild: error: The project 'RRCP-client.xcodeproj' does not contain a target named 'help'.
bash-5.3$ 

xcode are IDE projects ? Like Visual Studio projects ?
I would assume command line tab completion is of less interest there since one is working in the IDE and using the GUI ?

make/ninja are real command line things, and there are benefits if one never needs to descend in the binary tree, or don’t even want to know if it is make or ninja.
Staying at the cmake level has advantages, by abstracting things away.

If for example one has integrated on the cmake –build level, and never cared about the fact that behind the curtain it was make, it allows an easy switch for example to Ninja, just the -G option needs to be added/altered.

And switching from make to Ninja is a roadmap, I think, many people will have to take, since cmake only support c++ modules with Ninja.

This issue is related to this: cmake --build: Unified mapping for cmake-generated targets

The json-files generated via the file API contain the list of all targets (… but the file API is not always active).

Maybe cmake could also by default write a simple file listing just the targets, or a minimal version of the json replies.