'How to reuse an interface library in another project?

I want to reuse an interface library in another project. I tried it with:

find_package(mylib CONFIG REQUIRED)
target_link_libraries(project mylib)

Which gives the error:

/usr/bin/ld: cannot find -lmylib

Which I do not understand because I want to use an interface library why there is a linker error?

I made a minimal example of the interface library and the consumer project. Based on this stackoverlow answer

Console output install library:

walde@localhost build]$ cmake .. ; cmake --build . ; sudo cmake --install .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/walde/projects/sandbox/cmake_get_target/myLib/build
-- Install configuration: ""
-- Up-to-date: /usr/local/lib/cmake/mylib/mylibTargets.cmake
-- Up-to-date: /usr/local/lib/cmake/mylib/mylibConfigVersion.cmake
-- Up-to-date: /usr/local/lib/cmake/mylib/mylibConfig.cmake
-- Up-to-date: /usr/local/include
-- Up-to-date: /usr/local/include/calc.hxx
-- Up-to-date: /usr/local/include/calc.cxx
-- Up-to-date: /usr/local/include/CMakeLists.txt

Console output consumer:

[walde@localhost build]$ cmake .. ; cmake --build .
-- Configuring done
-- Generating done
-- Build files have been written to: /home/walde/projects/sandbox/cmake_get_target/use_my_lib_in_another_project/build
Consolidate compiler generated dependencies of target project
[ 50%] Linking CXX executable project
/usr/bin/ld: cannot find -lmylib
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/project.dir/build.make:97: project] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/project.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
[walde@localhost build]$ 


Solution 1:[1]

I want to reuse an interface library in another project. I tried it with:

find_package(mylib CONFIG REQUIRED)
target_link_libraries(project mylib)

Three things:

  1. Absolutely never use target_link_libraries without a visibility specifier.
  2. When exporting targets, always include a namespace (via the NAMESPACE argument to install(EXPORT)) so that the IMPORTED target name contains a :: sigil in it.
  3. For consistency in the build and install trees, create an ALIAS target in the build with the same namespace prefix as your install will have.

The reason for (1) is that no-visibility is not the same as any of simply PRIVATE, INTERFACE, or PUBLIC, and it drops into a weird legacy compatibility mode when the styles are mixed. Absolutely always include the appropriate one of the three.

The reason for (2) is that names that contain :: are always interpreted as CMake targets. That would make the error you observed absolutely impossible. CMake would instead tell you that namespace::mylib doesn't exist and you could correct the typo.

When target_link_libraries gets a name without a :: sigil, it tries to find a target with the same name, but if that fails, then it forwards it on to the compiler driver with the -l flag (or equivalent).

For (3), consistency is nice and this will also help users of add_subdirectory or FetchContent switch between that and find_package more easily.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Alex Reinking