It is desirable to use ALIAS targets instead of CONAN_LIB::* targets to minimize dependencies on Conan within CMake files.
In order to define an ALIAS target, the base target must be declared as GLOBAL, which is not currently done for the CONAN_LIB::* targets by the conan cmake generator.
Hi @sigiesec!
Two questions to really understand the use case:
CONAN_LIB::
targets and not the CONAN_PKG::
?Hi & thanks for the quick response!
The <target> may not be a non-GLOBAL Imported Target or an ALIAS.
Thanks for the info! I'm creating a test and will report.
Hi, I'm creating the CONAN_LIB::
targets with and without the GLOBAL: add_library(${_LIB_NAME} UNKNOWN IMPORTED GLOBAL)
but when I try to create an alias like this:
add_library(MY_ALIAS ALIAS CONAN_LIB::Hello0_helloHello0)
I'm receiving the error:
CMake Error at CMakeLists.txt:10 (add_library):
add_library cannot create ALIAS target "MY_ALIAS" because target "CONAN_LIB::Hello0_helloHello0" is
not a library.
Is it expected? Am I doing something wrong?
Hm, this is probably because of the target being specified as "UNKNOWN": https://gitlab.kitware.com/cmake/cmake/issues/18327. I noticed that yesterday when I experimented a bit, but wasn't aware that the CONAN_LIB targets are specified as UNKNOWN. I thought that https://docs.conan.io/en/latest/integrations/cmake/cmake_generator.html claims this, but actually this only refers to the CONAN_PKG targets:
Using TARGETS as argument, conan_basic_setup() will internally call the macro conan_define_targets() which defines cmake INTERFACE IMPORTED targets, one per package.
When using INTERFACE instead of UNKNOWN, however, it works:
add_library(Foo INTERFACE IMPORTED GLOBAL)
add_library(Bar ALIAS Foo)
But with INTERFACE IMPORTED
it doesn't allow to specify the IMPORTED_LOCATION
property. How do you specify where is the prebuilt library? In general, it appears to need important changes in the definition of the library targets and I can be it can be breaking for current users.
Yes that's right.
One option would be to define two targets then, such as:
# in conanbuildinfo.cmake
add_library(FooLib INTERFACE IMPORTED GLOBAL)
set_property(TARGET FooLib IMPORTED_LOCATION /somewhere/FooLib.a)
add_library(CONAN_LIB::Foo INTERFACE IMPORTED GLOBAL)
set_property(TARGET CONAN_LIB::FooPROPERTY INTERFACE_LINK_LIBRARIES FooLib)
# in user code
add_library(Bar ALIAS CONAN_LIB::Foo)
Another option would be not to use UNKNOWN, but SHARED or STATIC. I think conan has the necessary information to determine the difference, or doesn't it?
But maybe the CMake issue can be resolved, as I don't see a reason why an UNKNOWN target couldn't have an alias.
Another option would be not to use UNKNOWN, but SHARED or STATIC. I think conan has the necessary information to determine the difference, or doesn't it?
Not with data, but maybe checking extensions or something similar, but it tends to be weak.
About your example, I don't think if you made a mistake, but
set_property(TARGET FooLib IMPORTED_LOCATION /somewhere/FooLib.a)
is not valid either for INTERFACE IMPORTED GLOBAL
, maybe you meant to create a brand new target with INTERFACE IMPORTED GLOBAL
while we kept the rest exactly the same?
I wouldn't be very happy with duplicating the targets, sounds indeed like CMake craziness and unmaintainable conan code. :S
Oops, sorry, that was a mistake indeed, it should have been:
# in conanbuildinfo.cmake
add_library(FooLib UNKNOWN IMPORTED)
set_property(TARGET FooLib IMPORTED_LOCATION /somewhere/FooLib.a)
add_library(CONAN_LIB::Foo INTERFACE IMPORTED GLOBAL)
set_property(TARGET CONAN_LIB::FooPROPERTY INTERFACE_LINK_LIBRARIES FooLib)
# in user code
add_library(Bar ALIAS CONAN_LIB::Foo)
Beware, some functionality, like ALIAS to some targets, only work in very latest CMake, like 3.12. Also INTERFACE_LINK_LIBRARIES
for INTERFACE targets, I think. We need to keep backwards compatibility down to 3.3, for the targets approach, and cmake 2.8.12 for the global approach.
The ALIAS would only be used in the user CMake code (so we can only use it if we use a recent CMake version), so this change wouldn't put any additional restrictions on CMake versions on the conan side.
GLOBAL already is supported by CMake 3.0.2 at least.
I have played with this (manually adding GLOBAL
to the add_library(CONAN_PKG::<package> INTERFACE GLOBAL)
in the generated conanbuildinfo.cmake
and it did work for me.
I am not familiar with cmake to know what other implications this may have.
@memsharded @lasote: We are very interested in this (hence @dribeas 's comment) because our company's primary build system does not use Conan, so to ensure we can re-use our existing CMake under Conan, we'd like to ensure we can avoid having to mention CONAN_PKG::
or CONAN_LIB::
anywhere in our CML.
I have just hit this same issue, trying to define an alias, and being blocked by:
CMake Error at CMakeLists.txt:13 (add_library):
add_library cannot create ALIAS target "gflags::gflags" because target
"CONAN_PKG::gflags" is imported but not globally visible.
Same issue here, I've needed that kind of feature at least two or three times lately. Would it be possible to check the CMake version at the time when conanbuildinfo.cmake
is generated and to conditionally use the 3.12+ features in it dependending on whether they're supported? If build_requires
is run before the generators it can even allow to use cmake_installer
for people who want to use the feature.
I guess that conditionally using CMake features is another can of worms though :/
The package that wants to define an ALIAS to the conan-generated targets requires a recent-ish CMake.
However, as mentioned above, the code generated by conan defining GLOBAL targets does not depend on CMake 3.12, but is supported from CMake 3.0.2
So there is no need to make a check within conan for this particular thing. It might be useful for other features though.
So, summarizing, to implement the feature. The goal is to be able to create ALIAS of the targets generated with CMake taking into account we should keep the compatibility as much as possible with older CMakes, maybe introducing only the GLOBAL if the cmake is modern-enough or with another mechanism.
As @sigiesec said, I also think that setting the GLOBAL
option for the CONAN_LIB::
target would not be a problem as it is supported from CMake 3.0.2 and the consumer will be the one that needs a modern CMake version.
After testing this locally, using many different CMake versions I confirmed that:
Using ALIAS
for IMPORTED
targets works for CMake > 3.10.3
(as stated in the docs)
Using ALIAS
for UNKNOWN
IMPORTED
targets works only for CMake > 3.14
(will print the is not a library
error instead of the not globally visible
. one) as was commented earlier because of: https://gitlab.kitware.com/cmake/cmake/issues/18327
Hi @sigiesec, @Morwenn
After giving a thought to this problem I was wondering if, for example, conan provided a target with a name like: self.cpp_info.name + library_name
for those LIB::
targets, would it solve your issue in any way so you don't need to make the ALIAS for the LIB::
target?
Hi @sigiesec, @Morwenn
After giving a thought to this problem I was wondering if, for example, conan provided a target with a name like:
self.cpp_info.name + library_name
for thoseLIB::
targets, would it solve your issue in any way so you don't need to make the ALIAS for theLIB::
target?
No, I don't think so. Any name/naming scheme defined by conan wouldn't serve the purpose of being independent of conan in the CMake files.
It would be nice if the name were consistent, but looking at what I'm using them for right now, it might be difficult. Here is what I have in my top-level CMakeLists.txt
right now to package the k4a SDK:
add_library(Eigen3Workaround INTERFACE)
target_link_libraries(Eigen3Workaround INTERFACE CONAN_PKG::eigen)
add_library(Eigen3::Eigen ALIAS Eigen3Workaround)
add_library(gtest INTERFACE)
target_link_libraries(gtest INTERFACE CONAN_PKG::gtest)
add_library(gmock INTERFACE)
target_link_libraries(gmock INTERFACE CONAN_PKG::gtest)
add_library(imgui INTERFACE)
target_link_libraries(imgui INTERFACE CONAN_PKG::imgui)
add_library(turbojpeg INTERFACE)
target_link_libraries(turbojpeg INTERFACE CONAN_PKG::libjpeg-turbo)
add_library(turbojpeg-static INTERFACE)
target_link_libraries(turbojpeg INTERFACE CONAN_PKG::libjpeg-turbo)
add_library(uvc_static INTERFACE)
target_link_libraries(uvc_static INTERFACE CONAN_PKG::libuvc)
As you can see some targets have names such as uvc_static
or turbojpeg-static
which might or might not live along their non-static counterparts, some others work differently altogether, so we really need the ability to mock arbitrary names and can't just rely on Conan-provided ones.
My use case would be to replace the INTERFACE
libraries above by ALIAS
and I thought that GLOBAL
Conan targets would allow me to use simple ALIAS
to do that. Now maybe I'm wrong and it has some additional issues I don't quite understand, but the ability to provide aliases as arbitrary name is definitely a need.
Merged #6438, will be released in next Conan 1.22
To be reverted in 1.22.1: https://github.com/conan-io/conan/pull/6488, it started to break users with add_subdirectory
strategies. If needed, we have to think a different approach.
While trying to replace my INTERFACE
targets above with ALIAS
ones I was bitten by the fact that the library I'm packaging defines itself ALIAS
to the expected targets and apparently you can't have an ALIAS
to an ALIAS
in CMake: basically the switch to GLOBAL
was welcome yet unfortunately still insufficient because of CMake idiosyncrasies.
Since it wasn't enough and it's causing new issues, I guess that it's the best move to remove it swiftly for now and to mention in the release notes of 1.22 that it shouldn't be relied upon. The fix proposed in #6480 looks good to have anyway.
Have there been any thoughts on how to achieve the goals of this issue without the problems that #6438 caused?
I'm obviously late to the party, but this functionality would still be welcomed!
Could this be another option to conan_basic_setup
? Use TARGETS_GLOBAL
instead of TARGETS
which would in turn pass a variable to conan_define_targets
that conditionally includes the GLOBAL
property?
Would it be better to reopen this issue or to start fresh?
The release notes for CMake 3.18 have the following item:
The
add_library()
andadd_executable()
commands learned to create Alias Targets referencing non-GLOBAL
Imported Targets.
So maybe a partial workaround would be to use self.requires("cmake/3.18")
in recipes where this matter?
Most helpful comment
Merged #6438, will be released in next Conan 1.22