Documenting Best Practices For CMake Packages Development
A per https://gitlab.kitware.com/ben.boeckel
Regarding the bit of a rat's nest issue: #17212 (comment 308671)
And heeding advice on breaking above out into at least three separate issues of which this is one. This has been adapted to try and focus 3rd party lib development, better best practices, and documentation to aid in that goal. Removed from below were the Windows run time name mangling that is also desired in above.
-
Fix inconsistent documentation for cmake-packages and CMakePackageConfigHelpers
-
Fix or deprecate and write a new
CMakePackageConfigHelpers
to aid in standard install dir for includes and package files (lib/cmake/foo-ver
). Which preferably does not give an option to user as were to install and enforces versioning preferably for include dirs, lib names, and package files install dir. -
Find a way to guide 3rd party package developers to add library versions to the name (name mangeling) libfoo-[ver].lib for 3rd party packages.
Request Explanation:
Inconsistent Documentation:
There is some inconsistent and misleading documentation at
https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html
and
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html?highlight=package#
which conflicts with Kitware's own use in VTK and ITK
${LIB_INSTALL_DIR}/Foo/cmake
and not
${LIB_INSTALL_DIR}/cmake/Foo-<version>
ie version = 1.23
as an exercise:
Search:
https://cmake.org/cmake/help/latest/module/CMakePackageConfigHelpers.html?highlight=package
and
https://cmake.org/cmake/help/latest/manual/cmake-packages.7.html?highlight=package
for
"/cmake"
Notice anything?
say:
INSTALL_DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake
and
<prefix>/lib/cmake/foo-1.2/FooConfig.cmake
but then this bit later on
set(ConfigPackageLocation lib/cmake/ClimbingStats)
install(EXPORT ClimbingStatsTargets
FILE
ClimbingStatsTargets.cmake
NAMESPACE
Upstream::
DESTINATION
${ConfigPackageLocation}
)
Yep one of these is not like the other. Why version one foo and not the other foo or ClimbingStats?
So the destination was almost right at least if looking at where Kitware puts VTK and ITK bits, but not right if you read the CMake documentation. Well some of it. It is clearly inconsistent.
From the doc we could
Foo/Cmake
or
cmake/foo-1.2
It should be clear which one is preferred (cmake-packages versioned version lib/cmake/package-ver
if Kitware's own practices are used) at least have macros that perform "better" best practices.
Why is not lib/cmake/Foo-${version}
enforced by CMake macro? but rather leaving 3rdParty lib developer to set to to whatever they want... and they do. DCMTK did by putting it in share.dcmtk/DCMTKConfig.cmake
and hey why not it's a good a place as any. Why should it be not in a standard location? Like when your trying to figure out why DCMTK_DIR
is /usr
which is not even in the install tree on windows you want to be able to find the package file to figure out what's going on or more the point what's not going on in that file.
Lack of enforcement / guidance on include directory and lib name versioning:
such as:
${INCLUDE_INSTALL_DIR}/Foo-1.23/foo.h
and
libFoo.1.23.lib
I am currently having discussions on use of LIBPATH
, LINK_DIRECTORIES
, find_library
, and full lib paths regarding libs and versioning and name mangling may go along way to fix that problem. Maybe then CMake could give me access to LIBPATH
at a target level (target_link_directories
desired) and help fix the command line build path problem in ITK (try building ITK in a somewhat nested user folder). Ok so there are two problems tied up here and ITK does at least version it's libs. Also new versions of other third party libs blasting away older versioned include directories.
Use of project() command:
Use of project( proj-name VERSION 2.1)
where version has no effect on CMAKE_INSTALL_PREFIX
allowing new versions of 3rdParty libs to be blasted away by default (at least if ver info is not accounted for in include, lib, and package name versioning). So I am sure VERSION
does something here, just not what may be needed such as change install path or decorate include dirs or postpend version info to libs. It creates PROJECT_VERSION
macros just after you need them that would sure be useful in setting the default CMAKE_INSTALL_PREFIX
when project is called so you get it after you need it then have to set CMAKE_INSTALL_PREFIX
to append version manually (and some do... keyword some) for those that like to install to Program Files. This could be automatic.
Here's the option as I understand it to date (both should work):
set(VERSION 1.2.3)
package( mypack-${VERSION} VERSION ${VERSION} )
or
set(VERSION 1.2.3)
package( mypack VERSION ${VERSION} )
set(CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}-${<PROJECT-NAME>_VERSION_MAJOR}.<PROJECT-NAME>_VERSION_MINOR.<PROJECT-NAME>_VERSION_PATCH.<PROJECT-NAME>_VERSION_TWEAK)
Which is meant to be used? Neither?
Separation of Release and Debug name mangling:
The RELEASE
vs DEBUG
same lib name problem with out use of CMAKE_<CONFIG>_POSTFIX
use of which is optional (some FLTK, I believe, roll their own and you end up with a double d lib - dd.lib).
How about for children of superbuild projects?
How about for the user of a 3rd party library which has multiple superbuild child projects / dependencies the Russian doll/onion of superbuilds?
It is increasingly difficult to reach into superbuilds or superbuilds of superbuilds and change lib names to any desired naming convention or really much of anything for that matter.
Guidance to 3rd party lib developers:
If not given good direction and guidance people (3rd party package devs) will do and have done what whatever they want. This goes to the lack of clear direction for 3rd party lib developers to include things like lib version into their library and include directory naming convention or postpend version in project() calls so as to set CMAKE_INSTALL_PREFIX
to say ${CMAKE_INSTALL_PREFIX}-1.2.3
. Possibly a check list to lib devs:
- Version your include dirs
- Ensure lib versions
- Version your package files dir
- post pend version to
CMAKE_INSTALL_PREFIX
- Don't post pend d for debug libs instead rely on
CMAKE_DEBUG_POSTIFX
- actually test it to make sure it works and plays nice with other versions with out writing over them. ... ok yes i am griping :-(. give me at least that.