# Ability to clean individual targets?

**URL:** https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980
**Category:** Development
**Created:** [March 19, 2021, 7:54pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980 "2021-03-19T19:54:48Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [March 19, 2021, 7:54pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/1 "2021-03-19T19:54:48Z")

</div>

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.

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

```

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [March 19, 2021, 9:12pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/2 "2021-03-19T21:12:06Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [March 19, 2021, 10:24pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/3 "2021-03-19T22:24:49Z")

</div>

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](https://discourse.cmake.org/uploads/default/original/2X/7/7a8bf23a12ec81d4d2268c8b4c7c983714939252.png)

If you used vanilla visual studio you could clean individual targets, as shown here:  
 ![image](https://discourse.cmake.org/uploads/default/original/2X/0/0d0b77b1cd7caa3c7340a007133c0f29523ee9cf.png)

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.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [March 19, 2021, 10:29pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/4 "2021-03-19T22:29:58Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [March 20, 2021, 12:22am UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/5 "2021-03-20T00:22:48Z")

</div>

> 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 👍

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

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [March 22, 2021, 5:57pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/6 "2021-03-22T17:57:35Z")

</div>

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

```auto
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.

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [March 22, 2021, 8:09pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/7 "2021-03-22T20:09:55Z")

</div>

> [@YMba9g8j9CJp0wLoQf5y](#):
>
> I know in Visual Studio you can clean individual targets. And I believe other generators support a similar ability

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

> [@YMba9g8j9CJp0wLoQf5y](#):
>
> I think this behavior is pretty reasonable.

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).

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [March 23, 2021, 8:45am UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/8 "2021-03-23T08:45:21Z")

</div>

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

```auto
# 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.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [March 23, 2021, 2:31pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/9 "2021-03-23T14:31:56Z")

</div>

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”).

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [March 23, 2021, 8:21pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/10 "2021-03-23T20:21:55Z")

</div>

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

```auto
# 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.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [March 23, 2021, 9:11pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/11 "2021-03-23T21:11:28Z")

</div>

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

---

<div class="post-metadata">

### Author: ![hex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hex/32/363_2.png) [@hex](https://discourse.cmake.org/u/hex)
#### Post date: [March 23, 2021, 9:17pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/12 "2021-03-23T21:17:58Z")

</div>

no,

```auto
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.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [March 23, 2021, 9:27pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/13 "2021-03-23T21:27:19Z")

</div>

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

---

<div class="post-metadata">

### Author: ![int\_main](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/i/e95f7d/32.png) [@int\_main](https://discourse.cmake.org/u/int_main)
#### Post date: [May 1, 2024, 7:31pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/14 "2024-05-01T19:31:59Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [May 1, 2024, 9:05pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/15 "2024-05-01T21:05:02Z")

</div>

> [@int\_main](#):
>
> At least allow to add custom ‘actions’ like in Makefile.

These are allowed in the `Ninja` generator. How do you get something like this in a way that doesn’t work for `Ninja`?

---

<div class="post-metadata">

### Author: ![int\_main](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/i/e95f7d/32.png) [@int\_main](https://discourse.cmake.org/u/int_main)
#### Post date: [May 1, 2024, 10:04pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/16 "2024-05-01T22:04:27Z")

</div>

Yeah, I [see](https://gitlab.kitware.com/cmake/cmake/-/issues/22566#note_1005029). That’s sad.

> 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`.

---

<div class="post-metadata">

### Author: ![int\_main](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/i/e95f7d/32.png) [@int\_main](https://discourse.cmake.org/u/int_main)
#### Post date: [May 2, 2024, 12:59pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/17 "2024-05-02T12:59:02Z")

</div>

Did it through folder deletion as noted above! New targets for **clean** and **rebuild**.

```cmake
# remove_recurse.cmake
message("Files for removal:")
string (REPLACE " " "\n " FILES_LIST_ "${FILES_}") # <--- ";" is missing without "\;"  
message(" " ${FILES_LIST_})

file(REMOVE_RECURSE "${FILES_}")

```

```cmake
# CMakeLists.txt
add_custom_target(${PROJECT_NAME}-clean
  COMMENT "Cleaning `${PROJECT_NAME}` target:"
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  COMMAND ${CMAKE_COMMAND} -DFILES_="${PROJECT_BINARY_DIR}/CMakeFiles/${PROJECT_NAME}.dir/src/"
                           -P "misc/script/remove_recurse.cmake"
)

add_custom_target(${PROJECT_NAME}-rebuild
  COMMENT "Rebuilding `${PROJECT_NAME}` target:"
  DEPENDS ${PROJECT_NAME}-clean
  COMMAND ${CMAKE_COMMAND} --build "." --target ${PROJECT_NAME}
)

```

> **Output**
>
> ```plaintext
> [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 `cmd` _commands_ 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 ☹.

Comments and improvements are welcomed!

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [May 2, 2024, 9:29pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/18 "2024-05-02T21:29:56Z")

</div>

> [@int\_main](#):
>
> 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.

> [@int\_main](#):
>
> Pity that `add_custom_target` accepts only `cmd` _commands_ and not cmake functions. Is it an interesting idea to add `FUNCTION` feature as for `COMMAND` alternative to CMake?

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.

---

<div class="post-metadata">

### Author: ![denial](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/d/ce73a5/32.png) [@denial](https://discourse.cmake.org/u/denial)
#### Post date: [June 4, 2024, 10:11pm UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/19 "2024-06-04T22:11:11Z")

</div>

My first guess was like this:

```auto
function(add_clean_target target)
    set(clean_target clean.${target})
    add_custom_command(
        OUTPUT ${target}.cleaned
        COMMAND cmake -E rm -f $<TARGET_FILE:${target}>
        COMMAND cmake -E rm -f $<TARGET_OBJECTS:${target}>
        DEPENDS_EXPLICIT_ONLY
        COMMAND_EXPAND_LISTS
    )
    add_custom_target(${clean_target} DEPENDS ${target}.cleaned)
    set_property(TARGET ${clean_target} PROPERTY FOLDER "Utilities")
endfunction()

add_clean_target(my_lib)

```

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.):

```auto
function(add_clean_target target)
    set(clean_target clean.${target})
    set(cleanup_script ${target}.clean.bat)

    set(target_output "$<SHELL_PATH:$<TARGET_FILE:${target}>>")
    set(target_objects "$<JOIN:$<SHELL_PATH:$<TARGET_OBJECTS:${target}>>,\" \">")
    set(delete "del /Q /S")
    set(command "${delete} \"${target_output}\" \"${target_objects}\"")

    add_custom_command(
        TARGET ${target}
        POST_BUILD
        COMMENT "Writing `${target}` cleanup script"
        COMMAND cmd /c > ${cleanup_script} echo ${command}
        DEPENDS_EXPLICIT_ONLY
        COMMAND_EXPAND_LISTS
    )

    set(error "Cleanup script ${cleanup_script} not found. Try to [re]build `${target}` target")
    set(command "echo off & if exist ${cleanup_script} (call ${cleanup_script}) else (echo ${error})")
    add_custom_target(${clean_target}
        COMMENT "Cleaning target `${target}`"
        COMMAND cmd /c ${command}
    )

    set_property(TARGET ${clean_target} PROPERTY FOLDER "Utilities")
endfunction()

```

Comments and improvements are welcomed also! Would be nice to get it right and crossplatform

---

<div class="post-metadata">

### Author: ![leolcao](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/b487fb/32.png) [@leolcao](https://discourse.cmake.org/u/leolcao)
#### Post date: [November 15, 2024, 12:27am UTC](https://discourse.cmake.org/t/ability-to-clean-individual-targets/2980/20 "2024-11-15T00:27:10Z")

</div>

there is an open issue from here: [https://gitlab.kitware.com/cmake/cmake/-/issues/23458](https://gitlab.kitware.com/cmake/cmake/-/issues/23458)  
I agree with that idea, hope cmake can support that way in the near future, just hope~
