Make PROJ config more relocatable#4757
Conversation
…s BasicConfigVersion-SameMajorVersion.cmake.in to get support for version ranges.
…file for relocatable packages
…le cmake package config files.
|
@mwtoews Can you check if this is what you were looking for? |
Yes, it's along the lines of a dynamic install, e.g. I was looking at this issue and I see |
…-config file at install time.
|
Fingers crossed it works here 🤞. Otherwise, I'll need some help learning how to run CI locally so I can figure out why I keep running into CMake issues in CI but not on my local build. |
| set (MSVC_TOOLSET_MAJOR 0) | ||
| endif () | ||
|
|
||
| include(CMakePackageConfigHelpers) |
There was a problem hiding this comment.
Thanks for looking into CMakePackageConfigHelpers, it was on "my list" to look at eventually. You could probably notice that much of the CMake setup was started in 2014 based on CMake 2.6.0, then incrementally modernised over time, so some of these original configurations were probably needed at the time, but now there are better helpers for modern setups.
There was a problem hiding this comment.
I'm going to wrap up this PR so I can have the relocation I need for my job. I totally get the challenge, it seems like each section gets modernized a bit whenever it is touched so the structure just isn't cohesive. I'll try and make further changes when I have time.
…install manifest to using install(FILES <FILE> RENAME <OUTNAME>).
…gets added to the install manifest with file(INSTALL ...)
| install(SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/install_bash_completions.cmake) | ||
| foreach (program IN LISTS BASH_COMPLETION_PROGRAMS) | ||
| install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${program}-bash-completion.sh | ||
| RENAME ${program} DESTINATION ${BASH_COMPLETIONS_DIR}) |
There was a problem hiding this comment.
install_manifest_extra.txt is no longer used. why ?
There was a problem hiding this comment.
Fair question. In short, by figuring out how to install the proj.pc file, I learned a lot about how CMake installs a project. Here's what I learned for the sake of posterity:
install(FILES) is the intended mechanism for installing files 🤯. It also automatically adds those files to install_manifest.txt, though this behavior is not documented. Now, the install_bash_completions.cmake.in template was run at install time for each program with bash completions. All that script does is copy a file to its install destination, rename that file, and then add it to a list of files in install_manifest_extra.txt, mimicking CMake's internal install manifest file. The entire purpose of creating that extra manifest is so the uninstall target knows what files to delete. Because, the bash completions are now handled by CMake's internal system, the extra manifest is no longer needed.
The proj.pc installation was where things got weird. I use install(CODE) which is essentially the same as install(SCRIPT). These inject CMake code into the cmake_install.cmake script that CMake generates. These scripts are run when CMake installs the project. The only difference between install(SCRIPT) and install(CODE) is that install(SCRIPT) has an intermediate file of CMake code that gets included in the generated cmake_install.cmake script, while install(CODE) pastes the provided string into the cmake_install.cmake script verbatim. It just cuts out a step. The problem is that we need to generate the contents of proj.pc at install time so we know what the INSTALL_PREFIX is. So what I do is generate the proj.pc file as normal at configure time, and again to a temporary directory at install time. However, I can't use install(FILES) because it works by creating the cmake_install.cmake script (which we are currently executing) that is generated at configure time instead of actually installing the file. So I dug deeper and looked at how those generated cmake_install.cmake scripts work. install(FILES) generates a call to file(INSTALL) which does the actual copying of the file, but it uses some undocumented internal options. The documentation forfile(INSTALL) lacks detail in a lot of ways. We can install the file using only the public options, but an undocumented side effect of file(INSTALL) is that it adds the file path(s) to the CMAKE_INSTALL_MANIFEST_FILES variable, which eventually gets written to install_manifest.txt. This means, I can generate the file at install time, then use file(INSTALL) to install the file to the correct location, and have that installation recorded in the manifest.
|
This branch is not ready to merge. I was looking through another project and realized there is a much simpler way to deal with the pkg-config file. The prefix can be set relative to the pkg-config file location using the |
Related to but not addressing #4752, this PR updates the CMake scripts used to generate pkg-config's proj.pc file as well as the
proj-config[-version].cmakefiles that are used by CMake'sfind_package. Firstly, proj.pc is now relocatable as it gets regenerated at install time. The source template for proj-config-version.cmake has been converted to be based off the CMake 4.3 version ofBasicConfigVersion-SameMajorVersion.cmake.in, to allow for version ranges. The proj-config.cmake template has also been updated to be generated with configure_package_config_file which allows for better relocation and simplification of the template. Note that find_package will now fail if CMake 2.6.4 or earlier is used.Additionally, this will break any build scripts that mistakenly
find_package(PROJ)and then use thePROJ4::projtarget. ThePROJ4::projtarget is only provided byfind_package(PROJ4)now. The reverse also applies toPROJ::projnot being available whenfind_package(PROJ4)is used.