Combine static libraries

I’ve seen a bunch of related questions here and across the internet. However, most are pretty old and/or have different circumstances. So apologies for the potential repeat.

I have a project that organizes its files into several directories – each resulting in a static library. All of these libs are linked together with a main() to build the primary executable.

I also would like to combine those libs together into a single library – so users of my API can deal with just a single file. Some of my library users are not CMake users, so providing a single static library and an includes directory with what they need is the best way to go.

This seems like a very basic feature that CMake apparently lacks. I’ve found many old solutions, but some are limited (say only for OBJECT libraries), or are not cross-platform. I need a solution that works for Linux/Mac/Windows – gcc/clang/msvc.

Any help is appreciated,

Rob

1 Like

@ramcdona, did you find an elegant solution to your liking? If so could you share it?

My shop has done static library combos at times. It works, but I also question if there is a better CMake way of doing it.

We ended up creating two calling hierarchies. One for doing it on Windows (MSVC) and another for doing it on Linux (gcc), and a common interface call that would branch to Windows or Linux based on the machine we are running on. It “works” for the setup we have but we don’t do, and with this logic we cannot support, cross compilation.’

This is a long-running CMake request, the related issue is: https://gitlab.kitware.com/cmake/cmake/-/issues/19224

Thanks for the reply @JRR

I haven’t found a solution yet.

Fortunately, I don’t need to support cross compilation.

I do need to support MacOS too – and many of the solutions I’ve seen online rely on GNU ar behavior that BSD ar does not have.

@vito.gamberini Thanks for the reply.

The link you sent looks close, but it seems to start from a single target created with add_library().

In my situation, I’d like to bundle several targets created with add_library() – and ideally also several static libraries from outside my primary CMake project.

I have all of these in a list that I otherwise send as an argument to target_link_libraries( tgt ${lib_list} ).

I don’t see how to use the linked solution in this situation.

They’re the same, you want to call ar on static libraries to bundle them together. Whether those are system libraries or libraries created in the build is irrelevant to CMake.

The existing answer is to build the libraries you want to bundle as object libraries, then when they’re linked together a single archive is created with everything inside it.

CMake doesn’t have an abstraction for calling the archiver on static libraries to bundle them. It’s a known gap in the operations it supports.

The target_sources() command can be used to add sources to a target after the target has been defined.

This may be used to add sources in different subdirectories to build only one static library with all sources in a project tree.

@ramcdona, I think we did it on OSX long ago before we dropped its support. I thought we used ar even on OSX or maybe we used libtool, but that is a really old dusty memory – and a few SCMs and code purges ago.