# proper way to wrap an imported target around a third-party target

**URL:** https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757
**Category:** Usage
**Created:** [February 12, 2021, 4:06pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757 "2021-02-12T16:06:58Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [February 12, 2021, 4:06pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/1 "2021-02-12T16:06:58Z")

</div>

Hi,

I’m trying to enforce namespace usage for imported libraries.  
For third-party libraries that can be imported through find\_package but the don’t provide a namespace, I tried to wrap them in a namespace (see attached file)  
I have the following situation:  
application depends privately on a home-made (static)library which depends privately on a third-party library . When declaring dependency to in , I wrap it into third::third.  
on CMake 3.19.2 it works fine  
on CMake 3.5.1 (that I must support as it is the default version on Ubuntu 16.04), when configuring , I have the following error: Target “client” links to target “third::third” but the target was not found…

Why the difference in behaviour and would it be possible to have a “clean” workaround?

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 12, 2021, 5:10pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/2 "2021-02-12T17:10:10Z")

</div>

I don’t see an attached file (though the spam filter may have blocked it since you appear to be a new user). A GitHub Gist or other hosting service might suffice in the meantime. I don’t think there’s enough info without that to surmise what is going wrong.

> [@adaldev](#):
>
> on CMake 3.5.1 (that I must support as it is the default version on Ubuntu 16.04),

Hrm. It seems that they don’t provide backports for Xenial’s CMake. I would recommend that you suggest downloading a newer CMake from the prebuilt binaries if possible.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [February 15, 2021, 6:17pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/3 "2021-02-15T18:17:40Z")

</div>

I indeed cannot upload. It’s not long though. I post it directly:

```cmake
# MyLib CMakeLists

...

find_package(third REQUIRED)
# Work around for third-party package that don't use namespace
IF(third_FOUND AND NOT TARGET third::third)
	add_library(third::third UNKNOWN IMPORTED)
	set_target_properties(third::third PROPERTIES
	IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
		IMPORTED_LOCATION "${third_LIBRARY}"
		INTERFACE_INCLUDE_DIRECTORIES "${third_INCLUDE_DIR}"
		)
ENDIF()
target_link_libraries(${TARGET_NAME} PRIVATE third::third)

# Then export and install mylib::mylib

...

# client CMakeLists

find_package(mylib REQUIRED)
target_link_libraries(${TARGET_NAME} PRIVATE mylib::mylib)

```

I cannot rely on recent versions of CMake as I’ve still got users with 3.5.1 that may not be able to switch to newer version.

regards

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 15, 2021, 6:22pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/4 "2021-02-15T18:22:18Z")

</div>

Hmm. I am guessing that CMake 3.5.1 did not prune target references properly or something. In your `mylib-config.cmake` file, you’ll need similar logic around a `find_package(third)`.

```cmake
include(CMakeFindDependencyMacro)
find_dependency(third)
if (NOT third_FOUND)
  set(mylib_FOUND 0)
  list(APPEND mylib_NOT_FOUND_REASON "third party dependency not found: ${third_NOT_FOUND_REASON}")
  # Possibly other logic.
else ()
  # make third::third if needed.
endif ()

```

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [February 15, 2021, 6:29pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/5 "2021-02-15T18:29:08Z")

</div>

Thanks,

I’m afraid I did not understand properly the role of mylib-config.cmake. Do I have to write again the add\_library/set\_target\_properties parts in this file?

By the way, i’d appreciate a pointer on the exact function of this config file.

regards

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [February 15, 2021, 6:49pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/6 "2021-02-15T18:49:45Z")

</div>

No, your targets are there via `install(EXPORT)` (for the install tree) and/or `export(EXPORT)` (for the build tree) commands in your project. What those lines do _not_ do is make an `IMPORTED` targets you had available (e.g., because they may have paths that are build-machine specific and not useful on another machine).

The `mylib-config.cmake` file is there to implement the logic of `find_package(mylib)`. There is a module for doing the bare minimum, but if you have anything “extra” going on like dependent imported targets, a CMake API to provide, or logic for components, then you’re basically stuck with writing it yourself.

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [March 5, 2021, 5:16pm UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/7 "2021-03-05T17:16:14Z")

</div>

Hi,

I looked more precisely at the answers above and I’m still confused.

I have actually several use-cases.

Let’s call “mylib” my own library that I export as mylib::mylib (so far, everything is OK)

I’d like to declare a dependency to a third party library “third” that is detectable through find\_package.

1. third::third exists  
my cmakelist.txt contains:

```cmake
find_package(third REQUIRED)
target_link_libraries(mylib <whatever> third::third)
list(APPEND DEP third)
configure_file(<Path to MyLibConfig.cmake> MyLibConfig.cmake @ONLY)

```

my mylibConfig.cmake contains:

```cmake
include(CMakeFindDependencyMacro)
foreach(_lib_ IN ITEMS @DEP@)
	find_dependency(${_lib_} REQUIRED)
endforeach()

# include the generated target file
include("${CMAKE_CURRENT_LIST_DIR}/@TARGET_NAME@Targets.cmake")

```

everything is fine

1. third namespace exists but the exported target has a differente name third::third\_other (it happens for instance with Eigen that exports Eigen3::Eigen and not Eigen3::Eigen3)  
my cmakelist.txt contains:

```cmake
find_package(third REQUIRED)
target_link_libraries(mylib <whatever> third::third_other)
list(APPEND DEP third)
configure_file(<Path to MyLibConfig.cmake> MyLibConfig.cmake @ONLY)

```

my mylibConfig.cmake contains:

```cmake
include(CMakeFindDependencyMacro)
foreach(_lib_ IN ITEMS @DEP@)
	find_dependency(${_lib_} REQUIRED)
endforeach()

# include the generated target file
include("${CMAKE_CURRENT_LIST_DIR}/@TARGET_NAME@Targets.cmake")

```

It still works but I don’t understand why as the name third\_other does not seem to be propagated through my MyLibConfig.cmake

1. third namespace exists but there is no target third::xxx (for instance OpenCV)  
I tried to wrap it in my cmakelist as mentioned in a previous message but it does not work as the wrapped target is not propagate properly with my mylibConfig.cmake (If I understood you correctly)  
should I copy my wrapping from the cmakelist to the mylibConfig.cmake file (in pseudo-code):

```cmake
include(CMakeFindDependencyMacro)
foreach(_lib_ IN ITEMS @DEP@)
	find_dependency(${_lib_} REQUIRED)
	IF(${_lib_}_FOUND AND NOT TARGET ${_lib_}::${_lib_})
		add_library(${_lib_}::${_lib_} UNKNOWN IMPORTED)
		set_target_properties(${_lib_}::${_lib_} PROPERTIES
			IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
			IMPORTED_LOCATION "${${_lib_}_LIBRARIES}"
			INTERFACE_INCLUDE_DIRECTORIES "${${_lib_}_INCLUDE_DIRS}"
			)

endforeach()

```

So far I found only two unsatisfying solutions:  
first one:  
my cmakelist.txt contains:

```cmake
find_package(third REQUIRED)
target_include_directories(mylib <whatever> third_INCLUDE_DIRS)
target_link_libraries(mylib <whatever> third_LIBRARIES)
list(APPEND DEP third)
configure_file(<Path to MyLibConfig.cmake> MyLibConfig.cmake @ONLY)

```

my mylibConfig.cmake is unchanged

second one:  
I create a Findthird.cmake file that looks for third locations and finishes with:

```cmake
IF(third_FOUND AND NOT TARGET third::third)
add_library(third::third UNKNOWN IMPORTED)
set_target_properties(third::third PROPERTIES
	IMPORTED_LINK_INTERFACE_LANGUAGES "CXX"
	IMPORTED_LOCATION "${third_LIBRARIES}"
	INTERFACE_INCLUDE_DIRECTORIES "${third_INCLUDE_DIRS}"
	)
ENDIF()

```

but both solution create a dependency to all submodules in “third” (see point 4 below).

1. how to declare dependency only to a submodule of “third” for each use-case above? (for instance, using only opencv\_superres and not all OpenCV libraries

It’s a long post with many questions in one but I hope it will make the problem clearer.

Regards

---

<div class="post-metadata">

### Author: ![adaldev](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/9dc877/32.png) [@adaldev](https://discourse.cmake.org/u/adaldev)
#### Post date: [May 17, 2021, 8:47am UTC](https://discourse.cmake.org/t/proper-way-to-wrap-an-imported-target-around-a-third-party-target/2757/8 "2021-05-17T08:47:57Z")

</div>

Hi,

I’m coming back to this thread because I’m a bit stuck with 3rd party libraries that don’t use namespace.  
I require all my dependencies to use namespace for homogeneity.

For instance OpenCV does not provide OpenCV::OpenCV.  
I do this:  
find\_package(${PackName} REQUIRED)  
IF(${PackName}\_FOUND AND NOT TARGET ${PackName}::${PackName})  
add\_library(${PackName}::${PackName} UNKNOWN IMPORTED)  
set\_target\_properties(${PackName}::${PackName} PROPERTIES  
IMPORTED\_LINK\_INTERFACE\_LANGUAGES “CXX”  
IMPORTED\_LOCATION “${${PackName}\_LIBRARIES}”  
INTERFACE\_INCLUDE\_DIRECTORIES “${${PackName}\_INCLUDE\_DIRS}”  
)  
target\_link\_libraries(${TARGET\_NAME} ${Inheritance} ${PackName}::${PackName})  
ENDIF()  
but then I’ve got a build error, telling me that there is no rule to build target opencv\_calib3d required for my target (actually opencv\_calib3d is the first lib in OpenCV\_LIBRARIES)

Besides I do it twice:  
first in a static library L that publicly depends on OpenCV  
then on my application A that depends both on L and on OpenCV

then in the build.make file of A, I see the list of OpenCV libraries twice. The build issues then a warning about an overloaded rule.

What do I miss?  
Is it possible to have also some insights on my more general questions above?

Many thanks in advance  
PS I duplicate the OpenCV related part in another threads as the issue is perhaps more related to opencv than to cmake
