This project was created to help answer Stackoverflow question 56135785. See https://stackoverflow.com/questions/56135785/correctly-set-the-location-of-imported-cmake-targets-for-an-installed-package
It improves the sample code originally submitted by user bruce-adams and provides some recommendations to better organize the associated CMake project.
- 2019-05-25
- Create GitHub project to streamline reuse and adaptation. See https://github.com/jcfr/stackoverflow-56135785-answer
- Rename project and source directory from
foobartoFooBarLib, update Suggestions section accordingly - Improve
build.sh - Updated suggestions (
CPACK_PACKAGING_INSTALL_PREFIXshould indeed be absolute to properly impact RPM layout) - RPM:
- Be aware that setting
CPACK_PACKAGING_INSTALL_PREFIXalso impact the layout of theTGZarchive, this propably not what you want. - Update
build.shto display content of RPM package CPACK_PACKAGING_INSTALL_PREFIXis set to/opt
- Be aware that setting
- Two config files should be generated:
- one for the build tree: this allow user of your project to directly build against your project and import targets
- one for the install tree (which also end up being packaged)
- Do not force the value of
CMAKE_INSTALL_PREFIX CPACK_PACKAGING_INSTALL_PREFIXshould NOT be set to an absolute directoryFor sake of consistency, usefoobarTargetsinstead offoobarLibTargets<projecname_uc>placeholder used below correspond to the name of the project upper-cased (ABCinstead ofabc)- To allow configuring your project when vendorized along other one, prefer variable with
<projecname_uc>_. This means<projecname_uc>_INSTALL_LIBRARY_DIRis better thanLIBRARY_INSTALL_DIR. - To allow user of the project to configure
*_INSTALL_DIRvariables, wrap them aroundif(DEFINED ...) - Consistently use variables (e.g
LIBRARY_INSTALL_DIRshould always be used instead oflib) - Prefer naming variable
<projecname_uc>_INSTALL_*_DIRinstead of<projecname_uc>_*_INSTALL_DIR, it make it easier to know the purpose of the variable when reading the code. - Since version is already associated with the project, there is no need to set
VERSIONvariable. Instead, you can usePROJECT_VERSIONorFOOBAR_VERSION - If starting a new project, prefer the most recent CMake version. CMake 3.13 instead of CMake 3.7
- Introduced variable
<projecname_uc>_INSTALL_CONFIG_DIR <project_name>Targets.cmakeshould not be installed usinginstall(FILES ...), it is already associated with an install rule- conditionally set
CMAKE_INSTALL_RPATH, it is valid only on Linux <project_name>Config.cmake.in:- there is no need to set
FOOBAR_LIBRARY, this information is already associated with the exportedfoobartarget - FOOBAR_LIBRARY_DIR is also not needed, this information is already associated with the exported
foobartarget - instead of setting FOOBAR_INCLUDE_DIR, the command
target_include_directoriesshould be used - remove setting of
FOOBAR_VERSION, the generate version file already takes care of setting the version.
- there is no need to set
- always specify ARCHIVE, LIBRARY and RUNTIME when declaring install rules for target. It avoid issue when switching library type. One less thing to think about.
- always specify component with your install rule. It allows user of your project to selectively install part of it only development component or only runtime one, ...
- initializing
CMAKE_BUILD_TYPEis also important, it ensures the generated Targets file are associated with a configuration (instead of having the suffix-noconfig.cmake)