# Using object libraries to build a library for distribution.

**URL:** https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574
**Category:** Code
**Created:** [December 1, 2021, 12:51am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574 "2021-12-01T00:51:22Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Andrew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/andrew/32/2478_2.png) [@Andrew](https://discourse.cmake.org/u/Andrew)
#### Post date: [December 1, 2021, 12:51am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/1 "2021-12-01T00:51:22Z")

</div>

Situation:

We have a complex code base with lots of smallish libraries generated by CMake. For internal use, we can just link against these libraries.

However, we also want to provide a public library for 3rd parties to use. The code in this library is implemented using many of our internal libraries. However, we only want to ship a single library. This is partly for convenience, and partly because we don’t want to expose more of our internal architecture than we need to.

Prior to moving to CMake, we had an archiving step that collapsed all the smaller libraries into a single exportable libraries. On some platforms, this was supported by the archiver (e.g. MacOS libtool). On others, we unpacked the sub-libraries and re-packed them into a single large library.

CMake doesn’t seem to have a mechanism to do this automatically. Post 3.12, one can achieve something similar with object libraries without a lot of pain. But if we switch all our internal libraries over to being object libraries, what are the hidden costs?

Alternatively, what would it take for CMake to support this behaviour directly?

Basic support would be to define a new target type ‘archive’. This would mostly function like a library, but target\_link\_libraries would re-pack the libraries into the archive (like happens post 3.12 when object libraries are added to a regular library) rather than add them to the link interface.

Rather than re-packing, the “archive” could treat all dependent libraries as if they were object libraries and grab their object files rather than the finished libraries. It’s possible to fudge this behaviour by using a CMake function to wrap add\_library and switch between regular or object libraries. This might create issues if someone uses a feature that works on libraries but not object libraries which then breaks for archives - at least doing the switch manually rather than automatically makes it clear that someone unusual is happening.

More sophisticated archive behaviour would copy header files from PUBLIC dependencies into a new header directory. Given that adding headers (vs header paths) to projects is currently cosmetic, this could be managed in one of two ways:

- the archive target could list (relative?) paths to all headers to be included
- individual library targets could have some way of flagging headers as “to be exported” in the case of archives.

Handling header files might be stepping on CPack’s toes - a copy header files step is not needed to build the archive binary or link against it.

---

<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: [December 1, 2021, 11:58am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/2 "2021-12-01T11:58:18Z")

</div>

@marc.chevrier is working on [a feature](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6769) that should help here by having CMake consider a “linker feature” abstraction. Given a “whole archive” feature, CMake could be coaxed into making the command line as needed. As for what features actually exist, we’ll need to figure out which CMake will provide and such as the availability across platforms is quite spotty for various features.

---

<div class="post-metadata">

### Author: ![Andrew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/andrew/32/2478_2.png) [@Andrew](https://discourse.cmake.org/u/Andrew)
#### Post date: [December 2, 2021, 2:49am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/3 "2021-12-02T02:49:01Z")

</div>

Thanks Ben.

I don’t fully understand the discussion on that other page, but I did notice a query about what libraries would or would not be pulled in (e.g. local vs third-party).

I’d be perfectly happy if the “archive” feature was non-transitive. That is, only explicitly specified libraries get archived, any recursive dependencies that are not archived just become part of the link interface as usual.

I’ve written up a [feature request](https://gitlab.kitware.com/cmake/cmake/-/issues/22975) to be more precise about what I’d like for CMake to support.

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [December 2, 2021, 9:19am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/4 "2021-12-02T09:19:11Z")

</div>

The [feature](https://gitlab.kitware.com/cmake/cmake/-/merge_requests/6769) I am working on will not be of any help for this problem.

The goal is to decorate libraries when the linker is called, not the archiver.

---

<div class="post-metadata">

### Author: ![Andrew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/andrew/32/2478_2.png) [@Andrew](https://discourse.cmake.org/u/Andrew)
#### Post date: [December 3, 2021, 1:01am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/5 "2021-12-03T01:01:31Z")

</div>

OK, I’ve discovered an issue with recursive inclusion. Object libraries don’t seem to be transitive.

Consider:

[CMakeLists.txt](https://discourse.cmake.org/uploads/short-url/qzjF76NCqGQpYHoxiZSevFCXYue.txt) (788 Bytes)

Key lines:

> target\_link\_libraries( b PUBLIC a )  
> target\_link\_libraries( main PUBLIC b )  
> target\_link\_libraries( main\_all PUBLIC b a )

- If B and A are regular libraries, then both `main` and `main_all` build.
- If B and A are object libraries, then ‘main\_all’ builds, but when building `main`, the symbols from A are missing.
- If _only one_ of B or A are object libraries, then both `main` and `main_all` build.

This problem exists on:

- CMake 3.21.2 for Mac building to Makefiles
- CMake 3.21.2 for Mac building to XCode
- CMake 3.20.3 for Linux building to Makefiles

The problem does not seem to exist on:

- CMake 3.20.0 for Windows building to Visual Studio 2013 or 2015

This is all with PUBLIC dependencies.

---

<div class="post-metadata">

### Author: ![Andrew](https://discourse.cmake.org/user_avatar/discourse.cmake.org/andrew/32/2478_2.png) [@Andrew](https://discourse.cmake.org/u/Andrew)
#### Post date: [December 3, 2021, 1:07am UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/6 "2021-12-03T01:07:35Z")

</div>

I had first thought it was an issue with PRIVATE, but the Windows builds also worked with `target_link_libraries( b PRIVATE a)`.

I notice that 3.21 allows the use of the `$<TARGET_OBJECTS:obj_lib>` generator expression in `target_link_libraries`. When would I use this rather than just directly referencing the object library?

---

<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: [December 3, 2021, 8:51pm UTC](https://discourse.cmake.org/t/using-object-libraries-to-build-a-library-for-distribution/4574/7 "2021-12-03T20:51:18Z")

</div>

Linking to OBJECT libraries only brings in they objects themselves if directly named, not if brought in transitively. This is to avoid duplicate symbols by a shared library publicly linking to an OBJECT library (for usage requirements) also putting the objects directly into a consuming executable’s link line.
