# Creating Shared libraries and an executable

**URL:** https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846
**Category:** Usage
**Tags:** os:linux
**Created:** [February 25, 2021, 5:48pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846 "2021-02-25T17:48:39Z")
**Posts on this page:** 12
**Page:** 1

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 25, 2021, 5:48pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/1 "2021-02-25T17:48:39Z")

</div>

I’m a cmake newbie and I’m converting a rather large existing project to cmake so the basic tutorials don’t seem to help that much, so after Google and the help files, here I am…

The overall concept of the build is a small single file executable (essentially just a main()) and a series of shared libraries.

My main struggle now seems to be how to create the target so that it triggers the building of the libraries, but doesn’t explicitly link with them. What I get now is the creation of the .so libraries, however the executable attempts to also link together all of the object files from the libraries. Am I barking up the wrong tree here or should I separate the creation of the libraries into a new/separate cmake file?

More details available obviously, but I first wanted to see if what I am attempting is possible, and that is to (within the same build target, create .so libraries and dynamically link against them to create an executable).

Thanks

---

<div class="post-metadata">

### Author: ![YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/user_avatar/discourse.cmake.org/ymba9g8j9cjp0wloqf5y/32/1244_2.png) [@YMba9g8j9CJp0wLoQf5y](https://discourse.cmake.org/u/YMba9g8j9CJp0wLoQf5y)
#### Post date: [February 25, 2021, 6:00pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/2 "2021-02-25T18:00:27Z")

</div>

> [@Q123](#):
>
> The overall concept of the build is a small single file executable (essentially just a main()) and a series of shared libraries.

Use add\_executable and add\_library.

> [@Q123](#):
>
> My main struggle now seems to be how to create the target so that it triggers the building of the libraries, but doesn’t explicitly link with them

You can use add\_dependencies if you don’t want to link/establish dependency using target\_link\_libraries.

> [@Q123](#):
>
> I’m a cmake newbie and I’m converting a rather large existing project to cmake so the basic tutorials don’t seem to help that much, so after Google and the help files, here I am…

My recommendation is this book: [Professional CMake: A Practical Guide - 16th Edition](https://crascit.com/professional-cmake/)

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 25, 2021, 6:15pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/3 "2021-02-25T18:15:38Z")

</div>

> [@YMba9g8j9CJp0wLoQf5y](#):
>
> add\_dependencies

Ah, and it was as simple as that, thank you. And thanks, I’ll check out that book.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 25, 2021, 9:56pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/4 "2021-02-25T21:56:42Z")

</div>

Ok, I guess I replied a bit prematurely.

Using the add\_dependencies() does allow the separation between the executable and the libraries, so that is good, however the executable still contains the libraries.

I have defined my executable as:

`add_executable( myexec EXCLUDE_FROM_ALL ${PROJECT_SOURCE_DIR}/main.cpp)`

and added a library:

```
add_library(mylibA SHARED)
target_sources(mylibA PUBLIC Path/ToLibA/Source )
set_target_properties(mylibA PROPERTIES LINKER_LANGUAGE CXX)

```

as suggested, I then added a dependency on the library to the exec:

`add_dependencies( myexec mylibA )`

This creates the library mylibA.so however, on it’s own, fails to build the executable myexec and rightly so because we haven’t yet identified that it requires the library. My thought would then to be to add the line:

`target_link_libraries( myexec LINK_PUBLIC mylibA )`

however as I mentioned, this creates a myexec that contains not just the code for main.cpp as hoped, but also the code from the shared library mylibA.

---

<div class="post-metadata">

### Author: ![McMartin](https://discourse.cmake.org/user_avatar/discourse.cmake.org/mcmartin/32/150_2.png) [@McMartin](https://discourse.cmake.org/u/McMartin)
#### Post date: [February 26, 2021, 7:54am UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/5 "2021-02-26T07:54:28Z")

</div>

> [@Q123](#):
>
> My thought would then to be to add the line:
> 
> `target_link_libraries( myexec LINK_PUBLIC mylibA )`

The `LINK_PUBLIC` keyword is deprecated and only kept for compatibility reasons. The preferred keyword is `PUBLIC`.

However, executables usually don’t need a link interface, so it would make more sense to use the `PRIVATE` keyword here.

* * *

> [@Q123](#):
>
> this creates a myexec that contains not just the code for main.cpp as hoped, but also the code from the shared library mylibA.

This would mean that `mylibA` is a static library, not a shared one. Maybe you had `add_library(mylibA)` instead of `add_library(mylibA SHARED)` initially and you already built a static library. You should consider deleting/cleaning the build directory and build again.

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [February 26, 2021, 9:51am UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/6 "2021-02-26T09:51:56Z")

</div>

> [@Q123](#):
>
> `target_sources(mylibA PUBLIC Path/ToLibA/Source )`

Using `PUBLIC` here means “make these sources part of `mylibA` _and also_ make them part of whoever links to `mylibA`”. That is how the sources are getting into your executable. You should probably be using `PRIVATE` here. Actually, I don’t see a reason for you to use `target_sources()` at all: just list the source files directly in the `add_library()` command, and they will be `PRIVATE` by default.

It’s extremely rare to need to use anything other than `PRIVATE` with `target_sources()`. I [answered a similar question](https://discourse.cmake.org/t/ides-and-header-files/2665/2) recently, see that for more info.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 26, 2021, 2:32pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/7 "2021-02-26T14:32:01Z")

</div>

I’ve changed all LINK\_\* to be the updated versions, I should have mentioned off the top as well, that I’m using:

`cmake_minimum_required (VERSION 3.17)`

Since I’m still trying to figure this all out, I by default clear the build directory and start from scratch on every build. The link paths are:

`target_link_libraries( myexec PRIVATE ${CMAKE_BINARY_DIR}/mylibA.so )`

so it’s not pulling in some stale version, although a good suggestion.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 26, 2021, 3:11pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/8 "2021-02-26T15:11:33Z")

</div>

Thanks Petr,

I understand your explanation, however oddly, I tried both options (setting the sources as both PUBLIC and PRIVATE) and I see no difference in the output. In both cases, the library and the executable create the same outputs.

As for using the target\_sources() line, this is where the simple examples don’t really match larger projects. In my case, it’s not just one library, but 8 of them, plus a few 3-rd party .a libs. The libraries themselves vary from having their source in one directory to having them spread out over multiple directories (and not necessarily all of the source files in those directories), each with potential different compile options, , etc, etc.

Perhaps this all stems from the way that I am creating the libs in the first place. I’ve looked for examples on this and again they seem to all offer the simple solution of just listing the source files directly in the add\_library() call.

They way it’s being done now is that in a given directory, a shared library is created as:

`add_library(mylibDirA SHARED <local source files> )`

then it’s added to the mylibA target:

`target_link_libraries( mylibA PRIVATE mylibDirA $<TARGET_OBJECTS:mylibDirA> )`

Why you ask? Well that’s just the way that it was created from the existing build mechanism through the use of some scripts. If there’s a better (correct) way to do this then that may be the source of the problem.

---

<div class="post-metadata">

### Author: ![Angew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/angew/32/229_2.png) [@Angew](https://discourse.cmake.org/u/Angew)
#### Post date: [February 26, 2021, 3:16pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/9 "2021-02-26T15:16:05Z")

</div>

The goalposts keep moving on this one. Can you please reduce your real project into an [SSCCE](http://sscce.org/) that will actually reproduce your problems while being as minimal as possible, and post that? It’s much easier to look for bugs in code when one can _see_ that code.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 26, 2021, 4:06pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/10 "2021-02-26T16:06:15Z")

</div>

Sorry, I was being intentionally vague to try to get the obvious out of the way since what I’m trying to do is a lot more complicated, but the basic premise still stands. I’ll try to reproduce it with a shorter example of the concepts.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 26, 2021, 5:33pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/11 "2021-02-26T17:33:35Z")

</div>

As suspected, when I create a simple example, it works. I’ll start ‘adding’ in some of the concepts that the full project uses and see where it breaks.

---

<div class="post-metadata">

### Author: ![Q123](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/q/eada6e/32.png) [@Q123](https://discourse.cmake.org/u/Q123)
#### Post date: [February 26, 2021, 7:55pm UTC](https://discourse.cmake.org/t/creating-shared-libraries-and-an-executable/2846/12 "2021-02-26T19:55:26Z")

</div>

So my next possible source of an issue is the link order. I was able to get back to where I was using the test example format however it was giving me the same results. So at least I know that the top level format is correct. So I went to look at the linking output of cmake to see what the difference was between it and what I was previously using.

One of the libraries created contains some source code and is also built with some 3rd party deliverables (.a’s), so they are added:

target\_link\_libraries( libA\_lib PRIVATE ${PROJECT\_SOURCE\_DIR}/3rdPatry/lib3rdParty.a )

What I see in the link.txt file however is that the .a’s are added BEFORE the object files. In my executable I also had to add the 3rd party library to it’s target\_link\_libraries() and I couldn’t understand why, but I’m realizing now it’s because the libA\_lib didn’t actually add in the code because there was no reference to it (as the object files came after the archives). To test the theory I manually modified the link.txt file to put the .a’s at the end of the link and voila it ‘works’.

So now the question was how to you specify the link order? Or the larger question is why would cmake not place object file first in the linker?

Short term solution I have is to add the option:

`add_link_options( -Wl,--start-group )`

Not ideal, but it at least gets the library generation correct, or so it seems.

In summary, it looks like the format I was using was correct all along, the issue was that the link order on one of the libraries was incorrect requiring the executable to include all of the 3rd party code to resolve the remaining symbols.
