qi_install functions are simply wrappers for install upstream CMake functions.
Here are a few concepts you need to understand to properly use qi_install functions
The various qi_install_* function deals with the components and respect the SDK layout for you.
There are 3 sort of dependencies in qibuild, which match 3 install components:
Note that the qi_create_* and the qi_stage_lib functions create correct install rules for you by default.
function | component | destination |
---|---|---|
qi_create_bin | runtime | bin/ |
qi_create_lib(SHARED) | runtime | lib/ on UNIX, bin/ on windows |
qi_install_conf | runtime | etc/ |
qi_install_data | runtime | share/ |
qi_create_lib(STATIC) | build | lib/ |
qi_stage_lib(foo) | build | share/cmake/modules/foo/foo-config.cmake |
qi_install_header | build | include/ |
qi_create_test_helper | test | bin/ |
If you don’t want the executable to be installed (because it’s just used at build time, for instance), you can use:
qi_create_bin(foo NO_INSTALL)
If you want to install an executable that is NOT the result of a compilation (for instance a script), you can use qi_install_program
If you want to install something in your development install that does not fit in these destinations (say, an example), you can use the generic qi_install function with DESTINATION and COMPONENT arguments.
qi_install ends up calling regular install() CMake functions, but there are some differences, here are a few
If you try to install a file that does not exist, using install() will exit during installation, but qi_install will exit during configuration. This does no prevent you from installing generated files, but you have to make sure the are generated before creating the install rule.
# Always generate files in cmake build dir:
set(_out ${CMAKE_CURRENT_BINARY_DIR}/foobar)
configure_file(foobar.in "${_out}")
qi_install("${_out}"
DESTINATION /etc/init.d/
)
# Note the trailing "/" at the end of the DESTINATION argument.
# Do NOT use:
qi_install("${_out}"
DESTINATION /etc/init.d/foobar
)
# or you'll end up with /etc/init.d/foobar/foobar ...
Please not that on top of this, you can use directories, globbing expressions and list of files as arguments on all qi_install_* functions.
For instance
qi_install(foo/bar/ *.txt spam.cfg eggs.cfg DESTINATION "prefix")
will install:
Note the glob is not recursive by default.
If you really need it, just use:
qi_install(foo/*.hpp RECURSE)
Instead of using
if(FOO)
qi_install(.... )
endif()
you can use
qi_install(.... IF FOO)
qi_install functions accept either a SUBFOLDER or a KEEP_RELATIVE_PATHS keyword.
It is easier to understand the meaning of these keywords by an example.
You should use this for instance with headers in several different folders (a bit like an autotools project):
sources: destination
foo include
|__ include |__ foo
|__ foo.h |__ foo.h
|__ bar.h |__ bar.h
config.h (generated) |__ config.h
qi_install_header(foo
HEADERS
foo/include/foo.h
foo/include/bar.h
${CMAKE_BUILD_DIR}/config.h
SUBFOLDER foo)
qi_install_header will set DESTINATION “include” for you, but you need ‘SUBFOLDER foo’ argument to tell CMake to install files to include/foo, regardless their original path.
You should you this for instance with headers following the exact same hierarchy in the source tree and when installed (a bit like boost):
sources destination
libfoo include
|__ foo |__ foo
|__ foo.h |__ foo.h
bar bar
|__ bar.h |__ bar.h
baz baz
|__ baz.h |__ baz.h
qi_install_header(foo
HEADERS
foo/foo.h
bar/bar.h
bar/baz/baz.h
KEEP_RELATIVE_PATHS)
qi_install_header will set DESTINATION “include” for you, and you do not need SUBFOLDER because KEEP_RELATIVE_PATHS is set.