Combining two third party libraries into a single imported target

Hi

My need as described in the topic subject is occurring with the GMP library (Gnu Multiple Precision).
On my system it does not seem to be detectable by find_package so I tried to make it detectable through a Findgmp.cmake.

The issue is that it is actually made fo two libraries gmp (C API) and gmpxx (C++ API, which depend on the first one).

I can link both using two different find modules, and generating two targets (gmp::gmp and gmpxx::gmpxx) but I’d like to have only one target (say gmp::gmp) that allows me to link both libraries.

So far I cannot write my findmodule accordingly (example attached).

Can someone tell me how to fix it?

By the way, I’m utterly confused with the difference between _LIBRARY and _LIBRARIES, _INCLUDE_DIR and _INCLUDE_DIRS. I’d appreciate some clarifications on this topic.

Regards
A.
Findgmp.cmake (1.2 KB)

The singular ones tend to be find_* cache variables. Once the package is considered found, the plural ones are set as needed as local variables.

Right, a find module would need to be written. You can write one that finds both targets. Something like:

add_library(gmp::gmp UNKNOWN IMPORTED)
# skipping over location settings

# component conditional?
add_library(gmp::gmpxx UNKNOWN IMPORTED)
set_target_properties(gmp::gmpxx PROPERTIES LINK_INTERFACE_LIBRARIES gmp::gmp)
# skipping over location settings

add_library(gmp::gmpall INTERFACE)
set_target_properties(gmp::gmpxx PROPERTIES LINK_INTERFACE_LIBRARIES "gmp::gmp;gmp::gmpxx")

Thanks for your answer.

Here is my failed try
Findgmp.cmake (1.4 KB)

in my CMakeList:

  IF(gmp_FOUND)
  	MESSAGE("gmp package found")
  	IF (NOT TARGET gmp::gmp)
  		MESSAGE(WARNING "gmp::gmp target not found")
  	ENDIF()
  ENDIF()

and the configuration output:

gmp package found
gmp::gmp target not found

What did I do wrong?

Thanks again
A.

AND gmpxx_FOUND

Nothing ever sets gmpxx_FOUND. Additionally, you should guard target creation with if (NOT TARGET …) because find_package(gmp) running twice within a scope is otherwise a hard error on the target re-creation.

Thanks for having pinpointed a first error.

Here is the update

Now the configuration seems OK.

I find_package(gmp) then target_link_libraries(MyTargetName PRIVATE gmp::gmp) but on link, only libgmpxx is passed to the linker whereas libgmp is also expected and needed.

where is the next mistake?
Findgmp.cmake (1.9 KB)

A.

You still need to wrap all of the post-FPHSA stuff in if (gmp_FOUND). But the gmp::gmp target is completely wrong. It needs to be an INTERFACE, not an UNKNOWN library. You’re setting the same property twice which means that the first setting is completely ignored.

Sorry but I’m still lost.

I fixed the INTERFACE issue but I have the same behaviour, nothing is linked, as if gmp::gmp would be empty.

GMPTest.7z (1.4 KB)

Here is a minimal example to reproduce

on the other hand targets gmp::gmpc and gmp::gmpxx as, if I replace

target_link_libraries(${TARGET_NAME} PRIVATE gmp::gmp)

by

target_link_libraries(${TARGET_NAME} PRIVATE gmp::gmpc)
target_link_libraries(${TARGET_NAME} PRIVATE gmp::gmpxx)

it compiles and runs fine

another fix is to replace

set_target_properties(gmp::gmp PROPERTIES LINK_INTERFACE_LIBRARIES "gmp::gmpc;gmp::gmpxx")```
by
```cmake
target_link_libraries(gmp::gmp INTERFACE gmp::gmpc gmp::gmpxx)

whereas both commands seem equivalent to me…
then

target_link_libraries(${TARGET_NAME} PRIVATE gmp::gmp)

works properly
But anyway, whatever the commands used, variables gmp_LIBRARY and gmp_INCLUDE_DIR with incorrect values are created. How to set them correctly?

thanks again for the help

I have another issue with my Findgmp module.
on some random machine, I seem to find a gmp install as _INCLUDE_DIR and _LIBRARY paths are set

/usr/lib/x86_64-linux-gnu/libgmp.so
/usr/include/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libgmpxx.so
/usr/include

yet, when running CMake, I have the following error:
CMake Error at …/Findgmp.cmake:50 (target_link_libraries):
Cannot specify link libraries for target “gmp::gmp” which is not built by this project.

What does it mean? How can I fix it.
Thanks
Findgmp.cmake (1.6 KB)

Issue on cmake 3.10.2, no issue on 3.19.2

mere curiosity, what has changed between both version that may explained the error.
from what version should I consider that my Findgmp is OK?

I will just issue an error message if client cmake version is too old.

Thx,
A.

Probably CMP0079 in v3.13:
target_link_libraries() allows use with targets in other directories.

If that’s not the one: You can play around with different cmake_minimum_required until the problem also occurs in your newer version.

Thx, it sounds correct.
Regards
A.