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.
They also help you producing ‘runtime’ packages (containing just what is necessary to run your software), or ‘development’ packages (containing everything in the runtime package, plus all that is necessary to use your : headers, library, cmake config files, et al.)
Here are the components that will be used during a runtime install
component | function | destination |
---|---|---|
“binary” | qi_create_bin | bin/ |
“lib” | qi_create_lib(SHARED) | lib/ on UNIX, bin/ on windows |
“conf” | qi_install_conf | etc/ |
“data” | qi_install_data | share/ |
“doc” | qi_install_doc | share/doc |
Note that qi_create_bin and qi_create_lib create the install rules for you by default. If you don’t what the executable to be installed (because it’s just a test, 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
When doing a normal install, you will get the previous component, plus the following ones
component | function | destination |
---|---|---|
“static-lib”, | qi_create_lib(STATIC) | lib/ |
“cmake” | qi_stage_lib | share/cmake/modules/ |
“header” | qi_install_header | include/ |
If you want to install something in your development install that does not fit in these components (say, an example), you can use the generic qi_install function
For instance
qi_install(foo_example bar_examples DESTINATION examples KEEP_RELATIVE_PATHS)
will give you:
sources destination
examples
foo_example |__ foo_example
|__ CMakeLists |__ CMakeLists
|__ foo.cpp |__ foo.cpp
bar_example bar_example
|__ CMakeLists |__ CMakeLists
|__ bar.cpp |__ bar.cpp
Also, to install a README at the root of your package you could do:
qi_install(doc/README DESTINATION ".")
Since no component as been given, this files won’t be in the runtime install.
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 exists, 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.