Feature request: Add support for subcommands like git and many CLI utils do (cargo, npm)

The main CMake binary could use the subcommands like cmake test, cmake install, cmake pack which may, like Git, call the wrappers like cmake-test, cmake-install, cmake-pack.

Users also may add their user extensions (like cmake-pgo which may run PGO scripts and collect profiles - see cargo-pgo, vcpkg/conan deps resolving (like similar --resolve-package-references in cmake --build`), etc.). These extensions could be handled via CMake configs in user home or system paths (whitelists, configs, etc.).

There is an even some repos with similar “subcommands-like” tools, like the cmake-init

To avoid breakage, the old cmake <path> command may be marked as deprecated and will be used if <path> exists, with gradual removing in favor of subcommands.

See also:
Article about creating subcommands for Git: Make your own Git subcommands | Opensource.com

I have a local draft for this feature, maybe would publish later if the idea gains the support.

1 Like

I’ve thought about this a few times, but I’m concerned about creating even more ways to do the same things. If we were starting from scratch today we’d use this approach, but we have almost 25 years of inertia behind the current command-line conventions.

the old cmake <path> command may be marked as deprecated and will be used if <path> exists

The meaning of cmake <path> is entrenched, so IMO the namespace for cmake subcommands is not available. We’d need a new top-level cm <subcommand> entry point. Mapping of new entry points to existing functionality, such as cm build to cmake --build would need to be carefully designed on a case-by-case basis.

One of the most common ways to invoke cmake is to just configure/generate a new build tree or regenerate an existing one. What cm <subcommand> signature(s) might you propose for that? They’d need to be no harder to type than cmake -B build or cmake --preset xyz.

I think that we may use abbreviated terms from ccmake, like gen with more longer alias generate.
I also thought about cfg , but it looks ambiguous (is it "configuring the current project or setting the config values for CMake itself?).
The ccmake btw may me called via nice short command cm tui , and cmake-gui may be cm gui.

What is the motivation, or what would be the benefit of that ?

What is the motivation, or what would be the benefit of that ?

Loose coupling, orthogonal design.

There are three binaries, cmake, cpack, and ctest. But each binary already has different subcommands, they just aren’t called like that. There is not much that cmake -B and cmake --build have in common. cmake -P has actually more in common with ctest -S than with cmake -E.

If you look at the size of the binaries, you see they are all about the same; ctest being slightly bigger that the other two. Why is that? It is because the cmMakefile class is at the core of the CMake language interpreter. All three binaries depend on the CMake language and therefore link against CMakeLib, with implementation of project generation and all. Combining all three to a single binary would not be substantially larger than the largest out of them. (Please don’t do that).

The implementation of the ctest_configure command constructs a cmake -B.. -S.. command line and then invokes it. But actually, it could just as well invoke cmake::Configure, it already has that dependency anyway (Please don’t do that either).

The implementation of ctest_test on the other hand does not construct a command line to invoke the tests, but it could be changed to do that. This would decouple ctest script mode from ctest test mode. If further a cmInterpreter was split out ouf cmMakefile, a cm-script subcommand could be implemented as a replacement of both cmake -P and ctest -S that would neither depend on the generators nor on the test driver.

It is crucial that the old commands cmake -P and ctest -S would be reimplemented as wrappers of the new commands. Too often in the cmake codebase, there are new approaches implemented on top of old ones.

2 Likes