Modify CMake; cmake-package (doc); CMakePackageConfigHelper macros and doc; and project() to better support best practies for package maintainers
Request Distilled:
- 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 enforce library versions names for 3rd party packages in core CMake
- Modify or add command opt to project() for default append of version to
CMAKE_INSTALL_PREFIX
to say${CMAKE_INSTALL_PREFIX}-ver
automatically. - Provide mechanism for library and exe name mangling for VS versions and runtimes including in Superbuilds and Superbuilds of Superbuilds. This is to say a mechanism to reach into superbuilds or mod default CMake to support standard (boost like) name mangling. An CMAKE_VAR allowing config of any cmake var that would span superbuilds of superbuilds might prove usefull.
- Provide
CMAKE_INSTALL_PREFIX_<CONFIG>
Debug/Release to allow re-vectoring of entire tree in VS when switching Debug/Release in VS.
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. Not that this is all that is required on Windows such as the need for vs runtime version name mangling and for superbuilds to realize the need for a build (note I did not say rebuild as what the prior vs ver build should not be overwritten if new VS ver is then selected). 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) and how can one spec a complete boost like lib version name for 3rd party libs? 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.
Debug EXE generation:
For exe's if you want separate debug and release to be generated one has to:
set_target_properties(someexe PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
But what if you want the 3rd Party project you just downloaded to generate it so as to attach a debugger? You can do it for libs but not exe's as CMAKE_<CONFIG>_POSTFIX
setting has no effect on exe's except the build system will happily overwrite the release version.
Visual Studio Runtimes and superbuilds:
The problem of visual studio runtimes vc120 and mt vs mtd which boost lib naming convention handles with names like:
boost_system-vc120-mt-1_60.lib
if you have seen errors like:
error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MDd_DynamicDebug' doesn't match value 'MD_DynamicRelease' in some.obj
or say
LNK2038: mismatch detected for '_MSC_VER': value '1600' does not match value '1700' when linking to itk or vtk after switching VS versions in build tree.
CMake superbuild will tell you it's installed and built but is it? Well all the lib names are there of the correct version, but that version is not all that is needed and VS will certainly contradict CMake. I think actually CMake contradicts is self here as when rebuilding the cache the SuperBuild/ExternalProject_Add should sense this and does not.
If you have been there you know right about now what I am talking about, can CMake handle the problem from a build and packaging name mangling perspective. I have been there when using multiple VS versions on same build tree rebuilds when switching tools this can get a little irritating when CMake Superubild does not recognize the need to rebuild, but even if it did it would be writing over build files. Name decorating keeps host from running incorrect lib or compiling over another or using the wrong lib to link that was previously built. Some arguments could be made for using CMAKE_<CONFIG>_POSTFIX
, but what about reaching into a superbuild of superbuild (VMTK)? There I have to checkout tree and patch it myself and store in my own git repo.
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:
1 Version your include dirs
2 Ensure lib versions
3 version your package files dir
4 post pend version to CMAKE_INSTALL_PREFIX
5 Don't post pend d for debug libs instead rely on CMAKE_DEBUG_POSTIFX
6 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.
CMAKE_INSTALL_PREFIX_<CONFIG>
on windows builds:
If there was an CMAKE_INSTALL_PREFIX_<CONFIG>
(release/build) this way the entire release/build could be re-vectored. Surely I can rerun CMake and do, but what about when switching Debug/Release in VS? It would make it easier. How about the SuperBuilds and SuperBuilds of SuperBuilds? For superbuilds of superbuilds not supporting debug postfix on libs (by not passing flag to ExternalProject_Add calls) makes it difficult switching release/debug. This could be one way around the current problem.
CMAKE_INSTALL_PREFIX
set to same directory for multiple 3rd party installs:
There are people out there that override CMAKE_INSTALL_PREFIX
to say:
set( CMAKE_INSTALL_PREFIX ${CURRENT_LISTS_DIR}/install )
set( INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} )
and in External Project Adds:
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${INSTALL_PREFIX}
To put all build/dev bits in local directory to say C:\projects\project1
/build
and /install
. as to not muck up the host. Then its just a one directory (C:\projects\project1
) delete to clean host of crusty bits. Some don't necessarily like 3rd party libs in Program Files but rather consolidate 3rd party bits and multiple versions of same 3rd party libs into project tree. You will certainly see the inconsistencies and problems with CMake packaging if all 3rd Party packages are put into one install (bin, lib, include, share) directory and there are very valid reasons to do so. I should in theory be allowed to do this right? I am allowed to change CMAKE_INSTALL_PREFIX
as a user.
Hope is to not blast away header files, package files, and libs when there is an CMAKE_INSTALL_PREFIX
overlay across multiple 3rd party library versions and when switching VS vers and runtimes.