libfort
libfort copied to clipboard
Support exported targets
I have a C++ project using the CMake build system. I tried to link to libfort with
add_subdirectory(…)
+ target_link_libraries(mylib libfort)
but cmake complains as it does not export targets. Indeed, there is no install(export )
for targets with CMake configuration files.
It would be possible to support also exported targets for use in an external project?
Thanks in advance for any help!
Hi! I am currently working on exporting targets and creating appropriate files for library installation. I am not a cmake expert. So I think it will take a few days to figure out how to create proper cmake files.
But I wanted to note that library target is called fort
(not libfort
).
If I am not mistaken at the moment in case you copied sources in directory third-party
you can add it to you project like this:
add_subdirectory(third-party/libfort EXCLUDE_FROM_ALL)
target_link_libraries(mylib fort)
or
add_subdirectory(third-party/libfort/lib)
target_link_libraries(mylib fort)
Hi! Thank you for the prompt response. By digging a bit on what happens during the configuration process, I figure out that upon creation of the export targets in my project, cmake complains that libfort lacks one.
The first strategy you suggested works for me, as long as I don’t export targets by myself. The second approach works fine as long as no installation is performed, since it lacks version information provided by the full cmake project.
I am not a cmake expert either, so I may be missing something…
Since it took several days for me to figure out the proper way to support exported targets, let me suggest you how you can do it. Actually, in the end it is pretty straightforward. Your CMakeLists.txt file should contain the following lines after target creation (via add_library or add_executable):
include(CMakePackageConfigHelpers)
configure_package_config_file(
${LIB_NAME}-config.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}-config.cmake
INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR}
PATH_VARS CMAKE_INSTALL_INCLUDEDIR
)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}-config-version.cmake
COMPATIBILITY SameMajorVersion
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}-config.cmake
${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}-config-version.cmake
DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
install(
TARGETS ${LIB_NAME}
EXPORT ${LIB_NAME}-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
install(
EXPORT ${LIB_NAME}-targets
FILE ${LIB_NAME}-targets.cmake
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${CMAKECONFIG_INSTALL_DIR}
)
with the standard definitions CMAKE_INSTALL_LIBDIR=lib
, CMAKE_INSTALL_BINDIR=bin
, CMAKE_INSTALL_INCLUDEDIR=include
.
CMAKECONFIG_INSTALL_DIR
is usually defined as ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB_NAME}
, relative to the installation prefix.
Adding a NAMESPACE
prevents name clashes, and also allows for a clean way to support multi-targets projects. The target can then be linked to as ${PROJECT_NAME}::${LIB_NAME}
, in your case it would be: libfort::fort
.
The *-targets.cmake
files are automatically generated, you just need to write a *-config.cmake.in
file. This file can be nothing more than
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
check_required_components("@LIB_NAME@")
This is, to my current understanding, what should be done. This should just work. :) Hope it helps!
Best, Nicola
Hi! Sorry for keep you waiting.
Merged changes to develop (thanks for posting examples above, they helped me a lot).
Exported target is called libfort::fort
.
So I think in case libfort is installed you can use in cmake:
find_package(libfort)
target_link_libraries(mylib libfort::fort)
Also added some simple checks to CI to check how library is installed and used by other libraries.
If something is still incorrect or doesn't work as expected feel free to write comments.
As I understand what I've done and tested is not particular you case because you don't install libfort but use add_subdirectory
, I haven't tested such variant myself yet, I'll try to write such test for CI in a few days and correct cmake files if needed.
Hi! I am glad that it helped you.
You are right, I mixed some things, but I actually need both methods... ;) The library is first searched with find_package and if not found, cmake falls back to compilation from source with add_subdirectory.
As soon I have time to test myself, I will do!