12

I want to build both a static and shared version of the same library as described Is it possible to get CMake to build both a static and shared version of the same library?

However, the sources are compiled twice, one for each version which is not necessary. Is there any way to avoid this?

Currently I have:

add_library(${LIB} SHARED ${${LIB}_srcs})

add_library(${LIB}_static STATIC ${${LIB}_srcs})

What do I need to change in order to only need to compile once? FYI. I have the same compiler flags and defines.

Community
  • 1
  • 1
user1607549
  • 1,499
  • 3
  • 13
  • 17
  • 3
    Isn't it different compiler settings though? I know on Visual Studio you would certainly need to compile these 2 times (since there will be different compiler, linker settings and defines for a dll versus a static library) however I am not sure about gcc. – drescherjm Oct 15 '12 at 17:58
  • @drescherjm, on Linux/Solaris etc. you have to compile shared library object files to position independent code - with GCC/Solaris Studio/Clang etc. you supply -fpic/-fPIC to archieve that. Cf. my answer. – maxschlepzig Mar 08 '14 at 13:20
  • possible duplicate of: http://stackoverflow.com/questions/8912938/how-to-build-a-shared-and-a-static-library-without-recompiling-the-sources-with – maxschlepzig Mar 08 '14 at 19:37

2 Answers2

8

It's unfeasible and not recommended to create the shared/static library version from the same set of object files - at least on many platforms.

Object files linked into a shared library must be compiled as position independent code (-fpic/-FPIC on Linux/Solaris etc.) - whereas your executable and static libraries (usually) doesn't contain position independent code. On the other hand, shared libraries trade off sharing code pages with runtime overhead due to indirections. Since those indirections are unnecessary for static libraries and binaries, position independent code provides only disadvantages with thoses. Thus, if you want to create both a shared and a static library version you need to create two different sets of object files (one which is position independent and one which is the opposite).

Community
  • 1
  • 1
maxschlepzig
  • 35,645
  • 14
  • 145
  • 182
  • 3
    The first part of your statement is true: shared libraries require PIC. The second part isn't: you can very much build a static archive from PIC object files. When building static and shared libs from the same object files just have to make sure that PIC is used. In CMake: `set_property(TARGET ${objs} PROPERTY POSITION_INDEPENDENT_CODE 1)` where `${objs}` is the name of the object library. Check the link in Alexey's answer for details. – András Aszódi Apr 23 '15 at 13:13
  • 1
    @user465139, I've updated my answer and removed the 'impossible' part. – maxschlepzig Apr 23 '15 at 21:04
6

Since CMake 2.8.8 you can use Object Library: CMake: reuse object files built for a lib into another lib target.

See also http://www.cmake.org/Wiki/CMake/Tutorials/Object_Library

Community
  • 1
  • 1
Alexey
  • 938
  • 5
  • 13
  • 2
    This answer is misgiving, because it doesn't point out that compiling both the static and the shared lib with *position independent code* you would have a runtime performance penalty with the static version! See [this anwer] instead. – Paolo M Apr 21 '16 at 15:16