# Run custom command before some project build in Superbuild

**URL:** <https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152>\
**Category:** Code\
**Created:** [September 27, 2021, 2:56pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152 "2021-09-27T14:56:16Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [September 27, 2021, 2:56pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/1 "2021-09-27T14:56:16Z")

</div>

Hi,

The schema of my project is something like:

```auto
MyProject |
          FetchContent_Populate(MyDep) |
                                        ExternalProject_Add(ExternalDep_1)
                                        ExternalProject_Add(ExternalDep_2)
                                        ExternalProject_Add(...)

```

That means that my project `MyProject` fetches other project `MyDep` and that other project uses superbuild to to build all its dependencies via `ExternalProject_Add`.

I need to run some command (probably by using `add_custom_command`) when `MyDep` is ready to be built (all `ExternalProject_Add` are built). I guess this is similar to run the command while `MyDep` buildtime (but when all its deps are already built).

Is there a way to achieve that?

---

<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:** [September 27, 2021, 4:45pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/2 "2021-09-27T16:45:42Z")

</div>

I think using `ExternalProject_add_step` would be the way to do this (with `DEPENDEES build`).

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [September 28, 2021, 12:01am UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/3 "2021-09-28T00:01:33Z")

</div>

Thank you for reply,

I’ve just read the documentation on `ExternalProject_add_step` and it seems that this command only adds the steps for targets that are created via `ExternalProject_Add`.

In my case my project depends on `MyDep` project that uses `add_library()` command to create target and to build its dependencies it uses `ExternalProject_Add()`.

I need to run the command **after** all `ExternalProject_Add()` dependencies of `MyDep` are built but **before** `MyDep` starts building.

I’m sorry if I confused you

EDIT:  
I just understood that probably [add\_custom\_command](https://cmake.org/cmake/help/latest/command/add_custom_command.html#build-events) second use signature may do what I need. Probably I should try that

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [September 28, 2021, 11:50am UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/4 "2021-09-28T11:50:49Z")

</div>

```cmake
add_custom_command(
  TARGET MySubDep PRE_BUILD
  COMMAND 
    python -m editcpp 
    --src-file=src.cxx
    --dest-file=out.cxx
    --oldfile-keep 
    -std=c++17
    \"$<$<BOOL:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>>:-I$<JOIN:$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>, -I>>\"
  VERBATIM)

```

but I get error:

```cmake
No TARGET 'MySubDep' has been created in this directory.

```

`MySubDep` is a dependency of `MyDep` that is created via `add_library`.  
Is there a way to tell the cmake that somewhere in subfolder there is a target `MySubDep` and it should trust me? 🙂

---

<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:** [September 28, 2021, 3:50pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/5 "2021-09-28T15:50:22Z")

</div>

Yeah, I don’t think you can attach additional `{PRE,POST}_BUILD` commands to “remote” targets. You should be able to add your own target that depends on the dependencies and is then depended on by `MySubDep` using `add_dependencies` though.

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [September 30, 2021, 4:02pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/6 "2021-09-30T16:02:09Z")

</div>

Thank you for the hints but it seems that this doesn’t work (`Cannot add target-level dependencies to non-existent target "MySubDep".`)…

```cmake
# Somwhere within external project:
add_library(MySubDep somefile.cxx)
target_link_libraries(MySubDep lib_0 lib_1)

#---------------another CMakeLists.txt-------------------#
# My top level project:
# I add `FakeTarget` that depends on `lib_0` and `lib_1` and 
# at the same time `MySubDep` should depend on `FakeTarget`
add_custom_target(FakeTarget 
  COMMAND 
    editcpp 
    --src-file=src.cxx
    --dest-file=out.cxx
    --oldfile-keep 
    -std=c++17
    \"-I$<JOIN:$<TARGET_PROPERTY:MySubDep ,INCLUDE_DIRECTORIES>, -I>\"
    VERBATIM)
add_dependencies(FakeTarget lib_0 lib_1)
add_dependencies(MySubDep FakeTarget)

```

If I misunderstood you could you please explain a little more?

---

<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:** [October 1, 2021, 11:39am UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/7 "2021-10-01T11:39:41Z")

</div>

I think this looks fine except that why `MySubDep` is not around is odd. Does it pass an `if (TARGET MySubDep)` conditional?

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [October 1, 2021, 12:39pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/8 "2021-10-01T12:39:56Z")

</div>

Thank you for response,

You were right, there is no `if (TARGET MySubDep)` but there is another condition that checks if superbuild is ON then it doesn’t add `add_subdirectory()` with the `MySubDep` target…  
I need to discover how those libs are added in superbuild mode.

I will report back when I have progress

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [October 1, 2021, 8:50pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/9 "2021-10-01T20:50:17Z")

</div>

The system works in the following manner:

1. `MyProject` uses `FetchContent_Populate(MyDep)` ;
2. `MyDep` uses superbuild to build its dependencies as well as **itself** (i.e. uses `ExternalProject_Add(MyDep)` with `-DUSE_SUPERBUILD:BOOL=OFF`);
3. `MyDep` creates `MySubDep` via `add_library(MySubDep mysubdep.cpp)`;
4. `MySubDep` has its dependencies that are added via `target_link_libraries(MySubDep lib1 lib2 ...)`;

My task is to modify source code of `mysubdep.cpp` (I need to change the implementation of some functions there) before `MySubDep` is built. To do that (to parse .cpp files) I use [my tool](https://github.com/tierra-colada/cppguts) that uses `clang` and I need to get all dirs that are linked to `MySubDep` (that is why I use something like `-I$<JOIN:$<TARGET_PROPERTY:MySubDep ,INCLUDE_DIRECTORIES>, -I>`)

I hope now my task is clearer and I’m sorry that it took so long to explain.

For now I think the simplest solution would be modify the `CMakeLists.txt` where `MySubDep` target is created by appending custom command to it:

```cmake
set(cmake_file "~/MyProject/MyDep/MySubDep/CMakeLists.txt")
file(READ ${cmake_file} MySubDepFile)

string(FIND ${MySubDepFile} 
  "EDITED BY ME"
  isMySubDepFileEdited)

if(isMySubDepFileEdited LESS 0)
  # write the command to a variable
  set(MY_COMMAND
  "
  # EDITED BY ME

  add_custom_command(
    TARGET MySubDep PRE_BUILD
    COMMAND 
      editcpp 
      --src-file=mysubdep.cpp
      --dest-file=~/MyProject/MyDep/MySubDep/mysubdep.cpp
      --oldfile-keep 
      -std=c++17
      \"-I$<JOIN:$<TARGET_PROPERTY:MySubDep,INCLUDE_DIRECTORIES>, -I>\"
    VERBATIM)
  "
  )

  # append my command to `CMakeLists.txt` where `MySubDep` is added as a target
  file(APPEND  
    ${cmake_file}
    ${MY_COMMAND}
  )
endif()

```

but I feel that this is not the best way to solve the problem…

---

<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:** [October 2, 2021, 1:14pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/10 "2021-10-02T13:14:50Z")

</div>

`FetchContent` uses `ExternalProject` under the hood. You can use `PATCH_COMMAND` to patch the source.

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [October 2, 2021, 1:58pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/11 "2021-10-02T13:58:03Z")

</div>

I think you gave me all the necessary info I need to know to solve my problem, I appreciate that.  
Now I need some time to understand and to test that.  
Thank you very much!

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [October 6, 2021, 1:25am UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/12 "2021-10-06T01:25:46Z")

</div>

Is there a way to add to variable `${VAR}` without substitution value of a `VAR`?  
For example I need to prepare variable and write it as is to a file:

```cmake
  set(MY_COMMAND
  "
  get_target_property(tgt_deps MySubDep LINK_LIBRARIES)

  add_custom_command(
    TARGET MySubDep PRE_BUILD
    COMMAND 
      editcpp 
      --src-file=mysubdep.cpp
      --dest-file=~/MyProject/MyDep/MySubDep/mysubdep.cpp
      --oldfile-keep 
      -std=c++17
      \"-I$<JOIN:$<TARGET_PROPERTY:MySubDep,INCLUDE_DIRECTORIES>, -I>\"
    DEPENDS \"${tgt_deps}\"
    VERBATIM)
  "
  )

file(APPEND ~/CMakeLists.txt ${MY_COMMAND})

```

I would like to see that `tgt_deps`is written in modified CMakeLists without substitution its value (like `${tgt_deps}`).  
I’ve seen that `configure_file` is able to do something similar with `@ONLY` parameter set, and also `file(CONFIGURE ...)` but that is not an exact solution to what I would do I think.

---

<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:** [October 6, 2021, 12:14pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/13 "2021-10-06T12:14:08Z")

</div>

You can escale the `$`:

```cmake
\${tgt_deps}

```

---

<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:** [October 6, 2021, 9:16pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/14 "2021-10-06T21:16:05Z")

</div>

Also consider using [bracket syntax](https://cmake.org/cmake/help/latest/manual/cmake-language.7.html#id19) instead of double-quotes. Bracket syntax doesn’t require you to escape the contents and does not dereference variables. E.g.

```cmake
set(MY_COMMAND [==[
  get_target_property(tgt_deps MySubDep LINK_LIBRARIES)

  add_custom_command(
    TARGET MySubDep PRE_BUILD
    COMMAND 
      editcpp 
      --src-file=mysubdep.cpp
      --dest-file=~/MyProject/MyDep/MySubDep/mysubdep.cpp
      --oldfile-keep 
      -std=c++17
      "-I$<JOIN:$<TARGET_PROPERTY:MySubDep,INCLUDE_DIRECTORIES>, -I>"
    DEPENDS "${tgt_deps}"
    VERBATIM)
]==])

```

---

<div class="post-metadata">

**Author:** ![kerim](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/k/6f9a4e/32.png) [@kerim](https://discourse.cmake.org/u/kerim)\
**Post date:** [October 6, 2021, 10:28pm UTC](https://discourse.cmake.org/t/run-custom-command-before-some-project-build-in-superbuild/4152/15 "2021-10-06T22:28:50Z")

</div>

Thank you, I didn’t know that
