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.
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:
If you used vanilla visual studio you could clean individual targets, as shown here:
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.
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).
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”).
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.
Still would be nice to have ability to (clean-)rebuild (main) target since “ninja: no work to do” == no warnings to show. At least allow to add custom ‘actions’ like in Makefile.
The ninja build tool does not have any model of what outputs belong to what (cmake) targets. It is a monolithic build graph. There is no model for “clean target X”, so CMake has no direct way to express such a clean operation in build.ninja.
[main] Building folder: bplan
[build] Starting build
[proc] Executing command: "C:\Program Files\CMake\bin\cmake.EXE" --build C:/dan/dev/bplan/out/build/msvc-dbg --parallel 4 --target bplan-rebuild
[build] [0/2] Re-checking globbed directories...
[build] [1/2] Cleaning `bplan` target:
[build] Files for removal:
[build] C:/dan/dev/bplan/out/build/msvc-dbg/CMakeFiles/bplan.dir/src/
[build] [2/2] Rebuilding `bplan` target:
[build] [0/2] Re-checking globbed directories...
[build] [1/11] Building CXX object CMakeFiles\bplan.dir\src\int\imgui\tools\align_text.cpp.obj
[build] [2/11] Building CXX object CMakeFiles\bplan.dir\src\app\MainViewportMenuBar.cpp.obj
[build] [3/11] Building CXX object CMakeFiles\bplan.dir\src\app.cpp.obj
[build] [4/11] Building CXX object CMakeFiles\bplan.dir\src\app\DataTreeEditor.cpp.obj
[build] [5/11] Building CXX object CMakeFiles\bplan.dir\src\app\MainWindow.cpp.obj
[build] [6/11] Building CXX object CMakeFiles\bplan.dir\src\app\data\data.cpp.obj
[build] [7/11] Building CXX object CMakeFiles\bplan.dir\src\test\<file>.cpp.obj
[build] [8/11] Building CXX object CMakeFiles\bplan.dir\src\test\<file>.cpp.obj
[build] [9/11] Building CXX object CMakeFiles\bplan.dir\src\main.cpp.obj
[build] [10/11] Building CXX object CMakeFiles\bplan.dir\src\test\<file>.cpp.obj
[build] [11/11] Linking CXX executable C:\dan\dev\bplan\bplan.exe
[driver] Build completed: 00:00:06.965
[build] Build finished with exit code 0
Pity that add_custom_target accepts only cmdcommands and not cmake functions. Is it an interesting idea to add FUNCTION feature as for COMMAND alternative to CMake?
Also little flaw is that output flushes only after full completion, so no active build tracking .
That is a ninja design decision; nothing CMake does about that. You can assign commands to the console job pool, but then they cannot run concurrently with any other task either.
No, the context would be all wrong. Put it in a script and use cmake -P script.cmake with -D arguments to add other information as needed.
But turns out that the name add_clean_target for this function would better sound like clean_or_built_target because in most of my conditions it cleans the target after build, and the next time this target is invoked, it builds the target back. Anyway it does the work when needed, and all dependent targets are rebuilt after when necessary. But I landed with other solution (MSW specific a.t.m.):