# Rebuild external project's dependent targets when the external project changes?

**URL:** https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937
**Category:** Code
**Tags:** gen:makefiles
**Created:** [September 29, 2020, 1:03pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937 "2020-09-29T13:03:29Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![dtgriscom](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/d/59ef9b/32.png) [@dtgriscom](https://discourse.cmake.org/u/dtgriscom)
#### Post date: [September 29, 2020, 1:03pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937/1 "2020-09-29T13:03:29Z")

</div>

I’m working on a cross-compilation project with a top-level `CMakeLists.txt` file generating `Makefile`s. Some of the cross-compiled source code is generated by a host-based code generation tool; since that tool needs a different toolchain, the top-level `CMakeLists.txt` uses `ExternalProject_Add()` to invoke the code generator subdirectory’s `CMakeLists.txt`, with `BUILD_ALWAYS` set to `TRUE`. The code generation targets depend on the code generator target, so during the initial build the code generator is built, and then the code is generated, and then the whole shebang is compiled into the final result. (To be clear: there’s no downloading involved; all of the external project code is local.)

If I change the source of the code generator then the code generator executable will be properly rebuilt on the next `make`. Problem: the dependent code generation targets will NOT be rebuilt. There seems to be no way with an `ExternalProject_Add()` target to indicate when/if any dependencies of the target should be rebuilt.

For instance, if my code generator target were configured using `Add_Custom_Command()`, then I’d use its `OUTPUT` keyword to specify the resulting executable file. I’d then create a convenience target using `Add_Custom_Target()` whose `DEPENDS` keyword referenced the `Add_Custom_Command()`'s `OUTPUT` file. I’d then have the code generation targets depend on this convenience target. But, that won’t work for `ExternalProject_Add()`.

Is there a way to configure an `ExternalProject_Add()`-based target so that dependent targets will be automatically rebuilt when the main target’s output changes?

P.S. This is similar to the following post: [Generate dependency on external projects](https://discourse.cmake.org/t/generate-dependency-on-external-projects/139) .However, in my case nothing is being downloaded, and the concern is not the rebuilding of the code generator when its source changes (that works), but the rebuilding of the code generation targets when the code generator changes (that doesn’t).

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 1, 2020, 4:57pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937/3 "2020-10-01T16:57:48Z")

</div>

The artifacts of the external project are not available at the time you’re configuring the main project. You need to tell CMake about them by creating imported targets. For example:

```cmake
ExternalProject_Add(SomeProj ...)

add_library(SomeProjLib STATIC IMPORTED)
set_property(TARGET SomeProjLib PROPERTY IMPORTED_LOCATION ".../libSomeProj.a")
add_dependencies(SomeProjLib SomeProj)

add_executable(main ...)
target_link_libraries(main PRIVATE SomeProjLib)

```

That will give `main` a dependency on the `SomeProj` external target to ensure that the artifact is available before `main` is built.

Of course this requires carefully coordinating the external project’s configuration and the imported target’s `IMPORTED_LOCATION` to know exactly where the file will be, and its name can be per-platform.

Another approach is to use a separate “superbuild” project that doesn’t compile anything directly but instead uses `ExternalProject_Add` for each external dependency and again for your main project. That way your main project can be written to assume its dependencies are already available, and can use normal exporting and importing as documented [here](https://cmake.org/cmake/help/git-master/manual/cmake-packages.7.html) and [here](https://cmake.org/cmake/help/git-master/guide/importing-exporting/index.html). That avoids needing to hand-import anything.

---

<div class="post-metadata">

### Author: ![dtgriscom](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/d/59ef9b/32.png) [@dtgriscom](https://discourse.cmake.org/u/dtgriscom)
#### Post date: [October 1, 2020, 5:14pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937/4 "2020-10-01T17:14:05Z")

</div>

Excellent: your imported target example works. Many thanks.

I ended up hard-coding the location of the resulting generator executable in the top-level `CMakeLists.txt`, partly because the [target export example](https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets#exporting-targets) seemed to require installing the executable somewhere, when I only need it during the build process and don’t want to clutter up my dev system.

Is there a way to export an executable target without actually installing it somewhere?

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [October 2, 2020, 1:02pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937/5 "2020-10-02T13:02:13Z")

</div>

Further down in that [same page](https://gitlab.kitware.com/cmake/community/-/wikis/doc/tutorials/Exporting-and-Importing-Targets#exporting-from-a-build-tree) is an example of exporting from a build tree.

Or, you can use the same hand-imported approach as above, but for an executable:

```auto
add_executable(SomeProjExe IMPORTED)
set_property(TARGET SomeProjExe PROPERTY IMPORTED_LOCATION ".../SomeProj/AnExe")
add_dependencies(SomeProjExe SomeProj)

```

---

<div class="post-metadata">

### Author: ![dtgriscom](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/d/59ef9b/32.png) [@dtgriscom](https://discourse.cmake.org/u/dtgriscom)
#### Post date: [October 2, 2020, 5:51pm UTC](https://discourse.cmake.org/t/rebuild-external-projects-dependent-targets-when-the-external-project-changes/1937/6 "2020-10-02T17:51:58Z")

</div>

Interesting, but unfortunately the exported `*.cmake` file won’t exist until the code generator’s `CMakeLists.txt` has generated its output, which will be after the top level `CMakeLists.txt` has generated its own `Makefile`s. So, if I hand-trigger the building of the code generator then the main build will work, and will work every time after that, but I can’t do it as a single step from a clean build.

I tried adding a `add_subdirectory(codegen)` line higher up in the top `CMakeLists.txt`, hoping that that would generate the exported `*.cmake` file, but it still threw an error that the `*.cmake` wasn’t there. I’m guessing that it never got to the generation phase.

Eh; it’s far better than it used to be, and thanks for the help.

Dan
