CMake target_sources and install

北城余情 提交于 2021-02-08 08:22:21

问题


I am having a hard time figuring out how to install PUBLIC headers specified in target_sources().

It appears that target_sources() is somewhat of a mystery for anything other than adding private sources to an executable. After reading a lot of material, where especially this blog entry was helpful, I managed to understand & bypass the issue with target_sources() and PUBLIC files. A CMakeLists.txt in one of the many subdirectories of my C++ library project looks like this:

target_sources(mylib
    PRIVATE
        foo.cpp

    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/foo.hpp>
        $<INSTALL_INTERFACE:foo.hpp>
)

This allows me to successfully build the library. However, upon installation, the header file(s) listed in the PUBLIC section of target_sources() are never installed.

My installation looks like this:

install(
    TARGETS
        mylib
    EXPORT mylib-targets
    LIBRARY
        DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT lib
    ARCHIVE
        DESTINATION ${CMAKE_INSTALL_LIBDIR}
        COMPONENT lib
    RUNTIME
        DESTINATION ${CMAKE_INSTALL_BINDIR}
        COMPONENT bin
    INCLUDES
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib

However, this doesn't install any of the headers. This stackoverflow answer mentions the use of PUBLIC_HEADER but reading the documentation doesn't give me the feeling that that is relevant in my case.

Question: What is the proper way of installing PUBLIC or INTERFACE headers using install()?

Background: My goal is to have a separate CMakeLists.txt in every subdirectory of my source tree. Each of these lists is supposed to use target_sources() to add PRIVATE and PUBLIC files to the build. All PUBLIC (and INTERFACE) sources should be installed during installation.


回答1:


PUBLIC section of target_sources command has nothing common with public headers installed with PUBLIC_HEADER option of install command.

The headers you want to treat as public for your library should be listed in PUBLIC_HEADER property for the target.

Documentation for install(TARGETS) has a nice example of setting and installing private headers. In your case this would be:

# This defines `foo.hpp` located in the current source directory as a 'public header'.
set_target_properties(mylib PROPERTIES PUBLIC_HEADER foo.hpp)
# This install public headers among with the library.
install(
  TARGETS
    mylib
  PUBLIC_HEADER
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib
  # ... other options
)

See also that related question: How to configure CMakeLists.txt to install public headers of a shared library?.


Note also, that INCLUDES and PUBLIC_HEADERS clauses for install(TARGETS) command are different things:

  • INCLUDES specifies include directory for the installed library
  • PUBLIC_HEADERS specifies directory where all target's public headers will be copied upon installation.

E.g. if you want your header file to be used via

#include <mylib/foo.h>

then you need provide following options for install() command:

  PUBLIC_HEADER
    # The header will be places at ${CMAKE_INSTALL_INCLUDEDIR}/mylib/foo.h
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib
  INCLUDES
    # This directory will be used as include directory.
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}

So <include-directory> joined (via /) with the relative path in #include<> directive will give absolute path to the header file.



来源:https://stackoverflow.com/questions/60736689/cmake-target-sources-and-install

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!