Tomasso
Tomasso

Reputation: 711

Why no 'install' rules generated by cmake install()?

I'm running cmake v 3.18.0 on ubuntu 20.04

My install() command doesn't generate any install rules within the generated Makfile. CMakeLists.txt looks like this:

# Static library
add_library(mbaux
            STATIC 
            mb_cheb.c mb_delaun.c mb_intersectgrid.c mb_readwritegrd.c 
            mb_surface.c mb_track.c mb_truecont.c mb_zgrid.c)


target_include_directories(mbaux
                           PUBLIC
                           .
                           ${X11_INCLUDE_DIR}
                           ${GMT_INCLUDE_DIR}
                           ${GDAL_INCLUDE_DIR}
                           ${CMAKE_SOURCE_DIR}/src/mbio)

# Static library
add_library(mbxgr
            STATIC 
            mb_xgraphics.c)


target_include_directories(mbxgr
                           PUBLIC
                           .
                           ${X11_INCLUDE_DIR}                      
                           ${GMT_INCLUDE_DIR}
                           ${GDAL_INCLUDE_DIR}
                           ${CMAKE_SOURCE_DIR}/src/mbio)
                           
# Install
message("set up mbaux install targets")
install(TARGETS mbaux DESTINATION cmake-example/lib)
install(TARGETS mbxgr DESTINATION cmake-example/lib)

Yet when I look in the generated Makefile I see my message "set up mbaux install targets" but there is no reference to the destination 'cmake-example/lib', and no specific 'install' target that I can see.

Thanks!

Upvotes: 0

Views: 509

Answers (2)

Alex Reinking
Alex Reinking

Reputation: 19916

Just because you seem new to CMake, a couple words of advice re: install rules...

First, avoid hard-coding destinations. You always want to include(GNUInstallDirs) (even on Windows). This module defines a number of standard cache variables for configuring installation destinations.

See the documentation for the full list, but the following are the most relevant here:

  • CMAKE_INSTALL_INCLUDEDIR - the path below the installation prefix where the include structure should exist. Typically, and by default, include.
  • CMAKE_INSTALL_LIBDIR - the path below the installation prefix where libraries should be stored. Typically, and by default, lib. Often overridden on multiarch systems to include the target architecture, such as lib/aarch64-linux-gnu.
  • CMAKE_INSTALL_DATADIR - the path below the installation prefix where package-specific data should be stored. Typically, and by default, share.

In CMake 3.14+ these are used as the default destinations for install(TARGETS). This should be all you need:

include(GNUInstallDirs)

install(
  TARGETS mbaux mbxgr ...
  EXPORT mb-targets
  RUNTIME COMPONENT mb-runtime
  LIBRARY COMPONENT mb-runtime
  NAMELINK_COMPONENT mb-development
  ARCHIVE COMPONENT mb-development
  INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)

Don't forget to guard your include paths with $<BUILD_INTERFACE:...> in the main build (to allow INCLUDES DESTINATION above to overwrite them):

target_include_directories(
  mbaux
  PUBLIC 
  "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src/mbio>"
)

You almost certainly do not want to use the ${<PACKAGE_NAME>_INCLUDE_DIRS} variables here, either. Instead use target_link_libraries with the relevant imported targets; this will set up include paths automatically.

target_link_libraries(mbaux PRIVATE X11::X11)  # likely similar for GMT/GDAL

When you are required to specify a destination, you generally want to use the TYPE argument instead of DESTINATION. If you must use DESTINATION, use a project-specific cache variable as its argument; for example:

# will install headers to ${CMAKE_INSTALL_INCLUDEDIR}/**/*.h
# without mbio prefix, remove the trailing / to include mbio 
# in the path
install(DIRECTORY "${PROJECT_SOURCE_DIR}/src/mbio/"
        TYPE INCLUDE
        COMPONENT mb-development
        FILES_MATCHING PATTERN "*.h")

set(MB_INSTALL_CMAKEDIR "${CMAKE_INSTALL_DATADIR}/cmake/mb"
    CACHE STRING "Installation directory for CMake package files")

install(EXPORT mb-targets
        DESTINATION "${MB_INSTALL_CMAKEDIR}"
        NAMESPACE mb::
        FILE mb-targets.cmake)

Finally, you should never read or set CMAKE_INSTALL_PREFIX from within the CMakeLists.txt file. Instead you should rely on relative paths (as done above) or the $<INSTALL_PREFIX> generator expression (in exceptional circumstances) to avoid making your installation script non-relocatable.

Upvotes: 2

Tomasso
Tomasso

Reputation: 711

As pointed out by Stephen Newell, cmake spreads rules and logic across multiple files - and I now see where they are (in this case, cmake_install.cmake)

Upvotes: 0

Related Questions