PROJ
PROJ copied to clipboard
Absolute paths in proj-targets.cmake on install
Problem description
When I build and install PROJ (with CMake), its INSTALLATION-PATH/lib/cmake/proj/proj-targets.cmake
gets absolute paths for the dependencies:
#...
set_target_properties(PROJ::proj PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "PROJ_DLL="
INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
INTERFACE_LINK_LIBRARIES "D:/temp/deps/sqlite/lib/SQLite3.lib;\$<LINK_ONLY:>;D:/temp/deps/tiff/lib/tiff.lib;..."
)
# ...
As you can see, INTERFACE_LINK_LIBRARIES
contains absolute paths (and also one empty $<LINK_ONLY:>
for some reason), which makes the package non-relocatable, as these paths exist only on this machine (where it is being built and installed).
Here's how I build and configure PROJ:
$ cd /path/to/proj
$ mdir build && cd $_
$ cmake -DCMAKE_INSTALL_PREFIX="../installing" -DBUILD_APPS=0 -DBUILD_SHARED_LIBS=0 -DBUILD_TESTING=0 -DNLOHMANN_JSON_ORIGIN="external" -DCMAKE_PREFIX_PATH="d:/temp/deps/curl;d:/temp/deps/json;d:/temp/deps/sqlite;d:/temp/deps/tiff" ..
$ cmake --build . --target install --config Release
For simplicity I've put all dependencies to d:/temp/deps
. Normally I'd resolve them with Conan (and in that case proj-targets.cmake
would get absolute paths to c:\users\USERNAME\.conan\data\AND-SO-ON
).
I'm not a CMake expert, so I might be doing something wrong, but it seems to me that CMake installation procedure of PROJ is not entirely correct.
Expected output
As I understand it, this would be a correct value of the INTERFACE_LINK_LIBRARIES
inside proj-targets.cmake
:
INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:SQLite3.lib>;\$<LINK_ONLY:tiff.lib>;..."
Environment information
- PROJ version: 5b2d59b68f931303d73e742763309d258f9335d4
- Operating system:
- Windows 10 10.0.19043
- MSVC 143
- CMake 3.23.2
For static linking, I don't see much alternative than providing the full path of the dependencies. Otherwise the using program wouldn't know where to look for them. CC @dg0yt
I might be missing something, but when I statically link to other projects, they don't have full paths to dependencies in their CMake configs/targets files. Then of course I need to have their dependencies available in my system and provide paths to them in CMAKE_PREFIX_PATH
(or let Conan handle that), and after that everything works fine.
Perhaps I could ask this question differently. If I am to build PROJ with intention for it to be statically linked to, is it possible to make a relocatable CMake package for it, so it could be used on other machines, not only on the one where it was configured and built? I mean, of course it is possible, but is such scenario available/supported "out of the box"? So far I've failed to do so, and I was hoping that I've just overlooked something and that I won't need to dive into PROJ's CMake files and modify them for that purpose :)
For static linking, I don't see much alternative than providing the full path of the dependencies. Otherwise the using program wouldn't know where to look for them.
IMO there is no general problem locating static libs. What can be a problem is that library search processes may prefer shared libs over static libs, in particular in mixed linkage on non-Windows systems.
If I am to build PROJ with intention for it to be statically linked to, is it possible to make a relocatable CMake package for it ...
You point to the right page and section. But IMO this is not something which can be expected to be (already) available in general.
To make a long story it short, the solution is to switch to standardized imported targets for link libraries. These imported targets would be recreated when you use the PROJ config file, instead of using non-relocatable paths burned into the PROJ config file at build time. And these targets easily carry multi-config details (release+debug for MSVC) and transitive usage requirements (in particular link libraries for static linkage).
But the barrier is the slow transition to having standardized imported targets. PROJ relies on SQLite3, CURL, TIFF. All these package have Find Modules (and CURL provides exported config now), but standardized imported targets are not available in older version of CMake:
- CURL::libcurl: since CMake 3.12
- SQLite::SQLite3: since CMake 3.14
- TIFF::TIFF: since CMake 3.5
(Even with these targets, you cannot rely on CMake knowing the actual configuration of the CURL or TIFF. But configuration is relevant for adding the static link libraries for optional transitive dependencies such as OpenSSL or LibLZMA.)
PROJ even ships a vendored Find module for SQLite3, but this implementation doesn't provide a target.
FTR in the vcpkg package manager, relocatability of packages is achieved by a combination of patching (using targets, adding unofficial exports) and of post-build substitution of absolute paths in CMake config files.
Oh, I see. Indeed, that's not a trivial thing to implement, especially that it has to do with 3rd-party. Thank you for the explanation!
If anything, at least for me this issue certainly isn't critical, I'm sure I'll find a workaround for the time being. So if no one else asks about this, it can probably wait until better times under lower priority (can be closed too, if you'd prefer).
Reach the same issue when building the static lib for Yocto.
Handle this by adding "-DSQLITE3_LIBRARY:STRING=sqlite3" at configure time.