There is absolutely a canonical way to do that, and it revolves around the export(TARGETS)
command. (Or, if you’re already using install(EXPORT)
to create your exported target set for installation, the very similar export(EXPORT)
command.)
Basically, export(EXPORT)
: build-tree :: install(EXPORT)
: install-tree.
By exporting your CMake package configuration and build targets into the build tree, you can allow dependent projects to point CMAKE_PREFIX_PATH
into your build directory and use find_package()
to pick up your build artifacts the same way they consume your installed configuration.
So, say you have a library project:
add_library(foo SHARED ${foo_sources})
target_include_directories(foo
PRIVATE
src/include
PUBLIC
${CMAKE_INSTALL_INCLUDEDIR}/foo
)
set_target_properties(foo ...)
# etc...
And it installs exported targets:
include(GNUInstallDirs)
install(TARGETS foo
EXPORT FooTargets
[<PART> DESTINATION ...]s
)
install(EXPORT FooTargets
NAMESPACE Foo::
FILE FooTargets.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo
)
Along with a generated CMake configuration, so that your clients’ code can pick up the installed package using find_package(Foo)
and target_link_libraries(... Foo::foo)
:
include(CMakePackageConfigHelpers)
configure_package_config_file(
"${CMAKE_SOURCE_DIR}/cmake/FooConfig.cmake.in"
"${CMAKE_BINARY_DIR}/cmake/FooConfig.cmake"
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo/
)
install(FILES
"${CMAKE_BINARY_DIR}/cmake/FooConfig.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo/
)
To make that same exported configuration available without installing the package, all you need to do is ensure your exported INTERFACE_INCLUDE_DIRECTORIES
are properly mapped in both the build and install interfaces:
target_include_directories(foo PUBLIC
$<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/foo>
)
And export your targets into the build directory, in addition to the installed configuration:
export(EXPORT FooTargets
NAMESPACE Foo::
FILE "${CMAKE_BINARY_DIR}/cmake/FooTargets.cmake"
)
And any client code that would normally use find_package(Foo)
and target_link_libraries(... Foo::foo)
to link with your installed library can continue to do exactly the same thing, but pick up your uninstalled build artifacts by simply putting your build dir on the config search path:
$ cmake -B _build -S . \
-DCMAKE_PREFIX_PATH=/path/to/foo/_build
See the Importing and Exporting Guide for more details.