It's referring to a header-only library whose sources you don't control or are found in another build tree / in the system. Will most commonly be created in a Find module or CMake package config module.

Like other imported targets, and unlike non-imported targets, it doesn't have to be (and indeed cannot be) install()-ed if it appears in the INTERFACE_LINK_LIBRARIES property of an install()ed target transitively; instead, the resulting package will need to find_dependency the package.

Answer from Alex Reinking on Stack Overflow
🌐
CMake
cmake.org › cmake › help › latest › command › add_library.html
add_library — CMake 4.3.0-rc3 Documentation
Added in version 3.12: Object libraries can be linked to with target_link_libraries(). ... Add an Interface Library target that may specify usage requirements for dependents but does not compile sources and does not produce a library artifact on disk.
🌐
CMake Discourse
discourse.cmake.org › usage
misunderstanding interface library? - Usage - CMake Discourse
January 5, 2022 - I thought, I could use an interface library as a virtual target which declares include directories and used libraries … So that a toolkit with several include directories and library entries becomes a one liner. I coded in toplevel CMakeLists.txt: add_library(IFOcct INTERFACE) target_inc...
Discussions

What is an INTERFACE IMPORTED library in CMake and what are its uses? - Stack Overflow
So far I've seen the INTERFACE library type used to describe header-only libraries, as it does not compile sources and does not produce library artifacts. The IMPORTED library type I've seen less o... More on stackoverflow.com
🌐 stackoverflow.com
How can I combine INTERFACE libraries with shared libraries?
I have a situation like this. add_library(lib INTERFACE) target_sources(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/lib.cpp") target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") Next, I want to create a shared library, which links to this library, so that all things from ... More on discourse.cmake.org
🌐 discourse.cmake.org
1
0
March 26, 2021
[question] How to use cmake interface library with target sources?
In my CMakeLists.txt I create an interface library, add sources to it and then link it to an executable. When I try to consume it I get lots of undefined references. CMakeLists.txt example: add_lib... More on github.com
🌐 github.com
17
January 24, 2022
Create & link interface library with cmake - Windows - Swift Forums
hello, is it possible to compile interface library only and target it in another "project" to make compilable by interface rules but without linking library physically? since windows swift cannot link static library, there is no need to link libraries defining protocol / base class / ... what ... More on forums.swift.org
🌐 forums.swift.org
0
June 7, 2021
🌐
CMake
cmake.org › cmake › help › latest › guide › tutorial › In-Depth CMake Library Concepts.html
Step 5: In-Depth CMake Library Concepts — CMake 4.3.0-rc3 Documentation
An Object Library: a collection of object files which have not been archived or linked into a library. ... An Interface Library: a library target which specifies usage requirements for dependents but does not compile sources and does not produce a library artifact on disk.
🌐
CMake Discourse
discourse.cmake.org › code
How can I combine INTERFACE libraries with shared libraries? - Code - CMake Discourse
March 26, 2021 - Hello. I have a situation like this. add_library(lib INTERFACE) target_sources(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/lib.cpp") target_include_directories(lib INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}") Next, I want …
🌐
GitHub
github.com › conan-io › conan › issues › 10413
[question] How to use cmake interface library with target sources? · Issue #10413 · conan-io/conan
January 24, 2022 - CMakeLists.txt example: add_library(MyLib INTERFACE) target_sources(MyLib INTERFACE util.cxx) add_executable(SomeTarget main.cxx) target_link_libraries(SomeTarget MyLib)
Author   werto87
🌐
CMake
cmake.org › cmake › help › latest › prop_tgt › INTERFACE_LINK_LIBRARIES.html
INTERFACE_LINK_LIBRARIES — CMake 4.3.0-rc3 Documentation
This property contains the list of transitive link dependencies. When the target is linked into another target using the target_link_libraries() command, the libraries listed (and recursively their link interface libraries) will be provided to the other target also.
Find elsewhere
🌐
CMake
cmake.org › cmake › help › v3.5 › command › add_library.html
add_library — CMake 3.5.2 Documentation
The <name> may not be used to modify properties of <target>, that is, it may not be used as the operand of set_property(), set_target_properties(), target_link_libraries() etc. An ALIAS target may not be installed or exported. ... Creates an Interface Library.
🌐
CMake
cmake.org › cmake › help › v3.4 › command › add_library.html
add_library — CMake 3.4.3 Documentation
The <name> may not be used to modify properties of <target>, that is, it may not be used as the operand of set_property(), set_target_properties(), target_link_libraries() etc. An ALIAS target may not be installed or exported. ... Creates an Interface Library.
🌐
Lei Mao's Log Book
leimao.github.io › blog › CMake-Public-Private-Interface
CMake: Public VS Private VS Interface - Lei Mao's Log Book
April 28, 2024 - Note that when we do target_link_libraries(<target> <PRIVATE|PUBLIC|INTERFACE> <item>), the dependent <item>, if built in the same CMake project, would append the INTERFACE_INCLUDE_DIRECTORIES of <item> to the INCLUDE_DIRECTORIES of <target>. By controlling the INTERFACE_INCLUDE_DIRECTORIES, we could eliminate some unwanted or conflicting declarations from <item> to the <target>.
🌐
Gitlab
cliutils.gitlab.io › modern-cmake › chapters › basics.html
Introduction to the basics — Modern CMake
PUBLIC doesn’t mean much for an executable; for a library it lets CMake know that any targets that link to this target must also need that include directory. Other options are PRIVATE (only affect the current target, not dependencies), and INTERFACE (only needed for dependencies).
🌐
Swift Forums
forums.swift.org › platform › windows
Create & link interface library with cmake - Windows - Swift Forums
June 7, 2021 - hello, is it possible to compile interface library only and target it in another "project" to make compilable by interface rules but without linking library physically? since windows swift cannot link static library, there is no need to link libraries defining protocol / base class / ... what i have discovered so far is the only option to build library: add_library(BLA SHARED librarySource.swift) -> dll, lib, swiftmodule (interface i quess) and consumer links dynamic only this way: add_lib...
🌐
Reddit
reddit.com › r/learnprogramming › cmake: what is a link interface? not understanding difference between stipulating public, private and interface when using target_link_libraries()
r/learnprogramming on Reddit: CMake: What is a link interface? Not understanding difference between stipulating PUBLIC, PRIVATE and INTERFACE when using target_link_libraries()
June 21, 2021 -

Per target_link_libraries :

The PUBLIC, PRIVATE and INTERFACE keywords can be used to specify both the link

dependencies and the link interface in one command. Libraries and targets following

PUBLIC are linked to, and are made part of the link interface. Libraries and

targets following PRIVATE are linked to, but are not made part of the link interface.

Libraries following INTERFACE are appended to the link interface and are not used

for linking <target>.

I am not understanding what is being meant by "the link interface". Is anyone able to explain it to me?

Thanks

Top answer
1 of 1
2
If I write a library foo, then "the link interface" is the list of libraries you need to link to in order to use foo in your target. Let's say you are writing a network library. For some feature of your library, you are storing stuff in a red-black tree. So you either find or write a rbtree library. This is an implementation detail. Your network library needs to link to rbtree, but people linking to network don't need to know anything about rbtree. So, we would say that rbtree is a PRIVATE dependency, and it is NOT part of the link interface. Now let's say that your network library also depends on a lower level socket library. Users of your network library are expected to know about and interact with stuff from the socket library. Here, we would say that socket is a PUBLIC dependency, and it is part of the link interface. That is, you need to link socket when you are building network, and you ALSO need to link it when building anything that depends on network. So, INTERFACE is sort of the halfway point there. I am having difficulty contriving an example at the moment. But imagine there is some library that users of network need to link, but network itself does not need in order to build. This would be an INTERFACE dependency. The most obvious example I can think of for this would be if a portion of your network library was all written with templates, and thus header only. Anything those headers depend on would need to be part of the link interface, but wouldn't be needed to build network.
🌐
Apache Mesos
mesos.apache.org › documentation › latest › cmake-examples
Apache Mesos - CMake By Example
Its include directory is specified as an INTERFACE (the PUBLIC property cannot be used as the library itself is just an interface). Its “link” dependencies (despite not being a real, linkable library) are specified as an INTERFACE. This notion of an interface in the CMake dependency graph is what makes the build system reasonable.
Top answer
1 of 3
38

try this:

cmake_minimum_required(VERSION 3.7)

project(mylib VERSION 0.1 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 14)
#add_compile_options(-Wa -aslh)


# Define the library target
add_library(mylib INTERFACE)
target_include_directories(mylib INTERFACE 
    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
    $<INSTALL_INTERFACE:include>
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "${PROJECT_BINARY_DIR}/mylibConfigVersion.cmake"
    VERSION 0.1
    COMPATIBILITY AnyNewerVersion
)

install(TARGETS mylib
    EXPORT mylibTargets
    LIBRARY DESTINATION lib COMPONENT Runtime
    ARCHIVE DESTINATION lib COMPONENT Development
    RUNTIME DESTINATION bin COMPONENT Runtime
    PUBLIC_HEADER DESTINATION include COMPONENT Development
    BUNDLE DESTINATION bin COMPONENT Runtime
)

include(CMakePackageConfigHelpers)
configure_package_config_file(
    "${PROJECT_SOURCE_DIR}/cmake/mylibConfig.cmake.in"
    "${PROJECT_BINARY_DIR}/mylibConfig.cmake"
    INSTALL_DESTINATION lib/cmake/mylib
)

install(EXPORT mylibTargets DESTINATION lib/cmake/mylib)
install(FILES "${PROJECT_BINARY_DIR}/mylibConfigVersion.cmake"
              "${PROJECT_BINARY_DIR}/mylibConfig.cmake"
        DESTINATION lib/cmake/mylib)
install(DIRECTORY ${PROJECT_SOURCE_DIR}/include/ DESTINATION include)


add_executable(mytest test/basic_checks.cpp)
target_link_libraries(mytest mylib)

the content of cmake/mylibConfig.cmake.in should only be this

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/mylibTargets.cmake")
check_required_components("@PROJECT_NAME@")

if you do all of this, not only that it makes your header-only library 'installable', but it also makes it 'findable'. users will be able to import your library like so:

find_package(mylib CONFIG REQUIRED)
target_link_libraries(MyApp mylib) # installed include/ path automatically added
2 of 3
4

In my case the headers were contained in multiple sub directories and I simply wanted to map them to the install directory and preserve the relative file structure. I gathered from reading here that file sets are the preferred way to do this since cmake version 3.23.

This is the code I used to build the library...

cmake_minimum_required(VERSION 3.23.1)
include_guard(GLOBAL)
project(headerlib-proj VERSION 0.0.0 LANGUAGES C)
include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

add_library(mylib INTERFACE)

target_include_directories(mylib
        INTERFACE
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

target_sources(mylib
        INTERFACE FILE_SET HEADERS
        BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}
        FILES myHeader.h)

install(TARGETS mylib
        EXPORT mylibTargets
        FILE_SET HEADERS DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mylib)

install(EXPORT mylibTargets
        FILE mylibConfig.cmake
        NAMESPACE MyNamespace::
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib)

install(FILES
        ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/mylibTargetsVersion.cmake
        DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib)

export(EXPORT mylibTargets
        FILE ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake
        NAMESPACE MyNamespace::)

configure_package_config_file(
        ${CMAKE_CURRENT_SOURCE_DIR}/mylibConfig.cmake.in
        ${CMAKE_CURRENT_BINARY_DIR}/mylibConfig.cmake
        INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mylib)

write_basic_package_version_file(
        ${PROJECT_BINARY_DIR}/mylibTargetsVersion.cmake
        VERSION 1.0.0
        COMPATIBILITY SameMajorVersion)

And the client...

cmake_minimum_required(VERSION 3.23)
project(master-proj LANGUAGES CXX)

find_package(mylib CONFIG REQUIRED)

add_executable(myProgram)
target_link_libraries(myProgram PRIVATE MyNamespace::mylib)
target_sources(myProgram PRIVATE main.cpp)
🌐
GitHub
github.com › conan-io › conan › issues › 8222
[question] Packaging cmake INTERFACE libraries · Issue #8222 · conan-io/conan
November 11, 2020 - CMake uses the notion of INTERFACE library : An Interface library does not compile sources and does not produce a library artifact on disk. However, it may have properties set on it and it may be i...
Author   GPages
Top answer
1 of 2
36

When you create an imported target, you're telling CMake: I have this { static library | shared library | module library | executable } already built in this location on disk. I want to be able to treat it just like a target built by my own buildsystem, so take note that when I say ImportedTargetName, it should refer to that binary on disk (with the associated import lib if applicable, and so on).

When you create an interface library, you're telling CMake: I have this set of properties (include directories etc.) which clients can use, so if they "link" to my interface library, please propagate these properties to them.

The fundamental difference is that interface libraries are not backed by anything on disk, they're just a set of requirements/properties. You can set the INTERFACE_LINK_LIBRARIES property on an interface library if you really want to, but that's not really what they were designed for. They're to encapsulate client-consumable properties, and make sense primarily for things like header-only libraries in C++.

Also notice that an interface library is a library—there's no such thing as an interface executable, but you can indeed have imported executables. E.g. a package config file for Bison could define an imported target for the Bison executable, and your project could then use it for custom commands:

# 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
  ...
)

(Bison is used just as an example of something you might want to use in custom commands, and the command line is probably not right for it).

2 of 2
20

It seems like there is a lot of overlap. Say you have a shared library and headers on disk and you want to make it available so that bits of your CMake can do this

target_link_libraries(my_target foo)

and automatically link with it and get the necessary include directories.

You can do it either like this:

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"
)

Or like this:

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")

They both work and behave identically as far as I can tell. There is even an 'imported interface library' available via add_library(foo INTERFACE IMPORTED) though that didn't seem to work and I have no idea what it is for.

Frankly the docs don't really explain which you should use for libraries, and I'm afraid I don't find Angew's "that's not really what they were designed for" very compelling.

I guess use either. I think the interface library is easier to understand and more consistent with the use of INTERFACE properties from internal libraries.

🌐
CMake Discourse
discourse.cmake.org › code
Should cmake install an INTERFACE library when linked as PRIVATE dependency ? - Code - CMake Discourse
August 18, 2023 - Hi folks, I’m having a hard time understanding how cmake should behave regarding installation of dependencies added with FetchContent so I’m sorry if this is a noob question, but I couldn’t find a satisfying answer so far. I’m working with the C++ library xsimd and we’re having a ...