# Installation behavior of shared versus static libraries

**URL:** <https://discourse.cmake.org/t/installation-behavior-of-shared-versus-static-libraries/8236>\
**Category:** Code\
**Tags:** os:macos\
**Created:** [May 30, 2023, 6:44pm UTC](https://discourse.cmake.org/t/installation-behavior-of-shared-versus-static-libraries/8236 "2023-05-30T18:44:00Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![neuroevolutus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/neuroevolutus/32/3492_2.png) [@neuroevolutus](https://discourse.cmake.org/u/neuroevolutus)\
**Post date:** [May 30, 2023, 6:44pm UTC](https://discourse.cmake.org/t/installation-behavior-of-shared-versus-static-libraries/8236/1 "2023-05-30T18:44:00Z")

</div>

> **Context**
>
> I was going through [Step 5](https://cmake.org/cmake/help/latest/guide/tutorial/Installing%20and%20Testing.html#step-5-installing-and-testing) of the [CMake tutorial](https://cmake.org/cmake/help/latest/guide/tutorial/index.html), and after completing TODO items 1 through 4 to understand the installation process I noticed what I thought was some strange behavior in the generated Make buildsystem. Specifically, after running the following commands:
> 
> ```bash
> cmake ../Step5
> cmake --build .
> 
> ```
> 
> from my `Step5_build` folder, on the first run of `cmake --install . --prefix /my/install/directory` the resulting output was the following:
> 
> ```bash
> -- Install configuration: ""
> -- Installing: /my/install/directory/lib/libMathFunctions.a
> -- Installing: /my/install/directory/include/MathFunctions.h
> -- Installing: /my/install/directory/bin/Tutorial
> -- Installing: /my/install/directory/include/TutorialConfig.h
> 
> ```
> 
> On the second run of `cmake --install . --prefix /my/install/directory`, the output was the following:
> 
> ```bash
> -- Install configuration: ""
> -- Installing: /my/install/directory/lib/libMathFunctions.a
> -- Up-to-date: /my/install/directory/include/MathFunctions.h
> -- Up-to-date: /my/install/directory/bin/Tutorial
> -- Up-to-date: /my/install/directory/include/TutorialConfig.h
> 
> ```
> 
> However, when I decided to change the following line from `Step5/MathFunctions/CMakeLists.txt`:
> 
> ```bash
> add_library(MathFunctions mysqrt.cxx)
> 
> ```
> 
> to this:
> 
> ```bash
> add_library(MathFunctions SHARED mysqrt.cxx)
> 
> ```
> 
> after regenerating the buildsystem and re-building the targets, I got the following output on the next run of `cmake --install . --prefix /my/install/directory`:
> 
> ```bash
> -- Install configuration: ""
> -- Installing: /my/install/directory/lib/libMathFunctions.dylib
> -- Up-to-date: /my/install/directory/include/MathFunctions.h
> -- Installing: /my/install/directory/bin/Tutorial
> -- Up-to-date: /my/install/directory/include/TutorialConfig.h
> 
> ```
> 
> and this output on the subsequent run of `cmake --install . --prefix /my/install/directory`:
> 
> ```bash
> -- Install configuration: ""
> -- Up-to-date: /my/install/directory/lib/libMathFunctions.dylib
> -- Up-to-date: /my/install/directory/include/MathFunctions.h
> -- Installing: /my/install/directory/bin/Tutorial
> -- Up-to-date: /my/install/directory/include/TutorialConfig.h
> 
> ```

## Question

I am wondering why making a shared library would cause it to install once and show as up-to-date on subsequent invocations of `cmake --install` whereas using the default library type (which is ostensibly `STATIC` on my system) would cause it to have to be installed regardless of whether `cmake --install` had already been invoked.

Additionally, given the details from the context above, I would like to know why turning my library into a shared library would cause a dependent target executable to repeatedly install on each invocation of `cmake --install` whereas using a static library would cause the dependent executable to install only once.

I am very new to CMake and building C/C++ projects in general, so I would greatly appreciate any clarifications that would help me clear my doubts.

> **My Environment**
>
> CMake: 3.26.4  
> OS: macOS Ventura 13.4

---

<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 31, 2023, 7:14pm UTC](https://discourse.cmake.org/t/installation-behavior-of-shared-versus-static-libraries/8236/2 "2023-05-31T19:14:35Z")

</div>

> [@neuroevolutus](#):
>
> I am wondering why making a shared library would cause it to install once and show as up-to-date on subsequent invocations of `cmake --install` whereas using the default library type (which is ostensibly `STATIC` on my system) would cause it to have to be installed regardless of whether `cmake --install` had already been invoked.

The default library type is controlled by `BUILD_SHARED_LIBS` (usually a cache variable). Anyways, I would check the `cmake_install.cmake` code for each; there may be some difference here?

> [@neuroevolutus](#):
>
> Additionally, given the details from the context above, I would like to know why turning my library into a shared library would cause a dependent target executable to repeatedly install on each invocation of `cmake --install` whereas using a static library would cause the dependent executable to install only once.

On macOS, there is some binary patching to fixup rpath entries between the build and install tree. This may tinker with byte-exact files and cause a “new” install to happen.

---

<div class="post-metadata">

**Author:** ![neuroevolutus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/neuroevolutus/32/3492_2.png) [@neuroevolutus](https://discourse.cmake.org/u/neuroevolutus)\
**Post date:** [June 1, 2023, 1:29am UTC](https://discourse.cmake.org/t/installation-behavior-of-shared-versus-static-libraries/8236/3 "2023-06-01T01:29:08Z")

</div>

Hi Ben, thanks so much for taking the time to look into this. Following your suggestion, I decided to create two separate copies of the tutorial to try out both the static and dynamic library versions, and, to your point earlier, there were indeed differences between the two versions of the `Step5_build/cmake_install.cmake` file as well as between the two versions of the `Step5_build/MathFunctions/cmake_install.cmake` file!

In the former file, after the binary `Tutorial` is installed, within an `IF()` condition that checks for the existence of the binary in the install tree and ensures that it is not a symlink, there is an `execute_process` that invokes the macOS `install_name_tool` binary with the `-delete_rpath` option to remove the build tree version of the `Step5_build/MathFunctions` directory path from rpath of the executable in the install tree.

In the `Step5_build/MathFunctions/cmake_install.cmake` file, in the static library version, after the install of the library is performed, within a check to ensure that the library is present in the install tree and is not a symlink, there is an `execute_process` that invokes the macOS `ranlib` binary on the installed library. However, in the corresponding code for the dynamic library, there is an additional check for the presence of the `CMAKE_INSTALL_DO_STRIP` variable, and only if said variable is true will the CMake code run `execute_process` to invoke the `strip` binary on the generated dynamic library. I modified the CMake code to have an additional `ELSE()` branch that uses `execute_process` to output “I’m not invoking strip” to a text file on my system, and lo and behold when I ran `cmake --install` again that file was present with the expected contents!

I think, as you surmised, these differences explain all the behavior I was confused about originally.

Thanks so much once again for the suggestions. As a side note, I had not known what an [rpath](https://en.wikipedia.org/wiki/Rpath) was before, so I was happy to learn about that. I feel like I have a bit better appreciation of what’s going on behind the scenes now.

> **Addendum**
>
> I wanted to attach the diff files I made to explore what was going on, but unfortunately it seems that as a new user I cannot perform that action.
