# How to consume usage requirements of a target without exporting LINK\_ONLY

**URL:** https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352
**Category:** Usage
**Created:** [July 30, 2024, 12:44pm UTC](https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352 "2024-07-30T12:44:01Z")
**Posts on this page:** 4
**Page:** 1

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [July 30, 2024, 12:44pm UTC](https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352/1 "2024-07-30T12:44:01Z")

</div>

Hi,

I have the following sample project.

```cmake
cmake_minimum_required(VERSION 3.21)
project(proj LANGUAGES CXX)

include(GNUInstallDirs)

set(source_file "${CMAKE_CURRENT_BINARY_DIR}/lib.cpp")
file(WRITE "${source_file}" "int foo() {return 0;}")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/utils")

add_library(Core SHARED "${source_file}")
target_include_directories(Core PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/utils>")
target_compile_definitions(Core PUBLIC "FEATURE1=ON")
target_compile_features(Core PUBLIC "cxx_std_23")
target_compile_options(Core PUBLIC "-Wall")

add_library(Gui STATIC "${source_file}")

# (1)
#target_link_libraries(Gui PRIVATE Core)

# This causes the ToolkitTargets.cmake file to contain
#set_target_properties(Toolkit::Gui PROPERTIES
  #INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:Core>"
#)

# (2)
#target_link_libraries(Gui PRIVATE $<LINK_ONLY:Core>)

# This causes the ToolkitTargets.cmake file to contain
#set_target_properties(Toolkit::Gui PROPERTIES
  #INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:\$<LINK_ONLY:Core>>"
#)

#(3) This achieves the desired effect, but is verbose and might not cover everything?
target_include_directories(Gui PRIVATE "$<TARGET_PROPERTY:Core,INTERFACE_INCLUDE_DIRECTORIES>")
target_compile_definitions(Gui PRIVATE "$<TARGET_PROPERTY:Core,INTERFACE_COMPILE_DEFINITIONS>")
target_compile_features(Gui PRIVATE "$<TARGET_PROPERTY:Core,INTERFACE_COMPILE_FEATURES>")
target_compile_options(Gui PRIVATE "$<TARGET_PROPERTY:Core,INTERFACE_COMPILE_OPTIONS>")

install(TARGETS Core Gui
    EXPORT ToolkitTargets
    BUNDLE DESTINATION .
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(EXPORT ToolkitTargets
    NAMESPACE Toolkit::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Toolkit
)

```

```auto
$ cmake .. -DCMAKE_INSTALL_PREFIX=$PWD/installed -GNinja && ninja install

```

I would like to consume the usage requirements of the `Core` shared lib when building the `Gui` static lib, but not export the `$<LINK_ONLY:Core>` requirement in the installed `ToolkitTargets.cmake` file for the `Gui` static lib, so that user projects that consume `Gui` don’t need to link to the `Core` target.

By consuming the usage requirements, I mean make sure `Core`’s compile definitions, compile features, include paths, etc are used when building `Gui`’s sources.

The explicit link requirement is not needed, because `Core` will be dynamically loaded using `dlopen()` by `Gui`’s sources at an appropriate time.

I think I can achieve that using approach (3) as described in the project comment.

(1) and (2) don’t work because of `$<LINK_ONLY:Core>` being automatically added to `Gui`’s `INTERFACE_LINK_LIBRARIES`.

I don’t like (3) because i’m not sure if it covers everything, and because in the future CMake might introduce new types of usage requirements.

Ideally I’d use something like (1), perhaps with a new generator expression like

```cmake
target_link_libraries(Gui PRIVATE $<CONSUME_COMPILE_USAGE_REQUIREMENTS:Core>)

```

Does something like that exist already? Is there a better way of achieving what I want?

Thank you.

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [July 30, 2024, 10:18pm UTC](https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352/2 "2024-07-30T22:18:39Z")

</div>

Does the `$<BUILD_LOCAL_INTERFACE:...>` generator expression give you what you’re looking for? It is available with CMake 3.26 and later.

---

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [July 31, 2024, 9:15am UTC](https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352/3 "2024-07-31T09:15:34Z")

</div>

It seems so, but with a caveat.

When I use

```cmake
target_link_libraries(Gui PRIVATE $<BUILD_LOCAL_INTERFACE:Core>)

```

The exported file contains the following:

```cmake
# Create imported target Toolkit::Gui
add_library(Toolkit::Gui STATIC IMPORTED)

set_target_properties(Toolkit::Gui PROPERTIES
  INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:>"
)

```

I tried linking to this target in a separate project, and the `"\$<LINK_ONLY:>` didn’t seem to break anything, and the project built successfully, but it’s not unreasonable to think that a future CMake version might error out due to the empty value passed to `$<LINK_ONLY:>`.

I suppose this might be an oversight when `$<BUILD_LOCAL_INTERFACE:>` was implemented.

---

<div class="post-metadata">

### Author: ![alcroito](https://discourse.cmake.org/user_avatar/discourse.cmake.org/alcroito/32/186_2.png) [@alcroito](https://discourse.cmake.org/u/alcroito)
#### Post date: [July 31, 2024, 9:33am UTC](https://discourse.cmake.org/t/how-to-consume-usage-requirements-of-a-target-without-exporting-link-only/11352/4 "2024-07-31T09:33:05Z")

</div>

Filed [https://gitlab.kitware.com/cmake/cmake/-/issues/26181](https://gitlab.kitware.com/cmake/cmake/-/issues/26181)
