INTERFACE_LINK_LIBRARIES_DIRECT — CMake 4.1.1 Documentation

# INTERFACE_LINK_LIBRARIES_DIRECT

Added in version 3.24.

List of libraries that consumers of this library should treat as direct link dependencies.

This target property may be set to include items in a dependent target's final set of direct link dependencies. See the `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target property to exclude items.

The initial set of a dependent target's direct link dependencies is specified by its `LINK_LIBRARIES` target property. Indirect link dependencies are specified by the transitive closure of the direct link dependencies' `INTERFACE_LINK_LIBRARIES` properties. Any link dependency may specify additional direct link dependencies using the `INTERFACE_LINK_LIBRARIES_DIRECT` target property. The set of direct link dependencies is then filtered to exclude items named by any dependency's `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target property.

The value of `INTERFACE_LINK_LIBRARIES_DIRECT` may use `generator expressions`.

Note

The `INTERFACE_LINK_LIBRARIES_DIRECT` target property is intended for advanced use cases such as injection of static plugins into a consuming executable. It should not be used as a substitute for organizing normal calls to `target_link_libraries()`.

## Direct Link Dependencies as Usage Requirements

The `INTERFACE_LINK_LIBRARIES_DIRECT` and `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties are usage requirements. Their effects propagate to dependent targets transitively, and can therefore affect the direct link dependencies of every target in a chain of dependent libraries. Whenever some library target `X` links to another library target `Y` whose direct or transitive usage requirements contain `INTERFACE_LINK_LIBRARIES_DIRECT` or `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`, the properties may affect `X`'s list of direct link dependencies:

- If `X` is a shared library or executable, its dependencies are linked. They also affect the usage requirements with which `X`'s sources are compiled.

- If `X` is a static library or object library, it does not actually link, so its dependencies at most affect the usage requirements with which `X`'s sources are compiled.

The properties may also affect the list of direct link dependencies on `X`'s dependents:

- If `X` links `Y` publicly:

      target_link_libraries(X PUBLIC Y)

  then `Y` is placed in `X`'s `INTERFACE_LINK_LIBRARIES`, so `Y`'s usage requirements, including `INTERFACE_LINK_LIBRARIES_DIRECT`, `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`, and the usage requirements declared by the direct link dependencies they add, are propagated to `X`'s dependents.

- If `X` is a static library or object library, and links `Y` privately:

      target_link_libraries(X PRIVATE Y)

  then `$<LINK_ONLY:Y>` is placed in `X`'s `INTERFACE_LINK_LIBRARIES`. `Y`'s linking requirements, including `INTERFACE_LINK_LIBRARIES_DIRECT`, `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`, and the transitive link dependencies declared by the direct link dependencies they add, are propagated to `X`'s dependents. However, `Y`'s non-linking usage requirements are blocked by the `LINK_ONLY` generator expression, and are not propagated to `X`'s dependents.

- If `X` is a shared library or executable, and links `Y` privately:

      target_link_libraries(X PRIVATE Y)

  then `Y` is not placed in `X`'s `INTERFACE_LINK_LIBRARIES`, so `Y`'s usage requirements, even `INTERFACE_LINK_LIBRARIES_DIRECT` and `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`, are not propagated to `X`'s dependents.

- In all cases, the content of `X`'s `INTERFACE_LINK_LIBRARIES` is not affected by `Y`'s `INTERFACE_LINK_LIBRARIES_DIRECT` or `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE`.

One may limit the effects of `INTERFACE_LINK_LIBRARIES_DIRECT` and `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` to a subset of dependent targets by using the `TARGET_PROPERTY` generator expression. For example, to limit the effects to executable targets, use an entry of the form:

    "$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:...>"

Similarly, to limit the effects to specific targets, use an entry of the form:

    "$<$<BOOL:$<TARGET_PROPERTY:USE_IT>>:...>"

This entry will only affect targets that set their `USE_IT` target property to a true value.

## Direct Link Dependency Ordering

The list of direct link dependencies for a target is computed from an initial ordered list in its `LINK_LIBRARIES` target property. For each item, additional direct link dependencies are discovered from its direct and transitive `INTERFACE_LINK_LIBRARIES_DIRECT` usage requirements. Each discovered item is injected before the item that specified it. However, a discovered item is added at most once, and only if it did not appear anywhere in the initial list. This gives `LINK_LIBRARIES` control over ordering of those direct link dependencies that it explicitly specifies.

Once all direct link dependencies have been collected, items named by all of their `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` usage requirements are removed from the final list. This does not affect the order of the items that remain.

## Example: Static Plugins

Consider a static library `Foo` that provides a static plugin `FooPlugin` to consuming application executables, where the implementation of the plugin depends on `Foo` and other things. In this case, the application should link to `FooPlugin` directly, before `Foo`. However, the application author only knows about `Foo`. We can express this as follows:

    # Core library used by other components.
    add_library(Core STATIC core.cpp)

    # Foo is a static library for use by applications.
    # Implementation of Foo depends on Core.
    add_library(Foo STATIC foo.cpp foo_plugin_helper.cpp)
    target_link_libraries(Foo PRIVATE Core)

    # Extra parts of Foo for use by its static plugins.
    # Implementation of Foo's extra parts depends on both Core and Foo.
    add_library(FooExtras STATIC foo_extras.cpp)
    target_link_libraries(FooExtras PRIVATE Core Foo)

    # The Foo library has an associated static plugin
    # that should be linked into the final executable.
    # Implementation of the plugin depends on Core, Foo, and FooExtras.
    add_library(FooPlugin STATIC foo_plugin.cpp)
    target_link_libraries(FooPlugin PRIVATE Core Foo FooExtras)

    # An app that links Foo should link Foo's plugin directly.
    set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT FooPlugin)

    # An app does not need to link Foo directly because the plugin links it.
    set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE Foo)

An application `app` only needs to specify that it links to `Foo`:

    add_executable(app main.cpp)
    target_link_libraries(app PRIVATE Foo)

The `INTERFACE_LINK_LIBRARIES_DIRECT` target property on `Foo` tells CMake to pretend that `app` also links directly to `FooPlugin`. The `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target property on `Foo` tells CMake to pretend that `app` did not link directly to `Foo`. Instead, `Foo` will be linked as a dependency of `FooPlugin`. The final link line for `app` will link the libraries in the following order:

- `FooPlugin` as a direct link dependency of `app` (via `Foo`'s usage requirements).

- `FooExtras` as a dependency of `FooPlugin`.

- `Foo` as a dependency of `FooPlugin` and `FooExtras`.

- `Core` as a dependency of `FooPlugin`, `FooExtras`, and `Foo`.

Note that without the `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target property, `Foo` would be linked twice: once as a direct dependency of `app`, and once as a dependency of `FooPlugin`.

## Example: Opt-In Static Plugins

In the above Example: Static Plugins, the `app` executable specifies that it links directly to `Foo`. In a real application, there might be an intermediate library:

    add_library(app_impl STATIC app_impl.cpp)
    target_link_libraries(app_impl PRIVATE Foo)

    add_executable(app main.cpp)
    target_link_libraries(app PRIVATE app_impl)

In this case we do not want `Foo`'s `INTERFACE_LINK_LIBRARIES_DIRECT` and `INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties to affect the direct dependencies of `app_impl`. To avoid this, we can revise the property values to make their effects opt-in:

    # An app that links Foo should link Foo's plugin directly.
    set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT
      "$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:FooPlugin>"
    )

    # An app does not need to link Foo directly because the plugin links it.
    set_property(TARGET Foo PROPERTY INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
      "$<$<BOOL:$<TARGET_PROPERTY:FOO_STATIC_PLUGINS>>:Foo>"
    )

Now, the `app` executable can opt-in to get `Foo`'s plugin(s):

    set_property(TARGET app PROPERTY FOO_STATIC_PLUGINS 1)

The final link line for `app` will now link the libraries in the following order:

- `FooPlugin` as a direct link dependency of `app` (via `Foo`'s usage requirements).

- `app_impl` as a direct link dependency of `app`.

- `FooExtras` as a dependency of `FooPlugin`.

- `Foo` as a dependency of `app_impl`, `FooPlugin`, and `FooExtras`.

- `Core` as a dependency of `FooPlugin`, `FooExtras`, and `Foo`.