# Selection of targets from a superbuild's sub-projects

**URL:** https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243
**Category:** Usage
**Tags:** tool:cmake
**Created:** [March 1, 2024, 11:03am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243 "2024-03-01T11:03:13Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 1, 2024, 11:03am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/1 "2024-03-01T11:03:13Z")

</div>

Hi,

TL;DR; Is there a way of selecting specific targets (at _build_ time) from the sub-projects that are built as part of a superbuild?

Consider the simple scenario where there is a superbuild that builds two sub-projects. The reason that those two sub-projects exist is because they are built very differently (e.g. different toolchains).

Each sub-project produces two executables, so let’s call them:  
ProjectA: A\_exe1, A\_exe2  
ProjectB: B\_exe1, B\_exe2

When we run cmake to configure the top-level superbuild, cmake gives us a superbuild configuration that has the two sub-project targets (along with the usual support targets). E.g. running in the “build” directory:  
`cmake --build . --target help`  
would list “ProjectA” and “ProjectB” (along with “clean”, etc.)

If we then build those sub-project targets they will (by default) build the “all” target of the sub-project. (E.g. `cmake --build . --target ProjectA`)

However, we may want to build just a selection of the targets within a sub-project (e.g. some configuration options may be invalid for some of their targets, or we simply don’t want to waste time building them).

We could pass flags “down” to the sub-projects’ during the initial superbuild configuration to “switch stuff on/off”; however, that has drawbacks; e.g.

- It requires a re-run of the cmake configure, but we do not need reconfiguration; only target selection.
- It’s invasive on the cmake files of the sub-projects. If we were building these sub-projects stand-alone then we’d just build the specific targets (\*).
- It’s not scalable; we may want a matrix of target combinations from each sub-project (suppose each sub-project can produce 100 targets).

It seems we’d like to do something like:  
`cmake --build . --target ProjectA:A_exe2 --target ProjectB:B_exe1`

I did experiment with first running the cmake configure for the superbuild, and then trying to build the sub-projects from their generated sub-directories. However, the CMakeCache, etc, are not generated for the sub-projects - these are only created at build time, by which time the target is already “all”. E.g. following `cmake ../source_root` the _ProjectA_ and _ProjectB_ sub-dirs are empty. Perhaps there is a way of forcing the sub-project configuration without the build?

The sub-projects are first-party components, so the source is all there; i.e. it does not appear that the _FetchContent_ approach used for 3PP applies here (because AFAICT that copies the whole source sub-tree).

I’ve had a good search for anything superbuild related but haven’t found anything that appears to fit - apologies if this is made obvious somewhere.

(\*) Perhaps the superbuild pattern isn’t suited, and this should just be scripted.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 1, 2024, 9:28pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/2 "2024-03-01T21:28:54Z")

</div>

Sometimes it is good to know the tools below:

```bash
project/build> ninja help
# ...
intro: phony
libCatch2.a: phony
libCatch2Main.a: phony
libfmt.a: phony
libftxui-component.a: phony
libftxui-dom.a: phony
libftxui-screen.a: phony
libsample_library.a: phony
libspdlog.a: phony
sample_library: phony
screen: phony
spdlog: phony
tests: phony
build.ninja: RERUN_CMAKE
clean: CLEAN
help: HELP
bash-5.2$ ninja spdlog
[10/10] Linking CXX static library _deps/spdlog-build/libspdlog.a
bash-5.2$ ninja fmt    
ninja: no work to do.
bash-5.2$ ninja clean
[1/1] Cleaning all built files...
Cleaning... 10 files.
bash-5.2$ ninja fmt 
[3/3] Linking CXX static library _deps/fmt-build/libfmt.a
bash-5.2$ ninja fmt spdlog
[7/7] Linking CXX static library _deps/spdlog-build/libspdlog.a
bash-5.2$ ninja clean
[1/1] Cleaning all built files...
Cleaning... 10 files.
bash-5.2$ ninja fmt spdlog
[10/10] Linking CXX static library _deps/spdlog-build/libspdlog.a
bash-5.2$ ninja clean
[1/1] Cleaning all built files...
Cleaning... 10 files.
bash-5.2$ ninja libCatch2
libCatch2.a libCatch2Main.a  
bash-5.2$ ninja libCatch2.a
[104/104] Linking CXX static library _deps/catch2-build/src/libCatch2.a
bash-5.2$ ninja intro 
[88/82] Linking CXX static library _deps/ftxui-build/libftxui-component.a
# ...

```

If you want to try it yourself see [cmake\_template](https://github.com/ClausKlein/cmake_template/tree/feature/add-workflow-presets)

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 1, 2024, 10:55pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/3 "2024-03-01T22:55:58Z")

</div>

I’m struggling to see any context in that response that relates to the original post.  
This query is about the cmake superbuild pattern; I.e. a top-level project that adds sub-projects using _ExternalProject\_Add_.  
The generator used for the build is irrelevant to the question.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 2, 2024, 3:45am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/4 "2024-03-02T03:45:18Z")

</div>

This project is a sample of a super build project using `CPM.cmake` and `FetchContents`:

```bash
bash-5.2$ rm -rf out/build/
bash-5.2$ cmake --preset .
CMake Error: No such preset in /Users/clausklein/Workspace/cpp/cmake_template: "."
Available configure presets:

  "debug" - Debug
  "release" - Release
  "gcc-debug" - gcc Debug
  "gcc-release" - gcc Release
  "clang-debug" - clang Debug
  "clang-release" - clang Release

bash-5.2$ cmake --preset clang-release | grep -w CPM
-- CPM: Adding package fmt@9.1.0 (9.1.0 at /Users/clausklein/.cache/CPM/fmt/5c4bc51f3df5bb907a0028facff05ba4978aa6e5)
-- CPM: Adding package spdlog@1.11.0 (v1.11.0 at /Users/clausklein/.cache/CPM/spdlog/3f1a872999ca96ce50003a293cd3768892029aef)
-- CPM: Adding package Catch2@3.3.2 (v3.3.2 at /Users/clausklein/.cache/CPM/catch2/8336fa0dd617945aa607363db497172b01dc4bf1)
CMake Deprecation Warning at /Users/clausklein/.cache/CPM/cli11/9e6fd3fcb946a91f4a10e874dc9d09753d96ed7f/CMakeLists.txt:1 
-- CPM: Adding package CLI11@2.3.2 (v2.3.2 at /Users/clausklein/.cache/CPM/cli11/9e6fd3fcb946a91f4a10e874dc9d09753d96ed7f)
-- CPM: Adding package FTXUI@0 (dd6a5d371fd7a3e2937bb579955003c54b727233 at /Users/clausklein/.cache/CPM/ftxui/f0c2f804c00f907a3f5265baa402e97baa4f2ab5)
-- CPM: Adding package tools@ (update_build_system at /Users/clausklein/.cache/CPM/tools/8c8c55a914858ebfc250a90e65f4f4a988a4e20e)
CMake Warning (dev) at CMakeLists.txt:72 (message):
  Building Tests. Be sure to check out test/constexpr_tests.cpp for
  constexpr testing
This warning is for project developers. Use -Wno-dev to suppress it.

bash-5.2$ cmake --build --preset clang-release --target help | tail 
libsample_library.a: phony
libspdlog.a: phony
relaxed_constexpr_tests: phony
sample_library: phony
screen: phony
spdlog: phony
tests: phony
build.ninja: RERUN_CMAKE
clean: CLEAN
help: HELP
bash-5.2$ 

```

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 2, 2024, 6:41pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/5 "2024-03-02T18:41:52Z")

</div>

As mentioned, the _FetchContent_ approach works well for third-party packages (3PP), because they change rarely. But for nested **first-party** sub-projects we do not require (nor want) any source code fetching (nor copying).

If those first-party sub-projects are added using _ExternalProject\_Add_ then the sub-projects’ targets are not visible in the `cmake --build . --target help` list (nor `make help` nor `ninja help` nor whatever generator…).  
The top-level project cannot “see” the sub-projects’ targets.

As an illustration, here’s a simple mock up that provides the scenario as described in the original post.  
[Superbuild.tar.gz](https://discourse.cmake.org/uploads/short-url/8wGgP5qeKM0kuOI3lPvbyZb8TaX.gz) (10 KB)

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 2, 2024, 8:37pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/6 "2024-03-02T20:37:08Z")

</div>

I can`t see any good reason to use `external\_project`, except if it is a non CMake build project? You may use `fetch\_content`or`CMP.cmake` and point to a given source dir to build without cloning the subproject.

### i.e.: `FETCHCONTENT_SOURCE_DIR_<uppercaseName>`¶

If this is set, no download or update steps are performed for the specified content and the `<lowercaseName>_SOURCE_DIR` variable returned to the caller is pointed at this location. This gives developers a way to have a separate checkout of the content that they can modify freely without interference from the build. The build simply uses that existing source, but it still defines `<lowercaseName>_BINARY_DIR` to point inside its own build area. Developers are strongly encouraged to use this mechanism rather than editing the sources populated in the default location, as changes to sources in the default location can be lost when content population details are changed by the project.

And [CPM.cmake local-package-override](https://github.com/cpm-cmake/CPM.cmake/tree/v0.38.7?tab=readme-ov-file#local-package-override)

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 2, 2024, 10:43pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/7 "2024-03-02T22:43:45Z")

</div>

Use ninja at build dir and it works:

```bash
Claus-iMac:build clausklein$ ninja -C A help
ninja: Entering directory 'A'
[1/1] All primary targets available:
edit_cache: phony
rebuild_cache: phony
all: phony
build.ninja: RERUN_CMAKE
clean: CLEAN
help: HELP
Claus-iMac:build clausklein$ ninja -C B help
ninja: Entering directory 'B'
[1/1] All primary targets available:
edit_cache: phony
rebuild_cache: phony
all: phony
build.ninja: RERUN_CMAKE
clean: CLEAN
help: HELP
Claus-iMac:build clausklein$ 

```

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 3, 2024, 9:35am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/8 "2024-03-03T09:35:16Z")

</div>

The _ExternalProject\_Add_ directive is clearly intended to support cmake projects, after all, that’s what it looks for by default.  
However, it’s looking like trying to manage this pattern doesn’t fit, and it’s simply easier to use a script to build the sub-projects independently.

The _FetchContent_ approach appears to always (ultimately) use ‘add\_subdirectory’. This isn’t suitable because the sub-projects (in this case) have to be treated as very independent builds, so they do not want pollution of settings from each other.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 3, 2024, 12:19pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/9 "2024-03-03T12:19:15Z")

</div>

> [@Chardrazle](#):
>
> However, it’s looking like trying to manage this pattern doesn’t fit, and it’s simply easier to use a script to build the sub-projects independently.

Yes, I agree.

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 3, 2024, 7:37pm UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/10 "2024-03-03T19:37:41Z")

</div>

I figured out a way of achieving what I need. It’s all there in the docs for `ExternalProject`, under the _Explicit Step Management_.  
The problem I had essentially boils down to the top-level project not configuring the sub-projects. This means the desired targets of the sub-projects cannot be built because the cmake configuration is not available for them.  
This is where the _step targets_ come in. The configurations for those sub-projects can be forced to run by “exposing” the _configure_ step. This is simply just a case of adding `STEP_TARGETS configure` to the `ExternalProject_Add` options.  
This is then used to force configuration of the sub-project. It means several calls to cmake are required, but it avoids specific shell/platform/generator directives.

So a sequence would be:

```auto
cmake ../Superbuild # Configure top-level project
cmake --build . --target A-configure # Force configuration of A by executing the "step" target exposed for sub-project A
cmake --build A --target A_exe2 # Now build a specific target of sub-project A

```

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 10, 2024, 12:11am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/11 "2024-03-10T00:11:11Z")

</div>

> [@Chardrazle](#):
>
> Perhaps there is a way of forcing the sub-project configuration without the build?

Looks like this can be achieved by an explicit _execute\_process_ following the _ExternalProject\_Add_ (removing the need for the STEP target); e.g.:

```auto
execute_process(COMMAND
    ${CMAKE_COMMAND} -S ${CMAKE_SOURCE_DIR}/A -B ${CMAKE_BINARY_DIR}/A
)

```

I’m surprised there isn’t an option on _ExternalProject\_Add_ for forcing just that. Unless I missed it?  
( @craig.scott any opinion? 😉)

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [March 10, 2024, 6:12am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/12 "2024-03-10T06:12:51Z")

</div>

> [@Chardrazle](#):
>
> So a sequence would be:
> 
> ```auto
> cmake ../Superbuild # Configure top-level project
> cmake --build . --target A-configure # Force configuration of A by executing the "step" target exposed for sub-project A
> cmake --build A --target A_exe2 # Now build a specific target of sub-project A
> 
> ```

**IMHO** : it would be much clearer to write a script, on even better, a `GNUmakefile`, or not?

---

<div class="post-metadata">

### Author: ![Chardrazle](https://discourse.cmake.org/user_avatar/discourse.cmake.org/chardrazle/32/4362_2.png) [@Chardrazle](https://discourse.cmake.org/u/Chardrazle)
#### Post date: [March 10, 2024, 10:49am UTC](https://discourse.cmake.org/t/selection-of-targets-from-a-superbuilds-sub-projects/10243/13 "2024-03-10T10:49:28Z")

</div>

Sure, as soon as there are multiple commands to type in then a script file might become beneficial.  
The aim was that the script could consist purely of calls to _cmake_. IOW: it serves as not having to remember the _cmake_ command lines, rather than being intrinsically involved in the build logic.

Adding the _execute\_process_ entry, the second call to _cmake_ in the above sequence is no longer required; i.e. only two calls to _cmake_ are required in order to build a _specific target_ of a sub-project.
