# Multiple shared libs, alternative implementations of common interface, \*minimal\* cmake/c++ example?

**URL:** https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161
**Category:** Code
**Created:** [September 10, 2025, 7:35am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161 "2025-09-10T07:35:56Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![dunc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dunc/32/5805_2.png) [@dunc](https://discourse.cmake.org/u/dunc)
#### Post date: [September 10, 2025, 7:35am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/1 "2025-09-10T07:35:56Z")

</div>

Hi all,

new user here, my name is Jörg, but I usually go as “dunc” online… this is my first post here, and it’s really more of a very generic/basic cmake tutorial question, so you gents might consider it “too basic”. That’s all fine, but I’m struggling to find a good example, so I thought I ask as close to the source as possible.

Upfront: I am absolutely fine with answers like “RTFM!” or “plenty of examples available, just check them out”… however, I am unable to find the correct stuff online, so in case your answers sway that way, I would appreciate at least some pointers, if possible.

Here’s what I’d like to achieve with cmake (using C/C++):

a) have a very basic common INTERFACE header file, defining API functionality to be exported by a shared library

b) have a very basic SHARED library implementation which implements above API (this shared lib might be replaced later on by a similar shared lib that implements tha same API)

c) have a consumer APPLICATION that uses the shared library (and in case s/o replaces shared lib implementation 1 with implementation 2 later on, it is transparent to the consumer app)

So, as you can tell, extremely basic stuff. And yes, I know how to code and implement the C/C++ side of things.

My questions are obviously regarding “how to properly create a cmake config for this, which takes care of all the import export handling, as well as is universal enough to work for both DLLs on Windows and so on Linux”?

I know about Wiki examples like BuildWindowsDLL, which is targeted at cmake 2.8.something. But even here, there never is a complete example roundtrip availabe which combines everything, instead the reader is forced (well, at least _I_ am) to be able to work with snippets and deduce the actual correct combination of cmake options. Given the fact that cmake offers SO MUCH options for special cases, I fail to specifiy what the _minimum_ working base config for such a task would be.

Like “the interface library should be configured like this, we will use a minimal interface with only one exposed method as an example” … “the shared lib should be configured like this, we implement only the single exposed method from the interface” … “this is what you need to add as macros to the code, this is what cmake handles for you” … “this is where you need to handle Windows DLL and Unix SO seperately, this is where cmake handles it for you in a unified way” … “this is how to configre the app via cmake to consume the shared library, and this is the corresponding app code that YOU need to take care of, while THESE parts will be handled by cmake”.

I hope you understand what I’m asking for, and I also hope this is not considered too trivial or too basic for _this_ forum. If it is, no hard feelings, I will try to look around elsewhere.

Thanks upfront and kind regards,  
dunc

---

<div class="post-metadata">

### Author: ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)
#### Post date: [September 10, 2025, 9:17am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/2 "2025-09-10T09:17:07Z")

</div>

Not sure that I understood this part:

> in case s/o replaces shared lib implementation 1 with implementation 2 later on, it is transparent to the consumer app

But let’s start with at least something, and then it will probably get clearer. So what I got from your description is that you’d like to have two shared libraries with the same interface (_but obviously with different implementations_). And then you’d like to be able to just replace one variant with another without rebuilding the consumer application (_hence the libraries being shared_)?

Based on that understanding, I’ve made the following [example project](https://github.com/retifrav/MREs/tree/56e6232f7bc63963812cf6e36087c4b95fbf3316/discourse-cmake-org/15161). The `README.md` contains detailed instructions, but in short, first you build variant #1 of the dependency, then build and run the application against it, and then you build variant #2 of the dependency and run the application against this one (_no need to rebuild the application, obviously_).

The [interface header file](https://github.com/retifrav/MREs/blob/56e6232f7bc63963812cf6e36087c4b95fbf3316/discourse-cmake-org/15161/dpndnc/include/some/some.h) is naturally the same for both variants of the dependency. Generating the export config is [quite involved](https://github.com/retifrav/MREs/blob/56e6232f7bc63963812cf6e36087c4b95fbf3316/discourse-cmake-org/15161/dpndnc/cmake/Installing.cmake), but probably can be simplified.

Is that what you wanted to achieve?

---

<div class="post-metadata">

### Author: ![dunc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dunc/32/5805_2.png) [@dunc](https://discourse.cmake.org/u/dunc)
#### Post date: [September 10, 2025, 10:08am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/3 "2025-09-10T10:08:46Z")

</div>

Thank you,

and yes, that’s kind of what I wanted to achieve indeed. However, maybe my actual concerns were not pointed out correctly. I understand the results that the cmake configuration needs to produce. And there are _multiple_ ways to achive the desired result.

What I am struggling with is “what is currently considered the best practice, now that we are in the cmake 4.x age”. For example:

- Should I really opt for adding all the required dllimport/export stuff myself? Or is it easier/cleaner/preferred to e.g use GENERATE\_EXPORT\_HEADER functionality? If so, how would a minimal exampe for the _preferred_ way look like?

- Should I move the common interface header to its own cmake INTERFACE library, and have the implementation shared libraries reference/consume that INTERFACE library? Or is this not best practise to decouple things in such a way from a cmake POV?

Overall: with “modern” cmake 4.x where can cmake _help_ me or _ease the pain_ of having to take care of things manualy, and how to keep the config “clean and readable” at the same time.

So, that was basically what I meant by _minimal example_. It was not about the desired outcome per se, but about the “proper” or “most convenient” or “most structured cmake” way to achieve it.

Sorry that I did not made myself clear enough.

As for your question: the idea is to have a public interface of _something_ that is provided to some external developers in order they can implement their own desired version of _something_ and all they need to do is place _their_ DLL in the correct spot (using the correct name) to “enable” their implementation.

Of course, _their_ impl will not be part of the cmake config at all. But for our impl, we simply provide different example, hence we have two (or more) shared libs that will be “candidates” for usage at runtime. They will not link at the same time, but the .lib part of those shared libraries that is required for linking needs to be identical, so that in the end, the consumer app is built agnostic to the implementation.

Anyway, that’s probably not even necessary for the cmake config questions.

Thanks,’  
dunc

---

<div class="post-metadata">

### Author: ![retif](https://discourse.cmake.org/user_avatar/discourse.cmake.org/retif/32/1776_2.png) [@retif](https://discourse.cmake.org/u/retif)
#### Post date: [September 10, 2025, 10:16am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/4 "2025-09-10T10:16:18Z")

</div>

Okay, I got confused by your way too humble introduction 🙂  
It seems that you are quite above the entry level, for which I was targeting my example.  
Then it’s better to wait for a response from more experienced CMake users/maintainers, as I am still a sort of beginner myself.

---

<div class="post-metadata">

### Author: ![dunc](https://discourse.cmake.org/user_avatar/discourse.cmake.org/dunc/32/5805_2.png) [@dunc](https://discourse.cmake.org/u/dunc)
#### Post date: [September 10, 2025, 10:24am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/5 "2025-09-10T10:24:55Z")

</div>

Thank you for your kind words 😊

I try not to presume anything about my knowlege when asking questions, because I _know_ it’s mostly dangerous half-knowledge. In this particular case, I guess I just failed to describe my targets properly, so thank you for helping me pointing them out again more clearly.

---

<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: [February 20, 2026, 3:10am UTC](https://discourse.cmake.org/t/multiple-shared-libs-alternative-implementations-of-common-interface-minimal-cmake-c-example/15161/6 "2026-02-20T03:10:11Z")

</div>

This question and its discussion may be of use:

> [@Interfaces, implementations, and unresolved symbols](https://discourse.cmake.org/t/interfaces-implementations-and-unresolved-symbols/5283):
>
> Hi, how should we model the following situation in CMake? There is an interface specification (e.g. set of C language header files): H There are two (static) libraries L1 and L2, each of them implementing this interface H There is a (static) library U which uses the H interface but does not care whether L1 or L2 is used to implement that interface There is another (static) library M which uses U Finally, there are two executables E1 and E2 which both use M and additionally L1 or L2, respec…
