Skip to content

Make PROJ config more relocatable#4757

Draft
dbs4261 wants to merge 10 commits into
OSGeo:masterfrom
dbs4261:install-fixes
Draft

Make PROJ config more relocatable#4757
dbs4261 wants to merge 10 commits into
OSGeo:masterfrom
dbs4261:install-fixes

Conversation

@dbs4261
Copy link
Copy Markdown
Contributor

@dbs4261 dbs4261 commented Apr 17, 2026

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].cmake files that are used by CMake's find_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 of BasicConfigVersion-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 the PROJ4::proj target. The PROJ4::proj target is only provided by find_package(PROJ4) now. The reverse also applies to PROJ::proj not being available when find_package(PROJ4) is used.

@dbs4261
Copy link
Copy Markdown
Contributor Author

dbs4261 commented Apr 17, 2026

@mwtoews Can you check if this is what you were looking for?

@mwtoews
Copy link
Copy Markdown
Member

mwtoews commented Apr 17, 2026

@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 install(CODE ...) here too.

@dbs4261
Copy link
Copy Markdown
Contributor Author

dbs4261 commented Apr 17, 2026

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.

Comment thread cmake/CMakeLists.txt
set (MSVC_TOOLSET_MAJOR 0)
endif ()

include(CMakePackageConfigHelpers)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

dbs4261 added 2 commits April 20, 2026 12:37
…install manifest to using install(FILES <FILE> RENAME <OUTNAME>).
…gets added to the install manifest with file(INSTALL ...)
Comment thread scripts/CMakeLists.txt
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})
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

install_manifest_extra.txt is no longer used. why ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@dbs4261
Copy link
Copy Markdown
Contributor Author

dbs4261 commented Apr 23, 2026

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 ${pcfiledir} derived variable. Documentation

@rouault rouault marked this pull request as draft April 23, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants