18

Suppose that I've got the following libraries:

add_library(myLib_static STATIC ${SRC_FILES})
add_library(myLib SHARED ${SRC_FILES})

# installing header files
install(FILES ${H_FILES} DESTINATION ${INSTDIRHEADER})

# installing binaries
install(TARGETS myLib_static
         DESTINATION ${INSTDIRBIN})

install(TARGETS myLib
         DESTINATION ${INSTDIRBIN})

If I execute the following command, both shared and static libraries will be installed:

make install

How can I have separate install commands for each of them? Something like this:

make install-static
make install-shared

Update:

Header files should also be installed when needed:

install(FILES ${H_FILES} DESTINATION ${INSTDIRHEADER})
B Faley
  • 17,120
  • 43
  • 133
  • 223

1 Answers1

26

Put them each in a different component and set up custom targets for the installations.

add_library(foo_static STATIC foo.cpp)
add_library(foo SHARED foo.cpp)

install(TARGETS foo_static
        DESTINATION bin
        COMPONENT static)

install(TARGETS foo
        DESTINATION bin
        COMPONENT shared)

add_custom_target(foo-install
  DEPENDS foo
  COMMAND 
      "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=shared
      -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)

add_custom_target(foo_static-install
  DEPENDS foo_static
  COMMAND
     "${CMAKE_COMMAND}" -DCMAKE_INSTALL_COMPONENT=static 
     -P "${CMAKE_BINARY_DIR}/cmake_install.cmake"
)

install(FILES foo.h DESTINATION include COMPONENT static)
install(FILES foo.h DESTINATION include COMPONENT shared)

Then invoke the custom targets.

stephen@hal:~/dev/src/playground/cmake/build{master}$ cmake .. -DCMAKE_INSTALL_PREFIX=prefix
-- The C compiler identification is GNU 4.8.1
-- The CXX compiler identification is GNU 4.8.1
-- Check for working C compiler: /usr/lib/icecc/bin/cc
-- Check for working C compiler: /usr/lib/icecc/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/lib/icecc/bin/c++
-- Check for working CXX compiler: /usr/lib/icecc/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/stephen/dev/src/playground/cmake/build
stephen@hal:~/dev/src/playground/cmake/build{master}$ make foo_static-install
makeobj[0]: Entering directory `/home/stephen/dev/src/playground/cmake/build'
Scanning dependencies of target foo_static
[100%] Building CXX object CMakeFiles/foo_static.dir/foo.cpp.o
Linking CXX static library libfoo_static.a
[100%] Built target foo_static
Scanning dependencies of target foo_static-install
-- Install configuration: ""
-- Installing: /home/stephen/dev/src/playground/cmake/build/prefix/bin/libfoo_static.a
-- Installing: /home/stephen/dev/src/playground/cmake/build/prefix/include/foo.h

[100%] Built target foo_static-install
makeobj[0]: Leaving directory `/home/stephen/dev/src/playground/cmake/build'
stephen@hal:~/dev/src/playground/cmake/build{master}$ make foo-install
makeobj[0]: Entering directory `/home/stephen/dev/src/playground/cmake/build'
Scanning dependencies of target foo
[100%] Building CXX object CMakeFiles/foo.dir/foo.cpp.o
Linking CXX shared library libfoo.so
[100%] Built target foo
Scanning dependencies of target foo-install
-- Install configuration: ""
-- Installing: /home/stephen/dev/src/playground/cmake/build/prefix/bin/libfoo.so
-- Up-to-date: /home/stephen/dev/src/playground/cmake/build/prefix/include/foo_p.h
[100%] Built target foo-install
makeobj[0]: Leaving directory `/home/stephen/dev/src/playground/cmake/build'

Note that components are used by cpack to allow the user installing a package to decide which components to install. So, for a library, the headers might be part of the Development component. In this case we install the header with both the shared and static component. It might make sense to additionally install it with a Development component if cpack is to be used in that way.

steveire
  • 10,694
  • 1
  • 37
  • 48
  • Thank you very much! Could you please update your answer according to the updated question? Your solution does not install the header files. – B Faley Feb 18 '14 at 13:08
  • After adding `install(FILES foo.h DESTINATION include COMPONENT static)` and `install(FILES foo.h DESTINATION include COMPONENT shared)`, all header files are now copied twice into the include directory after executing `make install`. Is there any way to fix this? – B Faley Feb 19 '14 at 06:20
  • You're moving the goal posts every time I answer :). I don't know. – steveire Feb 20 '14 at 19:31
  • @Meysam: EXCLUDE_FROM_ALL option for install command can help – vsh Apr 20 '20 at 11:58
  • @vsh "Installing a target with the EXCLUDE_FROM_ALL target property set to TRUE has undefined behavior." – kyb Apr 30 '20 at 14:30
  • @kyb "EXCLUDE_FROM_ALL Specify that the file is excluded from a full installation and only installed as part of a component-specific installation" [link](https://cmake.org/cmake/help/v3.12/command/install.html) – vsh May 01 '20 at 12:51
  • @vsh my quotation was from CMake version 3.0.2, yours one from later release (i.e. 3.17) – kyb May 01 '20 at 18:21