# Static library dependencies

**URL:** <https://discourse.cmake.org/t/static-library-dependencies/9068>\
**Category:** Code\
**Created:** [September 24, 2023, 4:36pm UTC](https://discourse.cmake.org/t/static-library-dependencies/9068 "2023-09-24T16:36:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![YusakuGodai](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yusakugodai/32/3073_2.png) [@YusakuGodai](https://discourse.cmake.org/u/YusakuGodai)\
**Post date:** [September 24, 2023, 4:36pm UTC](https://discourse.cmake.org/t/static-library-dependencies/9068/1 "2023-09-24T16:36:08Z")

</div>

So, let’s say I have separate libraries A, B & C in separate project folders. C is a static library but it’s CMake is unimportant for this example.

B’s CMakeLists.txt looks something like this:

```auto
add_library(B STATIC b.cpp)
target_link_libraries(B PRIVATE C)

```

And A’s CMakeLists.txt looks something like this:

```auto
add_library(A STATIC a.cpp)
target_link_libraries(A PRIVATE B)

```

Now, I know the dependency to C is passed along to A thru B – that makes sense! If I were to add some shared or executable target that linked to A, I know that it needs both B & C’s outputs to link properly. That’s not my issue.

My issue is that when I try to build A, it complains that it can’t find target C. This is the part I don’t understand. Yes, the symbols for C are required ultimately for anyone who uses A, but _A_ doesn’t need C’s symbols. If C is truly private to B then I don’t even need it’s include files! So why do I get a CMake error complaining that it can’t find C when building A? I can’t tell if this is something I don’t understand or if I’m doing something wrong.

If it matters, I’m generating package cmake files as part of my outputs and using `find_package` to find & load targets. I’m mostly annoyed that I have to add a `find_package(C)` to A so CMake won’t halt and complain about not finding target C.

Any insight here would be greatly appreciated!

---

<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:** [September 24, 2023, 5:14pm UTC](https://discourse.cmake.org/t/static-library-dependencies/9068/2 "2023-09-24T17:14:01Z")

</div>

> [@YusakuGodai](#):
>
> it complains that it can’t find target C

Is it CMake that complains that _target_ C can’t be found or is it the linker complaining that symbols from C’s _library_ can’t be found? Do you have an actual error message (anonymized is fine).

> [@YusakuGodai](#):
>
> If it matters, I’m generating package cmake files as part of my outputs and using `find_package` to find & load targets. I’m mostly annoyed that I have to add a `find_package(C)` to A so CMake won’t halt and complain about not finding target C.

Ok, so it isn’t in _building_ A that you have problems, but with using A via `find_package(A)`? If this is the case, then yes, `B` needs to `find_package(C)` to make its target visible when in a static build.

When a static library has dependencies, the dependencies it links to with `PRIVATE` are added to the interface wrapped in `$<LINK_ONLY>`. This basically makes the target not necessary for compilation (no include directories, sources, compile options, definitions, etc.) but it is present for linking. This is because with a `STATIC` library, the dependent libraries are not actually copied during linking (verification of symbol availability may occur though). So anything using a `STATIC` library (say, `A`) needs to also know about these `PRIVATE` targets in order to properly link in all of the symbols (with `A`, that would be `B` and `C`).

See [this VTK MR](https://gitlab.kitware.com/vtk/vtk/-/merge_requests/10393) which hides `find_package` calls if the target requiring them is `SHARED`. Previously, all of these had been done in order to satisfy the `STATIC` build, but it is not necessary if the target needing them is `SHARED`.

---

<div class="post-metadata">

**Author:** ![YusakuGodai](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yusakugodai/32/3073_2.png) [@YusakuGodai](https://discourse.cmake.org/u/YusakuGodai)\
**Post date:** [September 25, 2023, 12:16am UTC](https://discourse.cmake.org/t/static-library-dependencies/9068/3 "2023-09-25T00:16:07Z")

</div>

Sorry, I should have used more precise language, and maybe a little more context would make it more obvious what I mean.

We have a collection of libraries we build individually from the command line and there are dependencies like I outlined above. So to continue with the original setup, I’ll generate a project for C with CMake, then do a build & install. Then I’ll do the same for B, but B’s CMakeLists.txt will include `find_package(C)` and I’d pass the C install directory when generating the project for B. Then I’ll do a build & install of B as well.

Lastly, I’m building static library A as outlined. Again, the CMakeLists for A will have a `find_package(B)` and I’d pass the install directory for B. This is the part that fails: generating the project for A. I don’t mind providing the full output for the project I’m working on – it wouldn’t exactly give away trade secrets or anything – but I figured a manufactured scenario was simpler. The error message I’d get for A would be something like:

```auto
  Target "A" links to target "C" but the
  target was not found. Perhaps a find_package() call is missing for an
  IMPORTED target, or an ALIAS target is missing?

```

I can solve this by adding a `find_package(C)` and also adding its install directory to the A generation step, but it _feels_ like I shouldn’t have to do that. But maybe I’m wrong?

Again, I understand that if I build some executable or shared library `app` and I link it to A, it will require me to provide both B & C as link targets as well. But since A is static, why is it giving me grief about C?

---

<div class="post-metadata">

**Author:** ![YusakuGodai](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yusakugodai/32/3073_2.png) [@YusakuGodai](https://discourse.cmake.org/u/YusakuGodai)\
**Post date:** [September 26, 2023, 11:37am UTC](https://discourse.cmake.org/t/static-library-dependencies/9068/4 "2023-09-26T11:37:46Z")

</div>

@ben.boeckel Does my question make more sense now? I’m not sure if you saw my reply. I can try and post a more detailed explanation if necessary.

---

<div class="post-metadata">

**Author:** ![YusakuGodai](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yusakugodai/32/3073_2.png) [@YusakuGodai](https://discourse.cmake.org/u/YusakuGodai)\
**Post date:** [September 27, 2023, 2:48am UTC](https://discourse.cmake.org/t/static-library-dependencies/9068/5 "2023-09-27T02:48:12Z")

</div>

Issue #19611 sounds like it’s basically my problem.

[https://gitlab.kitware.com/cmake/cmake/-/issues/19611](https://gitlab.kitware.com/cmake/cmake/-/issues/19611)

The reporter is saying it fails on the link step, but I actually get the error during the project generation step. Basically, I can see in my B (from my example above) that it includes a `$<LINK_ONLY:C>` in the exported config file. That makes sense of course, because if A was an executable or shared library, it _would_ need to link C. But since A is a static library I feel like it should just be passing along the `$<LINK_ONLY:C>` (presumably in addition to a `$<LINK_ONLY:B>`) to any consumers of A, not halt generation of A for lack of C.
