# How to do "link-time polymorphism" right?

**URL:** https://discourse.cmake.org/t/how-to-do-link-time-polymorphism-right/3381
**Category:** Code
**Created:** [May 21, 2021, 8:38am UTC](https://discourse.cmake.org/t/how-to-do-link-time-polymorphism-right/3381 "2021-05-21T08:38:06Z")
**Posts on this page:** 2
**Page:** 1

<div class="post-metadata">

### Author: ![Adam\_Badura](https://discourse.cmake.org/user_avatar/discourse.cmake.org/adam_badura/32/1058_2.png) [@Adam\_Badura](https://discourse.cmake.org/u/Adam_Badura)
#### Post date: [May 21, 2021, 8:38am UTC](https://discourse.cmake.org/t/how-to-do-link-time-polymorphism-right/3381/1 "2021-05-21T08:38:06Z")

</div>

In our project, we are doing “link-time polymorphism” to provide variants of the product and for testability. The second scenario is of interest here.

We have a library (`.so`). For it, there are two targets: one provides only headers, the other one (depending also on the first one) provides the `.a` for linking. On top of that, there is another implementation, test double, that provides a different `.a` to support stubs and mocks of the library in the testing code.

Perhaps having a proper dependency injection would prevent the need for link-time polymorphism, but for various reasons, it seems out of the picture for now.

Now, the approach is that all “intermediate targets” link (through `target_link_libraries`) only to the “library interface target” and this is enough for _compilation_. While only the “final targets” (typically executables) add the “library target”, either directly or indirectly through some other wrappers etc.

In theory, it should work since all the symbols are present while linking the final executable. And it did work… - so far. However, now while attempting to make a small change in the structure of the targets (part of a larger target is taken out and promoted to a target on its own) we got some linking errors with “undefined reference”.

Looking at the failed command line (as output by CMake itself) I can see the stubbing library is present there. So, I guess the problem might be that it is placed _before_ the other library that is reported as the source of unresolved reference. However, how can I influence this?

Or is it so, that our approach of using “library interface targets” is outright wrong and we should be using always either the real library or its stub? This should perhaps be done by creating a “selector target” which links to either the real thing or the stub, depending on what build are we doing, while all other targets would then only use the selector, being free of (direct) “logic”.

**Level: Hard**

We have another instance of the same problem also with an external library, that we import using `pkg-config`. The extra level of complexity here stems from the fact, that we no longer can easily make this “library interface target” since `PkgConfig::<target>` has it all - both headers and linking.

I have asked about it on StackOverflow ([How to do target\_link\_libraries in CMake without actual linking?](https://stackoverflow.com/questions/60206209/how-to-do-target-link-libraries-in-cmake-without-actual-linking)), however, with no success.

And this is a problem even without our approach of “library interface targets” since even if we would always be using either the library or its stab, making the “stub target” still implies the same difficulties - how no nicely extract from `PkgConfig::<target>` the “interface part”?

---

<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 21, 2021, 11:11am UTC](https://discourse.cmake.org/t/how-to-do-link-time-polymorphism-right/3381/2 "2021-05-21T11:11:44Z")

</div>

I don’t have much feedback on the main part of your question right now other than to say that some genex logic could help here to give target A to executables and target B to everything else:

```auto
$<IF:$<STREQUAL:$<TARGET_PROPERTY:TYPE>:EXECUTABLE>,for-exe,for-others>

```

> [@Adam\_Badura](#):
>
> And this is a problem even without our approach of “library interface targets” since even if we would always be using either the library or its stab, making the “stub target” still implies the same difficulties - how no nicely extract from `PkgConfig::<target>` the “interface part”?

Somewhere I mentioned about a potential `$<COMPILE_ONLY:>` genex. I don’t know what happened to it though ☹ .
