c++ - CMake 错误 - 目标 foo INTERFACE_SOURCES 属性包含源目录中前缀的路径

标签 c++ cmake

我正在尝试创建一个可以通过 CMake 重用的 C++ 库。当我尝试为项目安装导出文件时它失败了。我不明白为什么。这是我得到的错误。

Target "Proj_LibA" INTERFACE_SOURCES property contains path:

  "C:/projects/cmake_temp/src/libA/include/liba.hpp"

which is prefixed in the source directory.

阅读 CMake 文档和其他 stackoverflow帖子暗示我设置源文件路径和/或包含目录的方式有问题。这是重现我的问题的 SSCE。

文件夹结构
cmake_temp/
          /build
          /install
          /src/
              /CMakeLists.txt
          /src/libA/
                   /include/liba.hpp
                   /CMakeLists.txt
                   /liba.cpp
                   /LibAConfig.cmake.in

/src/CMakeLists.txt
cmake_minimum_required (VERSION 3.15)
project("TestProj")

set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)

set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

set(include_install_dir ${CMAKE_INSTALL_PREFIX}/include/)
set(export_cmake ${CMAKE_INSTALL_PREFIX}/cmake)
set(lib_install_dir ${CMAKE_INSTALL_PREFIX}/lib)
set(bin_install_dir ${CMAKE_INSTALL_PREFIX}/bin)

add_subdirectory(libA)
#add_subdirectory(exec)

liba/include/liba.hpp
#ifndef liba
#define liba

#include "LibA_export.hpp"

class PROJ_LIBA_EXPORT Foo
{
public:
    Foo(const int bias);
    int add(int a, int b);
private:
    int mBias;
};

#endif //liba

src/liba/liba.cpp
#include "liba.hpp"
Foo::Foo(const int bias) : mBias(bias) {}
int Foo::add(int a, int b) { return a + b + mBias; }

src/liba/CMakeLists.txt
# Setup alias to support add_subdirectory, find_package, and fetchcontent usage
add_library(Proj_LibA SHARED)
add_library(proj::liba ALIAS Proj_LibA)
set_target_properties(Proj_LibA PROPERTIES
    EXPORT_NAME LibA
    POSITION_INDEPENDENT_CODE TRUE)

target_sources(Proj_LibA
    PUBLIC
        include/liba.hpp
    PRIVATE
        liba.cpp)

target_include_directories(Proj_LibA
   PUBLIC
      $<INSTALL_INTERFACE:${include_install_dir}>
      $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
      $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>
   #PRIVATE
)

# Generate symbol export macros and add to source
include(GenerateExportHeader)
set(export_file "${CMAKE_CURRENT_BINARY_DIR}/LibA_export.hpp")
generate_export_header(Proj_LibA EXPORT_FILE_NAME ${export_file})
target_sources(Proj_LibA PUBLIC ${export_file})

# Install everything and mark it as part of the 'sdk' export package
install(TARGETS Proj_LibA
   EXPORT sdk
   ARCHIVE DESTINATION ${lib_install_dir}
   LIBRARY DESTINATION ${lib_install_dir}
   RUNTIME DESTINATION ${bin_install_dir}
)

# Install header files for package consumers
INSTALL(DIRECTORY include/ DESTINATION ${include_install_dir})

# Create the LibAConfig.cmake file for find_package
include(CMakePackageConfigHelpers)
configure_package_config_file(LibAConfig.cmake.in
  ${CMAKE_CURRENT_BINARY_DIR}/LibAConfig.cmake
  INSTALL_DESTINATION ${export_cmake}
  PATH_VARS include_install_dir)

# Create the LibAConfigVersion.cmake file for find_package
write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/LibAConfigVersion.cmake
  VERSION 1.2.3
  COMPATIBILITY SameMajorVersion )

# Install the LibAConfig*.cmake files
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/LibAConfig.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/LibAConfigVersion.cmake
        DESTINATION ${export_cmake})

# Install the auto-generated export support/find_package scripts
install(EXPORT sdk
   DESTINATION ${export_cmake}
   NAMESPACE proj::)

# HELP: The above command triggers the following errors
#CMake Error in libA/CMakeLists.txt:
#  Target "Proj_LibA" INTERFACE_SOURCES property contains path:
#
#    "C:/projects/cmake_temp/src/libA/include/liba.hpp"
#
#  which is prefixed in the source directory.
#
#
#CMake Error in libA/CMakeLists.txt:
#  Target "Proj_LibA" INTERFACE_SOURCES property contains path:
#
#    "C:/projects/cmake_temp/build/libA/LibA_export.hpp"
#
#  which is prefixed in the build directory.

src/liba/LibAConfig.cmake.in
set(LibA_VERSION 1.2.3)

@PACKAGE_INIT@

set_and_check(LibA_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@")

check_required_components(LibA)

有没有人对我在尝试导出我的库时应该查看什么来解决此错误有什么建议?

最佳答案

我昨天也遇到了这个问题。通读文档和 blog post of "co-maintainer of CMake"有助于阐明这一点(tldr;请参阅安装的并发症段落)。

这里的问题来自您的liba.hpp被添加为 PUBLIC目标源,它定义了头文件的绝对路径。这在本地机器上的构建树中有效,但在安装时可能会有所不同,使用 find_package()或将您的库复制到另一个源代码树中。我认为很多人,包括我自己,都会做出 PUBLIC 的假设。或 INTERFACE与公共(public)头文件相关联,事实并非如此。引用上面的博客文章:

[...] do not confuse the PRIVATE , PUBLIC and INTERFACE keywords with whether a header is part of the public API for the library or not, the keywords are specifically for controlling which target(s) the sources are added to



就像在您提供的 SO 链接中一样(与您的代码中相同),答案指向 BUILD_INTERFACEINSTALL_INTERFACE生成器表达式来解决包含目录的这个问题。一种可能的解决方案是更明确并在 target_sources() 中使用相同的表达式。
target_sources(Proj_LibA
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/liba.hpp>
        $<INSTALL_INTERFACE:include/liba.hpp>
    PRIVATE
        liba.cpp)

这可以说不是一个非常漂亮的解决方案,因为必须对每个头文件都这样做。另一种选择是简单地将您的标题移动到 PRIVATE范围。还有一种是使用PUBLIC_HEADER target 属性来定义您的 header 并指定安装目标,我实际上没有尝试过,但是 see this SO .

关于c++ - CMake 错误 - 目标 foo INTERFACE_SOURCES 属性包含源目录中前缀的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62348945/

相关文章:

c++ - SurfDescriptorExtractor/featureDetector - IOS 中的 OpenCv

c++ - std::vector.push_back() C++

java - 在图中寻找路径? (全局定位系统)?

c++ - CMakeLists 问题:在 thrust::device_vector 上调用 resize() 时出现 bad_alloc 错误

c++ - 使用 CLion IDE 运行 Opengl 程序

c++ - Box2D 创造世界

c++ - "library has no symbol"是什么意思?

c - 我如何在Windows中执行make file

c++11 - CMake FindThreads 与现代 C++ 的正确用途是什么?

CMake 使用 NASM 进行链接,但失败了。