https://public.kitware.com/Wiki/api.php?action=feedcontributions&user=Kitts+82&feedformat=atomKitwarePublic - User contributions [en]2024-03-28T20:25:45ZUser contributionsMediaWiki 1.38.6https://public.kitware.com/Wiki/index.php?title=CMake/Tutorials/Exporting_and_Importing_Targets&diff=41001CMake/Tutorials/Exporting and Importing Targets2011-06-21T18:32:49Z<p>Kitts 82: </p>
<hr />
<div>__TOC__<br />
<br />
CMake 2.6 introduced support for exporting targets from one project and importing them into another.<br />
The main feature allowing this functionality is the notion of an <code>IMPORTED</code> target.<br />
Here we present imported targets and then show how CMake files may be generated by a project to export its targets for use by other projects.<br />
<br />
=Importing Targets=<br />
<br />
Imported targets are used to convert files outside the project on disk into logical targets inside a CMake project.<br />
They are created using the <code>IMPORTED</code> option to <code>add_executable</code> and <code>add_library</code> commands.<br />
No build files are generated for imported targets.<br />
They are useful simply for convenient, flexible reference to outside executables and libraries.<br />
<br />
Consider the following example which creates and uses an IMPORTED executable target:<br />
<br />
add_executable(generator IMPORTED) # 1<br />
set_property(TARGET generator PROPERTY IMPORTED_LOCATION "/path/to/some_generator") # 2<br />
<br />
set(GENERATED_SRC ${CMAKE_CURRENT_BINARY_DIR}/generated.c)<br />
add_custom_command(<br />
OUTPUT ${GENERATED_SRC}<br />
COMMAND generator ${GENERATED_SRC} # 3<br />
)<br />
<br />
add_executable(myexe src1.c src2.c ${GENERATED_SRC})<br />
<br />
Line #1 creates a new CMake target called "<code>generator</code>".<br />
Line #2 tells CMake the location of the file on disk to import.<br />
Line #3 references the target in a custom command. The generated build system will contain a command line such as<br />
<br />
/path/to/some_generator /project/binary/dir/generated.c<br />
<br />
in the rule to generate the source file.<br />
<br />
Libraries may also be used through imported targets:<br />
<br />
add_library(foo STATIC IMPORTED)<br />
set_property(TARGET foo PROPERTY IMPORTED_LOCATION /path/to/libfoo.a)<br />
add_executable(myexe src1.c src2.c)<br />
target_link_libraries(myexe foo)<br />
<br />
The generated build system will contain a command line such as<br />
<br />
... -o myexe /path/to/libfoo.a ...<br />
<br />
in the rule to link <code>myexe</code>.<br />
On Windows a .dll and its .lib import library may be imported together:<br />
<br />
add_library(bar SHARED IMPORTED)<br />
set_property(TARGET bar PROPERTY IMPORTED_LOCATION c:/path/to/bar.dll)<br />
set_property(TARGET bar PROPERTY IMPORTED_IMPLIB c:/path/to/bar.lib)<br />
add_executable(myexe src1.c src2.c)<br />
target_link_libraries(myexe bar)<br />
<br />
The generated build system will contain a command line such as<br />
<br />
... -o myexe.exe c:/path/to/bar.lib ...<br />
<br />
in the rule to link <code>myexe</code>.<br />
A library with multiple configurations may be imported with a single target:<br />
<br />
add_library(foo STATIC IMPORTED)<br />
set_property(TARGET foo PROPERTY IMPORTED_LOCATION_RELEASE c:/path/to/foo.lib)<br />
set_property(TARGET foo PROPERTY IMPORTED_LOCATION_DEBUG c:/path/to/foo_d.lib)<br />
add_executable(myexe src1.c src2.c)<br />
target_link_libraries(myexe foo)<br />
<br />
The generated build system will link <code>myexe</code> to <code>foo.lib</code> when it is built in the release configuration and <code>foo_d.lib</code> when built in the debug configuration.<br />
<br />
In some cases, such as when using the result of a <code>find_library</code> command to create an imported target, the type of the library (static or shared) is not known. As of CMake 2.6.2 one may specify this explicitly:<br />
<br />
find_library(FOO_LIBRARY NAMES foo)<br />
add_library(foo UNKNOWN IMPORTED)<br />
set_property(TARGET foo PROPERTY IMPORTED_LOCATION "${FOO_LIBRARY}")<br />
add_executable(myexe src1.c src2.c)<br />
target_link_libraries(myexe foo)<br />
<br />
In this case CMake does not know the library type, so it just puts the library on the link line as-is. Therefore on Windows there is no special treatment for a shared library. The runtime library (foo.dll) need not be found. The import library (foo.lib) is specified by the <code>IMPORTED_LOCATION</code> property, not the <code>IMPORTED_IMPLIB</code> property.<br />
<br />
=Exporting Targets=<br />
<br />
Imported targets on their own are useful, but they still require the project that imports targets to know the locations of the target files on disk.<br />
The real power of this feature is when the project providing the target files also provides a file to help import them.<br />
<br />
==Exporting from an Installation Tree==<br />
<br />
The <code>install(TARGETS)</code> and <code>install(EXPORT)</code> commands work together to install a target and a file to help import it.<br />
For example, the code<br />
<br />
add_executable(generator generator.c)<br />
install(TARGETS generator DESTINATION lib/myproj/generators EXPORT myproj-targets)<br />
install(EXPORT myproj-targets DESTINATION lib/myproj)<br />
<br />
installs the files<br />
<br />
<prefix>/lib/myproj/generators/generator<br />
<prefix>/lib/myproj/myproj-targets.cmake<br />
<br />
The <code>myproj-targets.cmake</code> file contains code such as<br />
<br />
add_executable(generator IMPORTED)<br />
set_property(<br />
TARGET generator<br />
PROPERTY IMPORTED_LOCATION ${PREFIX}/lib/myproj/generators/generator<br />
)<br />
<br />
(in practice the <code>${PREFIX}</code> is computed relative to the file location automatically).<br />
An outside project may now contain code such as<br />
<br />
include(${PREFIX}/lib/myproj/myproj-targets.cmake) # 1<br />
set(GENERATED_SRC ${CMAKE_CURRENT_BINARY_DIR}/generated.c)<br />
add_custom_command(<br />
OUTPUT ${GENERATED_SRC}<br />
COMMAND generator ${GENERATED_SRC} # 2<br />
)<br />
add_executable(myexe src1.c src2.c ${GENERATED_SRC})<br />
<br />
Line #1 loads the target import script. The script may import any number of targets. Their locations are computed relative to the script location so the install tree may be moved around.<br />
The importing project need only find the import script (see the packaging section of this document for how this might be done).<br />
Line #2 references the generator executable in a custom command. The resulting build system will run the executable from its installed location.<br />
<br />
Libraries may also be exported and imported:<br />
<br />
add_library(foo STATIC foo1.c)<br />
install(TARGETS foo DESTINATION lib EXPORT myproj-targets)<br />
install(EXPORT myproj-targets DESTINATION lib/myproj)<br />
<br />
This installs the library and an import file referencing it. Outside projects may simply write<br />
<br />
include(${PREFIX}/lib/myproj/myproj-targets.cmake)<br />
add_executable(myexe src1.c)<br />
target_link_libraries(myexe foo)<br />
<br />
and the executable will be linked to the library <code>foo</code> exported and installed by the original project.<br />
<br />
Any number of target installations may be associated with the same export name.<br />
The export names are considered global so any directory may contribute a target installation.<br />
Only one call to the <code>install(EXPORT)</code> command is needed to install an import file that references all targets.<br />
Both of the examples above may be combined into a single export, even if they are in different subdirectories of the project:<br />
<br />
# A/CMakeLists.txt<br />
add_executable(generator generator.c)<br />
install(TARGETS generator DESTINATION lib/myproj/generators EXPORT myproj-targets)<br />
<br />
# B/CMakeLists.txt<br />
add_library(foo STATIC foo1.c)<br />
install(TARGETS foo DESTINATION lib EXPORT myproj-targets)<br />
<br />
# Top CMakeLists.txt<br />
add_subdirectory(A)<br />
add_subdirectory(B)<br />
install(EXPORT myproj-targets DESTINATION lib/myproj)<br />
<br />
==Exporting from a Build Tree==<br />
<br />
Typically projects are built and installed before being used by an outside project.<br />
However in some cases it is desirable to export targets directly from a build tree.<br />
The targets may then be used by an outside project that references the build tree with no installation involved.<br />
<br />
The <code>export</code> command is used to generate a file exporting targets from a project build tree.<br />
For example, the code<br />
<br />
add_executable(generator generator.c)<br />
export(TARGETS generator FILE myproj-exports.cmake)<br />
<br />
will create a file in the project build tree called <code>myproj-exports.cmake</code> that contains code such as<br />
<br />
add_executable(generator IMPORTED)<br />
set_property(TARGET generator PROPERTY IMPORTED_LOCATION "/path/to/build/tree/generator")<br />
<br />
This file may be loaded by an outside project that is aware of the project build tree in order to use the executable to generate a source file.<br />
<br />
An example application of this feature is for building a generator executable on a host platform when cross compiling.<br />
The project containing the generator executable may be built on the host platform and then the project that is being cross-compiled for another platform may load it.</div>Kitts 82