Ability to clean individual targets?

Currently I don’t believe you can clean individual targets correct?

I know in Visual Studio you can clean individual targets. And I believe other generators support a similar ability to clean individual targets but I might be wrong. Currently I believe the only way to clean is to just clean all the targets.

# Clean all targets
cmake --build C:/foo/build/ --target clean

Depending on your project structure, you may be able to just delete some directories from your build directory and re-run CMake to restore it back to a buildable state. It’s a bit of a poor man’s clean, but it can be good enough in some cases. I do that sometimes in complicated projects where ccache isn’t all that effective but the directory structure is very modular. If ccache is effective, it often doesn’t take long to do a full rebuild of the same sources, so cleaning the whole project is usually no big deal in that case.

1 Like

I basically agree @craig.scott that it’s not too much of an issue.

However, this lack of functionality causes an awkward workflow for IDEs that integrate with CMake.

For example I’m using the CMakeSettings.json and this is what I’m presented with:
image

If you used vanilla visual studio you could clean individual targets, as shown here:
image

I guess because the CMakeSettings.json route tries to use cmake for everything it can’t just clean individual targets because CMake doesn’t provide that functionality.

I’m not sure that the problem is specific to CMake. For any build tool, if there was a “clean target” feature, what would you expect to happen for a target that linked against other libraries? Should it also clean those libraries too? The answer to that will probably be different for different people, making this feature either misleading or dangerous depending on which choice the IDE made.

1 Like

For any build tool, if there was a “clean target” feature, what would you expect to happen for a target that linked against other libraries?

Good point. I guess I didn’t think about this too deeply. Thanks for pointing this out :+1:

I’ll look into what Visual Studio does when I have a chance.

I just check what my generated visual studio solution does when I clean an individual target:

Clean started...
1>------ Clean started: Project: foobar, Configuration: Release x64 ------
2>------ Clean started: Project: foobar2, Configuration: Release x64 ------
3>------ Clean started: Project: foobar3, Configuration: Release x64 ------
4>------ Clean started: Project: foobar4, Configuration: Release x64 ------
...
23>------ Clean started: Project: foobar5, Configuration: Release x64 ------
24>------ Clean started: Project: ZERO_CHECK, Configuration: Release x64 ------
========== Clean: 24 succeeded, 0 failed, 0 skipped ==========

It cleans all the targets in the dependency chain that could affect the target I built.
I think this behavior is pretty reasonable.

In this example I cleaned foobar and foobar has dependencies on foobar2,3,4 etc. So Visual Studio cleaned all my dependencies.

I was a bit confused at first since you are mentioning VS and generators. I am not familiar with VS. To clarify my understanding:

  • Vanilla VS doesn’t use CMake, but allows to clean individual targets.
  • CMake does not allow to clean individual targets using VS generator

I don’t think it is. For an development environment imagine a different scenario where i have 2 top level targets, foobar and foobar2, with common dependencies. I don’t want to clean the dependers (but maybe the dependees - those are rebuild anyways so a clean wouldn’t hurt). Otherwise what difference does it make to a global clean?

Besides the bigger issue is probably when the tool doesn’t work as expected. On the other hand if i set my dependencies wrong i am running into problems, sooner or later anyways (i’d blame it on the tools though, obviously).

When i clean individual targets in CMake it only affects the targets. This is not an extensive test so maybe i am overlooking something.

# Clean individual build directory (i.e. ~ target)
cmake --build C:/foo/build/src/foobar --target clean

If i wanted to propagate the clean to dependers or dependees I suppose I could support this myself using custom targets? I am not sure about the details to implement this.

This doesn’t work for all generators. Ninja, for instance, only has a single ninja -t clean exposed via CMake. You can do ninja -t clean tgt1 tgt2, but this also doesn’t have a way of specifying the same thing in other generators. Makefiles generators, I believe, have a per-directory clean target. VS has its behavior as shown in this thread already. I don’t know what Xcode does.

Anyways, CMake would basically have to implement its own cleaning mechanisms before consistent behavior for all generators could be exposed (other than “clean everything”).

1 Like

A consistent behaviour for all generators could simply be an error message for

# error - not the build directory
cmake --build C:/foo/build/src/foobar --target clean

because I can still do make -C C:/foo/build/src/foobar clean to achieve the same thing as above.

I think that’s already an error case, no? IIRC, --build would expect a CMakeCache.txt which only exists at the top-level.

no,

cd C:/foo/build
cmake ..
# Clean individual build directory (i.e. ~ target)
cmake --build C:/foo/build/src/foobar --target clean

works just fine from anywhere inside the build directory, using Makefile generator. CMakeCache.txt only exists at top-level build directory. No error is shown. For other generators this results in error.

Ah, thanks. News to me (though I generally use the Ninja generator).