# BUILD\_SHARED\_LIBS

**URL:** <https://discourse.cmake.org/t/build-shared-libs/4200>\
**Category:** Code\
**Created:** [October 4, 2021, 8:50am UTC](https://discourse.cmake.org/t/build-shared-libs/4200 "2021-10-04T08:50:27Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Leon0402](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/ccd318/32.png) [@Leon0402](https://discourse.cmake.org/u/Leon0402)\
**Post date:** [October 4, 2021, 8:50am UTC](https://discourse.cmake.org/t/build-shared-libs/4200/1 "2021-10-04T08:50:27Z")

</div>

As far as I know it’s best practice to not specify SHARED or STATIC for a library, but rely on BUILD\_SHARED\_LIBS instead.

I have to questions regarding this.

1. Should one specify BUILD\_SHARED\_LIBS as an `option`? Up to know I never did. But some Libraries do this and when using FetchContent BUILD\_SHARED\_LIBS will be set to that default value as it is by default empty → This lead to nasty bugs as some libs where build static, then one lib had option(BUILD\_SHARED\_LIBS ON) and set it therefore to On. All a second run then all Libraries where build shared.  
 → Is it wrong from the libraries to declare the option?  
 → Should I declare in my project the option, so BUILD\_SHARED\_LIB always has a value? → It will then not be overwritten, right?

2. Often Libraries delcare `my-library` and `my-library-shared`, so the just have two targets for both static and dynamic. This is often done so they can pass set some different values depending on whether it’s shared or not. But I think it’s also done to make packaging and building from source easier.  
 → Is this bad practice? → It makes my life harder to keep track which libraries use BUILD\_SHARED\_LIBS and which have two targets  
 → What are arguments against it? How can be argued against the “pro” arguments → I believe the different logic could just be done with `if(BUILD_SHARED_LIBS)`, so that’s no argument. What about the “ease of use” argument?

Thanks,  
Leon

---

<div class="post-metadata">

**Author:** ![alex](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alex/32/125_2.png) [@alex](https://discourse.cmake.org/u/alex)\
**Post date:** [October 4, 2021, 2:16pm UTC](https://discourse.cmake.org/t/build-shared-libs/4200/2 "2021-10-04T14:16:40Z")

</div>

It’s fine to declare it as an option if you want to change the default. As long as the minimum required CMake version is 3.13, a parent project can override it with a normal variable.

There is always a danger from FetchContent / add\_subdirectory that the child project will set a cache variable that affects global state. It is always a requirement to audit the code before including it, so you know what it does.

I think having two separate targets for static and shared is an absolutely terrible idea and I wish people would stop doing it. So much do I feel this way, I wrote a blog post about it:

> **[Building a Dual Shared and Static Library with CMake](https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html)**
>
> Personal website and blog of Alex Reinking.

---

<div class="post-metadata">

**Author:** ![Leon0402](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/l/ccd318/32.png) [@Leon0402](https://discourse.cmake.org/u/Leon0402)\
**Post date:** [October 6, 2021, 1:04pm UTC](https://discourse.cmake.org/t/build-shared-libs/4200/3 "2021-10-06T13:04:22Z")

</div>

Thanks for your answer! Especially the detailed blog post, which I will use in the future to convience library authors 😃

---

<div class="post-metadata">

**Author:** ![hwhsu1231](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hwhsu1231/32/5358_2.png) [@hwhsu1231](https://discourse.cmake.org/u/hwhsu1231)\
**Post date:** [August 17, 2022, 9:09am UTC](https://discourse.cmake.org/t/build-shared-libs/4200/4 "2022-08-17T09:09:34Z")

</div>

@alex Execuse me. I have some questions to ask after reading your **IMPRESSIVE** [blog article](https://alexreinking.com/blog/building-a-dual-shared-and-static-library-with-cmake.html).

In the article, you said that it is better to use `find_package()`'s **COMPONENTS** mechanism to specify whether to use `shared` or `static` version of a library. Am I correct?

```cmake
find_package(SomeLib REQUIRED shared) # or `static`

```

Then, what about the following libraries: Qt, Poco,…etc? Since those well-developed libraries already use **COMPONENTS** mechanism to provide their **Component Imported Targets**. Take Qt for example:

```cmake
find_package(Qt6 CONFIG REQUIRED
  Core Widget Gui Network)

target_link_libraries(myExe 
  PRIVATE
    Qt6::Core
    Qt6::Widget
    Qt6::Gui
    Qt6::Network)

```

What about this kind of situation? Do you mean that it is recommended for Qt to provide additional two **Component Imported Targets** , `shared` and `static`. For example:

- If I want to use `static` version:

- If I want to use `shared` version:

Like this?

---

<div class="post-metadata">

**Author:** ![hwhsu1231](https://discourse.cmake.org/user_avatar/discourse.cmake.org/hwhsu1231/32/5358_2.png) [@hwhsu1231](https://discourse.cmake.org/u/hwhsu1231)\
**Post date:** [August 17, 2022, 9:27am UTC](https://discourse.cmake.org/t/build-shared-libs/4200/5 "2022-08-17T09:27:19Z")

</div>

If the key point is to **“leave the decision to `find_package()`”**, how about request CMake to add some new arguments for `find_package()` like: **STATIC** and **SHARED**? (Just like [`add_library()`](https://cmake.org/cmake/help/latest/command/add_library.html#normal-libraries) did.)
