Woraround to overcome badly designed config packaging with imported target names = library names

One such badly designed package is the lapack software where those developers
(still as of the latest version, 3.9.0) do not use the NAMESPACE
option to install(EXPORT…) to set, e.g., a LAPACK:: namespace on
the imported lapack, etc., libraries. And even though I successfully
used env CMAKE_PREFIX_PATH=/home/software/lapack/install-3.9.0 to find
the version of lapack that I built myself, I discovered afterward that
target_link_libraries( lapack) linked to the system library lapack
rather than the imported target with that same name (at least for

If this lapack issue is a common occurrence for “config” CMake
packaging for other software packages, would CMake developers be
willing to change target_link_libraries to first search for targets
rather than libraries? Or has that already been done for CMake
versions > 3.13.4 with appropriate POLICY change?

But while such issues are being sorted out at the CMake level as
requested above or at the packaging level for individual software
projects such as lapack here is a workaround to overcome this issue for the
lapack case which could easily be generalized for other packaging
efforts with the same issue:

# Try pure config package first.
find_package(LAPACK CONFIG)
if(TARGET lapack)
   # Found it.  Now do what lapack team should have done which is to
   # create the LAPACK::lapack target rather than just the lapack target
   # to distinguish it from the lapack library.

   # Setting the following property allows creating an alias library with
   # the desired LAPACK::lapack name.
   add_library(LAPACK::lapack ALIAS lapack)
else(TARGET lapack)
   find_package(LAPACK REQUIRED)
endif(TARGET lapack)

Does using $<TARGET_NAME:lapack> work?

I don’t think we can change the current behavior without a new policy, but I don’t know how we could write such a policy if we end up going with -lfoolib in the current case since the warning would have to be at build time.

I thought CMake already uses targets in preference to libraries and that it has been this way for a long time (maybe @brad.king can confirm this) . Perhaps the target you are expecting to be picked up in your target_link_libraries() call is not a global target and isn’t in scope at the point you are expecting it to be used? For example, if you use find_package() to find something, it creates a local imported target. That target will be visible in the current scope and below, but not in parents or siblings. So if one subdirectory does the find_package() call and you try to refer to that target name in a different directory that isn’t that same directory or a child of it, then the target won’t be visible. Linking to the name would result in CMake looking for a target by that name, failing to find one and assuming it refers to the name of an ordinary library to be linked with -lthename instead. It looks like you kinda already know this though, given that your example promotes the local imported targets to global so you can create your own ALIAS for it.