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.

@craig.scott @brad.king what is now the plan to fix or add this feature?

Should I prepare an issue?

Creating an issue that clearly defines the goals would be a good start. Discussion there can be used to make decisions about the feature, drawing on the comments made here in this forum thread as a starting point. It will then be up to someone to volunteer their time to implement it once an agreed way forward has been reached.

It would be helpful if the issue description gave a concise summary of the current problems. Try not to lump unrelated things together, an issue focused on an achievable improvement is more likely to get a volunteer than something that looks like a grab-bag of related but distinct features.

I see 2 options:

  1. In short, I would make a PR to add the missing –target handling to the existing bash_completion
  2. And long-term the use of the file API, but is not clear to me, which advantages this has?

I like bash-completion on Unix, but on windows, it is terrible slow, and for other generators than ninja, or makefile, what would be the use cases?

I’d like a staged approach, we can already give value to the generators/platforms that support ‘cmake –build build –target help” ==> so if these gives an error, neutralize it and do nothing (no worse/better than today), if this does give valid output, we have the wanted completion, meaning we are doing better than today.

The POC mentioned here above can be used, with the modification for neutralizing an error return (the no help target it seems).