# LINK\_LIBRARY generator expression with WHOLE\_ARCHIVE doesn't work with exported/imported targets

**URL:** https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448
**Category:** Usage
**Tags:** os:linux
**Created:** [January 8, 2026, 8:39pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448 "2026-01-08T20:39:42Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 8, 2026, 8:39pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/1 "2026-01-08T20:39:42Z")

</div>

## **Context of the Problem**

We are creating a DPDK package using CMake that exports targets with a namespace prefix (e.g., `dpdk::libeal`, `dpdk::libmempool_ring`). Some DPDK libraries (for example, `mempool_ring` and `mempool_stack`) require linking with the `--whole-archive` flag (or `-Wl,--whole-archive`), otherwise symbols from these libraries are not included in the final executable.

## **The Problem**

We are trying to use the CMake generator expression `$<LINK_LIBRARY:WHOLE_ARCHIVE,...>`, but it doesn’t work properly for exported targets:

1. **When using local target names (before export):**

2. **When using** `$<TARGET_NAME:...>` **:**

## **Expected Behavior**

When linking, something like this should be generated:

text

```auto
-Wl,--whole-archive /path/to/librte_mempool_ring.a -Wl,--no-whole-archive

```

## **Actual Behavior**

1. In the first case, an incorrect linker flag is generated: `-llibmempool_ring`

2. In the second case, only the library path is generated without the `--whole-archive` flags

## **Questions**

1. How to properly use `$<LINK_LIBRARY:WHOLE_ARCHIVE,...>` for targets that will be exported with a namespace prefix?

2. Is there a workaround for this issue in current CMake versions (4.2.1)?

3. Is this a known issue/limitation in CMake?

## **CMake Version and Environment**

- CMake 4.2.1 (minimum version 3.30 specified in the project)

- Compiler: GCC/G++

- Linker: GNU ld or gold

- OS: Linux

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [January 8, 2026, 9:55pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/2 "2026-01-08T21:55:56Z")

</div>

Your explanations are not clear enough. Please, provide a snippet showing the problem.

---

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 12, 2026, 10:41pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/3 "2026-01-12T22:41:22Z")

</div>

I’m building DPDK via `ExternalProject`, then creating CMake targets for all libraries, but I can’t get `--whole-archive` to work properly when linking in the final project.

1. Building DPDK via `ExternalProject`:

```auto
externalproject_add(dpdk_build ...)

```

1. Creating dummy targets for all DPDK libraries:

```auto
foreach(lib ${ALL_LIBS})
    add_library(${lib} STATIC EXCLUDE_FROM_ALL "${STUB_C}")
    # Setting properties...
endforeach()

```

1. Attempts to add whole-archive (tried 3 methods):

**Method 1:** In the list of libraries in a group:

```auto
set(_LIBS
    "lib1"
    "-Wl,--whole-archive"
    "lib2" # Should be in whole-archive
    "lib3" # Should be in whole-archive  
    "-Wl,--no-whole-archive"
)

```

**Problem:** The flags appear separately from the libraries in the link command line.

**Method 2:** Using `LINK_LIBRARY` with `TARGET_NAME`:

```auto
target_link_libraries(lib2 INTERFACE 
    "$<LINK_LIBRARY:WHOLE_ARCHIVE,$<TARGET_NAME:lib2>>"
)

```

**Result:** Library paths are substituted correctly, but the `--whole-archive` flag does not appear during linking.

**Method 3:** Using `LINK_LIBRARY` without `TARGET_NAME`:

```auto
target_link_libraries(lib2 INTERFACE
    "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib2>"
)

```

**Result:**  **The** `--whole-archive` flag appears in the command line, but CMake tries to link with `-llib2` instead of using the library file path. It doesn’t use the target `lib2`, but tries to find the library by name in standard paths.

1. **Grouping libraries** :

```auto
add_library(core_libs INTERFACE)
foreach(lib ${CORE_LIBS})
    target_link_libraries(core_libs INTERFACE ${lib})
endforeach()

```

1. **In the consuming project** :

```auto
target_link_libraries(my_app dpdk::core_libs)

```

### **Paradoxical Situation**

It turns out that in methods 2 and 3, different things work, but not together:

- **Method 2:** Correct library paths, but no `--whole-archive`

- **Method 3:** Has `--whole-archive`, but incorrect paths (uses `-l` instead of absolute paths)

Here’s what the link commands look like:

**Method 2:**

```auto
# Paths are correct, but no whole-archive
/path/to/librte_net_af_packet.a /path/to/librte_net_bnx2x.a ...

```

**Method 3:**

```auto
# Has whole-archive, but link is incorrect
-Wl,--whole-archive -lrte_net_af_packet -Wl,--no-whole-archive ...

```

##

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [January 13, 2026, 10:16am UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/4 "2026-01-13T10:16:00Z")

</div>

`$<LINK_LIBRARY>` generator expression is not supported and will be ignored when specified on an `INTERFACE` library type, as clearly specify in the [documentation](https://cmake.org/cmake/help/latest/manual/cmake-generator-expressions.7.html#link-features), under the sub-title `The following limitations should be noted:`.

---

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 13, 2026, 7:52pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/6 "2026-01-13T19:52:03Z")

</div>

How can I configure an exported target (static library) so that when it’s imported, it links with the whole-archive attribute? It’s not correct to maintain this option in projects. I would like consumers to simply specify the dependency as:

```auto
target_link_libraries(my_app 
    dpdk::core_libs 
    dpdk::pmds
)

```

If I use PUBLIC instead of INTERFACE in the package build script:

```auto
target_link_libraries(lib2 PUBLIC 
    "$<LINK_LIBRARY:WHOLE_ARCHIVE,$<TARGET_NAME:lib2>>"
)

```

The problem occurs at the configuration stage - error: the library cannot link to itself.

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [January 13, 2026, 9:40pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/7 "2026-01-13T21:40:21Z")

</div>

You cannot do that. The link features, defined by the genex `$<LINK_LIBRARY>`, must be specified by the consumer, not the producer.

---

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 14, 2026, 1:47am UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/8 "2026-01-14T01:47:16Z")

</div>

DPDK consists of (2-)300+ libraries. Some of them require linking with specific flags. They also have interdependencies. All drivers must be linked with `whole-archive`, otherwise the linker completely discards the driver code. Some libraries require linking with this and other flags.

We have over 40 modules, each linked with its own list of DPDK libraries.  
5 projects.  
At this scale, maintaining and verifying the correctness of linking is a very labor-intensive task, and there have been many bugs. Therefore, an attempt was made at this refactoring…

Is it possible to submit a feature request, please? In any form, so that we can manage linking parameters and the consumer wouldn’t even need to know that some of the libraries they import into their project require special linking?

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [January 14, 2026, 9:54am UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/9 "2026-01-14T09:54:40Z")

</div>

You can use this pattern:

```cmake
add_library(lib STATIC ...)

add_library(w_lib INTERFACE)
target_link_libraries(w_lib INTERFACE "$<LINK_LIBRARY:WHOLE_ARCHIVE,lib>")

add_executable(main ...)
target_link_libraries(main PRIVATE w_lib)

```

---

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 16, 2026, 9:20pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/10 "2026-01-16T21:20:17Z")

</div>

It looks like it should work, but it doesn’t:

**dpdkTargets.cmake:**

```cmake
...
# Create imported target dpdk::libmempool_ring
add_library(dpdk::libmempool_ring STATIC IMPORTED)

set_target_properties(dpdk::libmempool_ring PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "\$<LINK_LIBRARY:WHOLE_ARCHIVE,dpdk::libmempool_ring>;dpdk::libeal;dpdk::libmempool"
)
...

```

When imported into a project and linked, the resulting link command looks like this:

```bash
/sbin/c++ ... /home/pavard/.build-Linux-x86_64/dpdk-25.11/lib/librte_mempool_ring.a ...

```

Without the necessary arguments.

Tried manually removing the escape backslash before `$` – didn’t help.

---

<div class="post-metadata">

### Author: ![marc.chevrier](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/m/ecb155/32.png) [@marc.chevrier](https://discourse.cmake.org/u/marc.chevrier)
#### Post date: [January 17, 2026, 12:02pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/11 "2026-01-17T12:02:25Z")

</div>

As I already said: you cannot specify the `$<LINK_LIBRARY>` on the producer. Moreover, you specify to link `dpdk::libmempool_ring` to itself by specifying `$<LINK_LIBRARY:WHOLE_ARCHIVE,dpdk::libmempool_ring>` as part of libraries linked to `dpdk::libmempool_ring`.

---

<div class="post-metadata">

### Author: ![pavard](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/p/b5e925/32.png) [@pavard](https://discourse.cmake.org/u/pavard)
#### Post date: [January 17, 2026, 9:29pm UTC](https://discourse.cmake.org/t/link-library-generator-expression-with-whole-archive-doesnt-work-with-exported-imported-targets/15448/12 "2026-01-17T21:29:02Z")

</div>

My mistake: mempool\_ring is part of the drivers list, not the libraries list. Consequently, I was experimenting with the wrong list. Your approach worked, but $\<TARGET\_NAME:\> still needs to be written there. Thank you very much for your help.
