.. _cmake-install: Using qi_install functions ========================== ``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 Components ---------- 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.) Runtime versus development installation --------------------------------------- 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 :ref:`qi_create_bin` and :ref:`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: .. code-block:: cmake 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 :ref:`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 :ref:`qi_install` function For instance .. code-block:: cmake 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: .. code-block:: cmake qi_install(doc/README DESTINATION ".") Since no component as been given, this files won't be in the runtime install. Special features ----------------- :ref:`qi_install` ends up calling regular install() CMake functions, but there are some differences, here are a few Check of arguments ++++++++++++++++++ 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. .. code-block:: cmake # 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 ... Support of glob and directories +++++++++++++++++++++++++++++++ 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 .. code-block:: cmake qi_install(foo/bar/ \*.txt spam.cfg eggs.cfg DESTINATION "prefix") will install: * directory foo/bar to "prefix/bar" * every .txt file in current directory to "prefix" * the spam and eggs cfg file to "prefix" "IF" keyword ++++++++++++ Instead of using .. code-block:: cmake if(FOO) qi_install(.... ) endif() you can use .. code-block:: cmake qi_install(.... IF FOO) SUBFOLDER and KEEP_RELATIVE_PATHS keywords ++++++++++++++++++++++++++++++++++++++++++ ``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. Using SUBFOLDER ~~~~~~~~~~~~~~~ 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 .. code-block:: cmake qi_install_header(foo HEADERS foo/include/foo.h foo/include/bar.h ${CMAKE_BUILD_DIR}/config.h SUBFOLDER foo) :ref:`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. Using KEEP_RELATIVE_PATHS ~~~~~~~~~~~~~~~~~~~~~~~~~ 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 .. code-block:: cmake qi_install_header(foo HEADERS foo/foo.h bar/bar.h bar/baz/baz.h KEEP_RELATIVE_PATHS) :ref:`qi_install_header` will set DESTINATION "include" for you, and you do not need ``SUBFOLDER`` because ``KEEP_RELATIVE_PATHS`` is set.