[CMake] Best way to combine generated static libraries into a single static library

Deniz Bahadir deniz.bahadir at benocs.com
Sat Sep 22 05:41:51 EDT 2018


Am 21.09.2018 um 21:23 schrieb Ke Gao:
> So I guess in order to include the object-files from a third party 
> static library, the only way would be to first extract it's object-files 
> and then combine them?

That is how I understand it, yes.

> 
> On Fri, Sep 21, 2018 at 12:34 PM Deniz Bahadir <dbahadir at benocs.com 
> <mailto:dbahadir at benocs.com>> wrote:
> 
>     Am 21.09.2018 um 18:38 schrieb Ke Gao:
>      > Hi David,
>      >
>      > It didn't give me error info. It can produce the final static
>     library,
>      > but the contents of third party static libraries are not included.
> 
>     Some clarification regarding STATIC and OBJECT library targets and how
>     they interact with each other using `target_link_libraries`:
> 
> 
>     A STATIC library target A can be linked (via
>     `target_link_libraries`) to
>     another STATIC library target B.
> 
>         `target_link_libraries(A STATIC PUBLIC B)`
> 
>     However, the resulting library file libB does not contain the
>     information (aka object-files) of libA.
>     Instead, CMake makes sure to link both static library files libB and
>     libA when e.g. creating an executable exeC1 using target C1 which just
>     links (via `target_link_libraries`) to target B.
> 
>         `target_link_libraries(C1 EXECUTABLE PUBLIC B)`
> 
>     (Instead of an executable exeC1 you could have created a shared library
>     libC1 instead. The behavior is the same.)
> 
> 
>     If you instead want to create a combined, single STATIC library libC2,
>     which contains the object-files archived in both static library files
>     libA and libB created from targets A and B, then you somehow need to
>     extract the archived object-files from libA and libB. I am not sure if
>     CMake provides a (simple) way to do this.
> 
> 
> 
>     For OBJECT libraries the behavior is like this:
> 
> 
>     An OBJECT library target X can be linked (via `target_link_libraries`)
>     to another OBJECT library target Y.
> 
>         `target_link_libraries(Y OBJECT PUBLIC X)`
> 
>     This, however, only transports the usage-requirements
>     (preprocessor-defines, include-paths etc.) from X to Y. The
>     object-files
>     of X are in no way referenced by Y.
> 
>     So, if you then create a STATIC target Z1 that links (via
>     `target_link_libraries`) to Y,...
> 
>         `target_link_libraries(Z1 STATIC PUBLIC Y)`
> 
>     ... Z1 will reference/contain the usage-requirements of X and Y and the
>     object-files of Y, but not the object-files of X. (The static library
>     file libZ1 resulting from Z1 will contain the object-libraries of Y but
>     not of X.)
> 
> 
>     What you should do instead is not to link the OBJECT targets X and Y
>     together but instead only link them (explicitly) to the STATIC
>     target Z2:
> 
>         `target_link_libraries(Z2 STATIC PUBLIC Y X)`
> 
>     Z2 then references the usage-requirements as-well-as object-files of
>     both OBJECT targets X and Y and the resulting static library file libZ2
>     will then contain the object-files of both library targets, X and Y.
> 
> 
>      >
>      > Also, sorry for the mistake I have made in my previous email.
>     Deniz is
>      > right, the keyword "PUBLIC" should be used in target_link_librarie().
>      >
>      > Thanks
> 
>     You're welcome.
> 
>     Deniz
> 
> 
>      >
>      > On Fri, Sep 21, 2018 at 10:06 AM David Jobet
>     <djobet at tower-research.com <mailto:djobet at tower-research.com>
>      > <mailto:djobet at tower-research.com
>     <mailto:djobet at tower-research.com>>> wrote:
>      >
>      >     Hello,
>      >
>      >     glad that could help you.
>      >     For your newer problem, you don't describe them, so it's
>     tough to know
>      >     what kind of problems you're facing.
>      >     Maybe a small example of your CMakeLists.txt + a capture of
>     the error
>      >     cmake gives you could help ?
>      >
>      >     David
>      >     On Fri, Sep 21, 2018 at 4:52 PM Ke Gao <ke.gao.ut at gmail.com
>     <mailto:ke.gao.ut at gmail.com>
>      >     <mailto:ke.gao.ut at gmail.com <mailto:ke.gao.ut at gmail.com>>> wrote:
>      >      >
>      >      > Thank you all for the help.
>      >      >
>      >      > I finally use a way quite similar to David's first approach. I
>      >     first generate all sub-projects into object libraries using
>      >     add_library(lib1 OBJECT SOURCES). Then in the final library,
>     I use
>      >     add_library(single_static_lib STATIC SOURCES) and
>      >     target_link_libraries( single_static_lib lib1 lib2 ...). Note
>     that I
>      >     didn't use " $<TARGET_OBJECTS:lib1>" in the final
>     "add_library" and
>      >     also didn't use "PUBLIC" keyword in the final
>      >     "target_link_libraries". It works on CMake v3.12.2 and gives me a
>      >     single static lib which combines all the objs I want.
>      >      >
>      >      > But currently I still have problems of further combining third
>      >     party static libraries into the final generated static
>      >     single_static_lib. Can anybody provide a solution for this?
>      >      >
>      >      > Thank you very much.
>      >      >
>      >      > Ke
>      >      >
>      >      > On Fri, Sep 21, 2018 at 6:15 AM Deniz Bahadir
>      >     <dbahadir at benocs.com <mailto:dbahadir at benocs.com>
>     <mailto:dbahadir at benocs.com <mailto:dbahadir at benocs.com>>> wrote:
>      >      >>
>      >      >> Am 21.09.2018 um 09:33 schrieb David Jobet:
>      >      >> > Hello,
>      >      >> >
>      >      >> > I had a similar issue lately and wanted to "pack" several
>      >     static libs
>      >      >> > into a dynamic one. (Not even talking about an
>     INTERFACE lib
>      >     since I
>      >      >> > really wanted that .so)
>      >      >> > I made it work with 3 different solutions, none of them
>     being
>      >     "clean"
>      >      >> > from my point of view.
>      >      >> >
>      >      >> > 1- OBJECT libs on sub projects : add_library(lib1 OBJECT
>      >     SOURCES) and
>      >      >> > for the single static lib :
>     add_library(single_static_lib STATIC
>      >      >> > $<TARGET_OBJECTS:lib1> ...)
>      >      >> > Problem I faced : since OBJECT libs do not support
>      >      >> > target_link_libraries(), I had to remove the existing
>     one and move
>      >      >> > them instead to the target_include_directories() using
>     generators.
>      >      >>
>      >      >> This is no longer true. Since CMake 3.12
>     `target_link_libraries`
>      >     fully
>      >      >> supports OBJECT libraries. You just need to pay attention
>     to the
>      >     special
>      >      >> case of linking an OBJECT library with keyword "PUBLIC".
>      >     (Object-files
>      >      >> are always private and inherited object-files are
>     therefore never
>      >      >> further inherited. See:
>      >      >>
>      >
>     https://cmake.org/cmake/help/v3.12/command/target_link_libraries.html#linking-object-libraries)
>      >      >>
>      >      >> > e.g : target_include_directories(lib1 PUBLIC
>      >      >> > $<TARGET_PROPERTY:another_lib,INCLUDE_DIRECTORIES>)
>      >      >> > Because I had a dependency to a protobuf generated lib,
>     I also
>      >     had to
>      >      >> > add manual add_dependencies to respect proper build order.
>      >      >> > Not clean at all
>      >      >> >
>      >      >> > 2- add_library(mysharedlib STATIC CMakeLists.txt)
>      >      >> > target_linked_libraries(mysharedlib PUBLIC lib1 ...)
>      >      >> > Maybe the cleanest way I found.
>      >      >> > The trick with CMakeLists.txt is that add_library needs at
>      >     least one
>      >      >> > source file. You can put any kind of files you want.
>      >     CMakeLists.txt is
>      >      >> > not compilable, so no extra compilation step, no need for
>      >     dummy empty
>      >      >> > source file and add_library is happy.
>      >      >> > It did not work in my case because of problems related
>     to how
>      >     our .so
>      >      >> > are used/generated. (problems at runtime with duplicated
>      >     symbols in
>      >      >> > protobufs)
>      >      >> >
>      >      >> > 3- a variation around 1
>      >      >> > instead of defining OBJECT libs, define a variable
>     holding all the
>      >      >> > sources for lib1, another for lib2, ...
>      >      >> > then just do add_library(mysharedlib STATIC
>     ${SOURCES_FOR_lib1}
>      >      >> > ${SOURCES_FOR_lib2})
>      >      >> > It works a little bit like 1) but does not have any of its
>      >     problems
>      >      >> > (target_link, add_dependencies, generators, ...)
>      >      >> > It has new problems of its own though : if your libs
>     live in
>      >     different
>      >      >> > subfolders, the variables might not be visible from your
>      >      >> > add_library(mysharedlib...) call.
>      >      >> > To work around that, you can use PARENT_SCOPE (not sure if
>      >     that works
>      >      >> > accross several levels), or includes (defines those
>     variables into
>      >      >> > separate files living in each subfolders and include
>     them in the
>      >      >> > parent CMakeLists).
>      >      >> >
>      >      >> > Hope this helps (and I'd be happy to know of other ways)
>      >      >> >
>      >      >> > David
>      >      >> > On Thu, Sep 20, 2018 at 5:45 PM Ke Gao
>     <ke.gao.ut at gmail.com <mailto:ke.gao.ut at gmail.com>
>      >     <mailto:ke.gao.ut at gmail.com <mailto:ke.gao.ut at gmail.com>>> wrote:
>      >      >> >>
>      >      >> >> Hi,
>      >      >> >>
>      >      >> >> I have a project which includes many sub-projects. Each
>      >     sub-project generates a static library. In the main project,
>     I want
>      >     to combine the generated objs, generated static libraries
>     from other
>      >     sub-projects, and some other third party static libraries
>     together
>      >     into a single static library. Is there an elegant way to do
>     this, or
>      >     maybe an existing function?
>      >      >> >>
>      >      >> >> Thank you very much.
>      >      >> >>
>      >      >> >> --
>      >      >> >>
>      >   
>       ..............................................................................................................................................
>      >      >> >> Ke Gao
>      >      >>
>      >      >>
>      >      >> Hope that information was of value,
>      >      >> Deniz
>      >      >>
>      >      >> --
>      >      >>
>      >      >> Powered by www.kitware.com <http://www.kitware.com>
>     <http://www.kitware.com>
>      >      >>
>      >      >> Please keep messages on-topic and check the CMake FAQ at:
>      > http://www.cmake.org/Wiki/CMake_FAQ
>      >      >>
>      >      >> Kitware offers various services to support the CMake
>     community.
>      >     For more information on each offering, please visit:
>      >      >>
>      >      >> CMake Support: http://cmake.org/cmake/help/support.html
>      >      >> CMake Consulting: http://cmake.org/cmake/help/consulting.html
>      >      >> CMake Training Courses:
>     http://cmake.org/cmake/help/training.html
>      >      >>
>      >      >> Visit other Kitware open-source projects at
>      > http://www.kitware.com/opensource/opensource.html
>      >      >>
>      >      >> Follow this link to subscribe/unsubscribe:
>      >      >> https://cmake.org/mailman/listinfo/cmake
>      >      >
>      >      >
>      >      >
>      >      > --
>      >      >
>      >   
>       ..............................................................................................................................................
>      >      > Ke Gao
>      >     --
>      >
>      >     Powered by www.kitware.com <http://www.kitware.com>
>     <http://www.kitware.com>
>      >
>      >     Please keep messages on-topic and check the CMake FAQ at:
>      > http://www.cmake.org/Wiki/CMake_FAQ
>      >
>      >     Kitware offers various services to support the CMake
>     community. For
>      >     more information on each offering, please visit:
>      >
>      >     CMake Support: http://cmake.org/cmake/help/support.html
>      >     CMake Consulting: http://cmake.org/cmake/help/consulting.html
>      >     CMake Training Courses: http://cmake.org/cmake/help/training.html
>      >
>      >     Visit other Kitware open-source projects at
>      > http://www.kitware.com/opensource/opensource.html
>      >
>      >     Follow this link to subscribe/unsubscribe:
>      > https://cmake.org/mailman/listinfo/cmake
>      >
>      >
>      >
>      > --
>      >
>     ..............................................................................................................................................
>      > Ke Gao
>      >
>      >
>     -- 
> 
>     Powered by www.kitware.com <http://www.kitware.com>
> 
>     Please keep messages on-topic and check the CMake FAQ at:
>     http://www.cmake.org/Wiki/CMake_FAQ
> 
>     Kitware offers various services to support the CMake community. For
>     more information on each offering, please visit:
> 
>     CMake Support: http://cmake.org/cmake/help/support.html
>     CMake Consulting: http://cmake.org/cmake/help/consulting.html
>     CMake Training Courses: http://cmake.org/cmake/help/training.html
> 
>     Visit other Kitware open-source projects at
>     http://www.kitware.com/opensource/opensource.html
> 
>     Follow this link to subscribe/unsubscribe:
>     https://cmake.org/mailman/listinfo/cmake
> 
> 
> 
> -- 
> ..............................................................................................................................................
> Ke Gao

-- 
BENOCS GmbH
Dipl.-Inform. Deniz Bahadir
Reuchlinstr. 10 D
10553 Berlin
Germany
Phone: +49 - 30 / 577 0004-22
Email: deniz.bahadir at benocs.com
www.benocs.com

Advisory Board (Chairman): Oliver Fietz
Board of Management: Stephan Schröder, Dr.-Ing. Oliver Holschke, 
Dr.-Ing. Ingmar Poese
Commercial Register: Amtsgericht Bonn HRB 19378


More information about the CMake mailing list