Fix CMake export and include interfaces#181
Fix CMake export and include interfaces#181NikEfth wants to merge 20 commits intoETSInitiative:mainfrom
Conversation
- Add install/export rules for PETSIRD targets - Provide PETSIRDConfig.cmake and version file - Fix include directories using BUILD/INSTALL interfaces - Export PETSIRD::petsird target for find_package() - Prepare PETSIRD for external consumers (STIR -- this has been going on for a while )
for more information, see https://pre-commit.ci
|
Finally, this took me 2 week of bouncing around and many problems in STIR: Very brief summary. This PR fixes PETSIRD integration issues by properly exporting PETSIRD as a CMake package instead of relying on in-tree submodule builds. Specifically, it: ⸻ Background / Motivation PETSIRD was previously consumed via a submodule and built inside STIR, which caused: These issues became visible once CI enabled stricter sanitizers and newer compilers. Exporting PETSIRD as a proper CMake package ensures a single canonical definition of all PETSIRD/STIR types across the entire build. |
|
Further to the previous posts, While PETSIRD built correctly on my PC, it failed when used as an external dependency in CI. Several independent problems linked.
Fixes:
|
KrisThielemans
left a comment
There was a problem hiding this comment.
I think the export is a good idea. It'll also make it easier for putting on conda etc. However, I think it'd be best to export 2 targets: PETSIRD::generated and PETSIRD::helpers.
Potentially, we should INSTALL the examples.
And I guess we need a simple CI test for this as well. sorry.
cpp/helpers/CMakeLists.txt
Outdated
| find_package(xtensor-blas REQUIRED) | ||
| find_package(xtensor REQUIRED) | ||
| # find_package(xtensor-blas REQUIRED) | ||
| find_package(BLAS REQUIRED) |
There was a problem hiding this comment.
I disagree.
geometry.huses
#include <xtensor-blas/xlinalg.hpp>
helpersdepends ongenerated, which hasWe don't usefind_package(xtensor ${XTENSOR_MINIMUM_VERSION} REQUIRED)
BLASdirectly.xtensor-blaswill requirextensor(and I see no reason we need its variables, see below)
There was a problem hiding this comment.
I commented out xtensor-blas because of an unwanted lxtensor linkage (When linking with STIR, in a conda environemet I was gettign a lxtensor ), but that’s a packaging issue. I will bring this back now and see how it goes. Maybe other changes resolved this.
cpp/helpers/CMakeLists.txt
Outdated
|
|
||
| target_include_directories(petsird_helpers | ||
| INTERFACE | ||
| ${xtensor_INCLUDE_DIRS} |
There was a problem hiding this comment.
should not be necessary. Depending on xtensor-blas should take care of this
There was a problem hiding this comment.
See the comment before. Xtensor is headers only, but somehow STIR, for example:
| collect2: error: ld returned 1 exit status
| gmake[2]: *** [src/test/numerics/CMakeFiles/test_IR_filters.dir/build.make:121: src/test/numerics/test_IR_filters] Error 1
| gmake[1]: *** [CMakeFiles/Makefile2:8070: src/test/numerics/CMakeFiles/test_IR_filters.dir/all] Error 2
| gmake[1]: *** Waiting for unfinished jobs....
/root/micromamba/envs/yardl/bin/ld: cannot find -lxtensor: No such file or directory
| collect2: error: ld returned 1 exit status
| gmake[2]: *** [src/test/numerics/CMakeFiles/test_BSplines.dir/build.make:121: src/test/numerics/test_BSplines] Error 1
| gmake[1]: *** [CMakeFiles/Makefile2:8102: src/test/numerics/CMakeFiles/test_BSplines.dir/all] Error 2```
There was a problem hiding this comment.
I have to note that the error in the comment above was just an instance of a torrent of similar problems.
| foreach(t petsird petsird_generated petsird_helpers) | ||
| if(TARGET ${t}) | ||
| get_target_property(_libs ${t} INTERFACE_LINK_LIBRARIES) | ||
| if(_libs) | ||
| list(FILTER _libs EXCLUDE REGEX "xtensor") | ||
| set_target_properties(${t} | ||
| PROPERTIES INTERFACE_LINK_LIBRARIES "${_libs}") | ||
| endif() | ||
| endif() | ||
| endforeach() |
There was a problem hiding this comment.
why did you need this? (probably because you removed target_link_libraries)
There was a problem hiding this comment.
To undo an overly-aggressive dependency propagation introduced by generated / helper targets.
xtensor is header-only
However… Some targets propagate xtensor via INTERFACE_LINK_LIBRARIES
Something like:
INTERFACE_LINK_LIBRARIES xtensor::xtensor
This becomes a real problem in STIR / STIR2PETSIRD. Header-only deps should not force downstream linking.
There was a problem hiding this comment.
As long as xtensor is header-only, we could use the same trick as https://github.com/UCL/STIR/blob/ec3a5670f9b63cb10f4bebce6edf22d6f028a6fb/src/buildblock/CMakeLists.txt#L125-L137, i.e. only add the include path.
However, this is all quite ugly. I'd rather avoid it as much as possible.
As long as we have find_dependency(xtensor) in the Config.cmake, there should be no problem
cpp/CMakeLists.txt
Outdated
| date::date | ||
| ) | ||
|
|
||
| target_compile_features(petsird PUBLIC cxx_std_17) |
There was a problem hiding this comment.
Interesting. Do we have to do this explicitly?
There was a problem hiding this comment.
I thought it would be a good idea. idk? Initially I was getting many mysterious compiler errors and tried to cover all bases.
NikEfth
left a comment
There was a problem hiding this comment.
I will try step-by-step to bring lxtensor-blas back and see when linking becomes an issue.
cpp/helpers/CMakeLists.txt
Outdated
|
|
||
| target_include_directories(petsird_helpers | ||
| INTERFACE | ||
| ${xtensor_INCLUDE_DIRS} |
There was a problem hiding this comment.
I have to note that the error in the comment above was just an instance of a torrent of similar problems.
| foreach(t petsird petsird_generated petsird_helpers) | ||
| if(TARGET ${t}) | ||
| get_target_property(_libs ${t} INTERFACE_LINK_LIBRARIES) | ||
| if(_libs) | ||
| list(FILTER _libs EXCLUDE REGEX "xtensor") | ||
| set_target_properties(${t} | ||
| PROPERTIES INTERFACE_LINK_LIBRARIES "${_libs}") | ||
| endif() | ||
| endif() | ||
| endforeach() |
There was a problem hiding this comment.
To undo an overly-aggressive dependency propagation introduced by generated / helper targets.
xtensor is header-only
However… Some targets propagate xtensor via INTERFACE_LINK_LIBRARIES
Something like:
INTERFACE_LINK_LIBRARIES xtensor::xtensor
This becomes a real problem in STIR / STIR2PETSIRD. Header-only deps should not force downstream linking.
|
@KrisThielemans I am about to finish the CI yml and I think I have to apologize but my yml skill are not as good as yours (or @casperdcl ) and I make just as typing commands in the terminal :) I could not modify yours successfully, running to all sort of issues. Have a look at mine and let me know if I can improve. |
Co-authored-by: Kris Thielemans <[email protected]>
Co-authored-by: Kris Thielemans <[email protected]>
Co-authored-by: Kris Thielemans <[email protected]>
Export 2 targets: PETSIRD::generated and PETSIRD::helpers and PETSIRD as interface target. Reverted Xtesnor dependency
KrisThielemans
left a comment
There was a problem hiding this comment.
I have no idea what you tried to change in CI. I see you use APT, but then conda anyway. I see no fantastic reason to try and avoid conda for the moment. (There's microsoft/yardl#154)
I can't see anything else in the ci.yml that we immediately need for testing functionality of this PR.
I'd therefore suggest to revert ci.yml, but maybe I'm missing something.
Instead, I think we need to do a "ninja install" and add a new step which then links an independent program that against the installed version to test (similar to what we do for the STIR example here).
Maybe we can create cpp/example/ (or examples/cpp I suppose) with a cut-down version of the analysis.cpp.
I can do that, if you prefer.
| PETSIRD::helpers | ||
| ) | ||
|
|
||
| target_compile_features(petsird INTERFACE cxx_std_17) |
There was a problem hiding this comment.
looks like this is set minimum version, and is therefore useful, see https://stackoverflow.com/questions/70667513/cmake-cxx-standard-vs-target-compile-features and in particular https://stackoverflow.com/questions/70667513/cmake-cxx-standard-vs-target-compile-features#comment135186815_70667652
However, probably should be added to the generated library already. (In fact, should be in the generated CMakeLists.txt)
There was a problem hiding this comment.
microsoft/yardl#261. but we can still add it ourselves
| foreach(t petsird petsird_generated petsird_helpers) | ||
| if(TARGET ${t}) | ||
| get_target_property(_libs ${t} INTERFACE_LINK_LIBRARIES) | ||
| if(_libs) | ||
| list(FILTER _libs EXCLUDE REGEX "xtensor") | ||
| set_target_properties(${t} | ||
| PROPERTIES INTERFACE_LINK_LIBRARIES "${_libs}") | ||
| endif() | ||
| endif() | ||
| endforeach() |
There was a problem hiding this comment.
As long as xtensor is header-only, we could use the same trick as https://github.com/UCL/STIR/blob/ec3a5670f9b63cb10f4bebce6edf22d6f028a6fb/src/buildblock/CMakeLists.txt#L125-L137, i.e. only add the include path.
However, this is all quite ugly. I'd rather avoid it as much as possible.
As long as we have find_dependency(xtensor) in the Config.cmake, there should be no problem
|
I had to change the CI, because I could not make it to compile yardl. I tried. If you can tell me how to make this work, I am happy to revert.
I do this quite extensively in STIR and STIR2PETSIRD. But, sure we can do it here, too. |
Changes in this pull request
When PETSIRD is used as a subproject and exported by a parent project, CMake
requires that exported targets do not reference source-tree paths and that all
public dependencies are also exported.
This PR fixes those issues while keeping standalone PETSIRD builds unchanged.
Related issues
Checklist before requesting a review
Please tick the following: