IMPORTED目标和INTERFACE库之间有什么区别?

Ben*_*inB 17 cmake

据我所知,INTERFACE库就像Visual Studio属性表,非常有用.我们可以使用它来链接静态库并传播属性.

IMPORTED目标让我困扰:我无法看到只能通过IMPORTED目标解决的问题.

Rei*_*ica 18

当你创建一个导入的目标时,你告诉CMake:我有这个{静态库| 共享库| 模块库| 已经在磁盘上的这个位置构建的可执行文件.我希望能够将它视为由我自己的构建系统构建的目标,所以请注意,当我说ImportedTargetName,它应该引用磁盘上的二进制文件(如果适用,使用相关的导入库,依此类推).

当你创建一个接口库时,你告诉CMake:我有一组客户端可以使用的属性(包括目录等),所以如果它们"链接"到我的接口库,请将这些属性传播给它们.

根本区别在于接口库没有磁盘上的任何东西支持,它们只是一组需求/属性.您可以设置INTERFACE_LINK_LIBRARIES在接口库财产,如果你真的想,但是这不是真的是他们设计的.它们是封装客户端可使用的属性,主要用于C++中仅包含头文件库的内容.

另请注意,接口库是一个 - 不存在接口可执行文件,但您确实可以导入可执行文件.例如,Bison的包配置文件可以为Bison可执行文件定义导入的目标,然后您的项目可以将其用于自定义命令:

# In Bison package config file:
add_executable(Bison IMPORTED)
set_property(TARGET Bison PROPERTY IMPORTED_LOCATION ...)

# In your project:
find_package(Bison)
add_custom_command(
  OUTPUT parser.c
  COMMAND Bison tab.y -o parser.c
  DEPENDS tab.y
  ...
)
Run Code Online (Sandbox Code Playgroud)

(Bison仅用作您可能希望在自定义命令中使用的示例,并且命令行可能不适合它).


Tim*_*mmm 8

似乎有很多重叠.假设您在磁盘上有一个共享库和标题,并且您希望它可用,以便您的CMake位可以执行此操作

target_link_libraries(my_target foo)
Run Code Online (Sandbox Code Playgroud)

并自动链接获取必要的包含目录.

你可以这样做:

find_package(Foo)

add_library(foo SHARED IMPORTED)
set_target_properties(foo PROPERTIES
    IMPORTED_LOCATION ${FOO_LIBRARIES} # The DLL, .so or .dylib
    INTERFACE_INCLUDE_DIRECTORIES ${FOO_INCLUDE_DIR}
    INTERFACE_COMPILE_DEFINITIONS "ENABLE_FOO"
)
Run Code Online (Sandbox Code Playgroud)

或者像这样:

add_library(foo INTERFACE)
target_link_libraries(foo INTERFACE ${FOO_LIBRARIES})
target_include_directories(foo INTERFACE ${FOO_INCLUDE_DIR})
target_compile_definitions(foo INTERFACE "-DENABLE_FOO")
Run Code Online (Sandbox Code Playgroud)

就我所知,他们的工作和行为完全相同.甚至还有一个"导入的接口库" add_library(foo INTERFACE IMPORTED)虽然看起来不起作用但我不知道它的用途.

坦率地说,这些文档并没有真正解释你应该为图书馆使用哪些文件,而且我担心我没有找到Angew的"那不是它们的设计目的"非常引人注目.

我想也要用.我认为接口库更容易理解,并且与INTERFACE内部库的属性的使用更加一致.