Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 137 additions & 75 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,79 +1,141 @@
name: CI

on:
push:
branches: [main]
tags: ['**']
paths-ignore:
- '**/*.md'
pull_request: {branches: [main]}
workflow_dispatch:
inputs:
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: false
defaults: {run: {shell: 'bash -el {0}'}} # https://github.com/marketplace/actions/setup-miniconda#important
env:
YARDL_VERSION: 0.6.3
push:
paths-ignore:
- '**/*.md'
pull_request: {branches: [main]}
workflow_dispatch:
inputs:
debug_enabled:
description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
required: false
default: 'false'

jobs:
validate:
strategy:
matrix:
cppVersion: [17]
environment: pypi
permissions: {id-token: write}
name: Validate Python and C++${{ matrix.cppVersion }} and deploy to PyPI
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: {fetch-depth: 0, submodules: recursive}
- name: strip environment.yml
run: |
cat environment.yml | grep -v "#.*\<\local\>" > temp-ci-environment.yml
- uses: conda-incubator/setup-miniconda@v3
with:
activate-environment: yardl
environment-file: temp-ci-environment.yml
- name: Install yardl
run: |
rm temp-ci-environment.yml
gh release download -R microsoft/yardl -p '*linux_x86_64.tar.gz' v$YARDL_VERSION
mkdir yardl
tar -xzf "yardl_${YARDL_VERSION}_linux_x86_64.tar.gz" -C yardl
rm "yardl_${YARDL_VERSION}_linux_x86_64.tar.gz"
echo "$PWD/yardl" >> "$GITHUB_PATH"
validate:
strategy:
matrix:
cppVersion: [17]
runs-on: ubuntu-24.04
name: Validate Python and C++${{ matrix.cppVersion }} and deploy to PyPI
env:
GH_TOKEN: ${{ github.token }}
# Enable tmate debugging of manually-triggered workflows if the input option was provided
- name: Setup tmate session if triggered
#if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
timeout-minutes: 30
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled == 'true' }}
- name: Build model
run: |
just generate
- name: Python
run: |
just run-python
- name: cpp
run: |
mkdir cpp/build
cd cpp/build
cmake -G Ninja -S .. -DHDF5_ROOT="$CONDA_PREFIX"
ninja
cd ../..
just run-cpp
- name: Copy LICENSE for deployment
run: |
cp LICENSE.txt python/LICENSE
cp LICENSE.txt cpp/LICENSE
- uses: casperdcl/deploy-pypi@v2
with:
build: python -o dist
upload: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
requirements: 'build twine packaging>=24.2' # https://github.com/pypa/twine/issues/1216
- uses: actions/upload-artifact@v4
with:
name: python-petsird
path: dist/**
PETSIRD_PREFIX: ${{ github.workspace }}/petsird-install

steps:
- name: Install System Dependencies (date-tz)
run: |
sudo apt-get update
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y universe
sudo apt-get update
sudo apt install -y libomp-dev libboost-dev libhdf5-serial-dev nlohmann-json3-dev
sudo apt-get install -y libdate-tz-dev || sudo apt-get install -y libhowardhinnant-date-dev

- name: Checkout PETSIRD
uses: actions/checkout@v4


- name: Checkout Yardl (main)
uses: actions/checkout@v4
with:
repository: microsoft/yardl
ref: main
path: yardl

- name: Setup micromamba (yardl env)
uses: mamba-org/setup-micromamba@v2
with:
environment-file: yardl/environment.yml
activate-environment: yardl

- name: Export CMake prefix path
run: |
echo "CMAKE_PREFIX_PATH=$CONDA_PREFIX;$CMAKE_PREFIX_PATH" >> $GITHUB_ENV

- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: '1.22'

- name: Build and install Yardl
run: |
cd yardl/tooling/cmd/yardl
go build
mkdir -p "$HOME/.local/bin"
install -m 755 yardl $HOME/.local/bin/yardl
echo "$HOME/.local/bin" >> $GITHUB_PATH
"$HOME/.local/bin/yardl" --version

- name: Setup tmate session if triggered
#if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
timeout-minutes: 30
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled == 'true' }}

- name: Install just
run: |
sudo apt-get update
sudo apt-get install -y cmake ninja-build just

- name: Install PETSIRD Python dependencies
run: |
micromamba install -y -n yardl -f environment.yml
micromamba install -n yardl -c conda-forge xtensor xtensor-blas openblas

- name: Generate PETSIRD sources (yardl)
run: |
micromamba run -n yardl bash -lc "
export CC=/usr/bin/gcc
export CXX=/usr/bin/g++

# Make conda packages visible to CMake
export CMAKE_PREFIX_PATH=\$CONDA_PREFIX:\$CMAKE_PREFIX_PATH
export CXXFLAGS=\"-I\$MAMBA_ROOT_PREFIX/envs/yardl/include \$CXXFLAGS\"

cd model
just generate
just run-python
just run-cpp
"

- name: Build PETSIRD C++
run: |
micromamba run -n yardl bash -lc "
cd cpp
mkdir -p build
cd build

cmake .. \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=\"\$CONDA_PREFIX\" \
-DCMAKE_INSTALL_PREFIX=\"${{ env.PETSIRD_PREFIX }}\"

cmake --build . --target install -- -j$(nproc)
"

- name: Fix yardl mistake
run: |
FILE="cpp/generated/petsird/CMakeLists.txt"
echo "🔧 Fixing yardl-generated CMakeLists.txt (removing xtensor linkage)"
sed -i.bak \
-e '/^[[:space:]]*xtensor[[:space:]]*$/d' \
"$FILE"

- name: Set up Python for PyPI
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Copy LICENSE for deployment
run: |
cp LICENSE.txt python/LICENSE
cp LICENSE.txt cpp/LICENSSE
- uses: casperdcl/deploy-pypi@v2
with:
build: python -o dist
upload: ${{ github.event_name == 'push' && startsWith(github.ref, 'refs/tags') }}
requirements: 'build twine packaging>=24.2' # https://github.com/pypa/twine/issues/1216
- uses: actions/upload-artifact@v4
with:
name: python-petsird
path: dist/**
73 changes: 67 additions & 6 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
cmake_minimum_required(VERSION 3.12.0) # older would work, but could give warnings on policy CMP0074
project(petsird VERSION 0.7.2)
project(petsird VERSION 0.7.2 LANGUAGES CXX)
include(GNUInstallDirs)
set(PETSIRD_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/PETSIRD")

include(CMakePackageConfigHelpers)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(WIN32)
add_compile_options(/W3 /WX)
Expand All @@ -19,10 +24,66 @@ endif()
# sourcesOutputDir: ../cpp/generated/petsird

add_subdirectory(generated/petsird)
# create a petsird library target
# Currently it is just empty, but allows creating target properties which are transitive
add_library(petsird)
target_link_libraries(petsird PUBLIC petsird_generated)
target_include_directories(petsird PUBLIC "${PROJECT_SOURCE_DIR}/generated")
target_include_directories(petsird_generated
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/generated>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

add_subdirectory(helpers)

add_library(PETSIRD::generated ALIAS petsird_generated)
add_library(PETSIRD::helpers ALIAS petsird_helpers)


add_library(petsird INTERFACE)
add_library(PETSIRD::petsird ALIAS petsird)

target_link_libraries(petsird
INTERFACE
PETSIRD::generated
PETSIRD::helpers
)

target_compile_features(petsird INTERFACE cxx_std_17)
Copy link
Contributor

Choose a reason for hiding this comment

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

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)

Copy link
Contributor

Choose a reason for hiding this comment

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

microsoft/yardl#261. but we can still add it ourselves


install(TARGETS petsird petsird_generated petsird_helpers
EXPORT petsirdTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

install(EXPORT petsirdTargets
NAMESPACE PETSIRD::
DESTINATION ${PETSIRD_CMAKE_DIR}
)

install(
DIRECTORY generated/petsird/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/petsird
)

install(
DIRECTORY helpers/include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)


configure_package_config_file(
cmake/PETSIRDConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/PETSIRDConfig.cmake
INSTALL_DESTINATION ${PETSIRD_CMAKE_DIR}
)

write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/PETSIRDConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)

install(FILES
${CMAKE_CURRENT_BINARY_DIR}/PETSIRDConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/PETSIRDConfigVersion.cmake
DESTINATION ${PETSIRD_CMAKE_DIR}
)
12 changes: 12 additions & 0 deletions cpp/cmake/PETSIRDConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@PACKAGE_INIT@
include(CMakeFindDependencyMacro)
find_dependency(date)
find_dependency(xtensor-blas)
if(@PETSIRD_GENERATED_USE_NDJSON@)
find_dependency(nlohmann_json)
endif()
if(@PETSIRD_GENERATED_USE_HDF5@)
find_dependency(HDF5 COMPONENTS CXX)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/petsirdTargets.cmake")
check_required_components(PETSIRD)
31 changes: 26 additions & 5 deletions cpp/helpers/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,33 @@ find_package(xtensor-blas REQUIRED)

# create a petsird_helpers library target
# Currently it is just empty, but allows creating target properties which are transitive
add_library(petsird_helpers INTERFACE)
target_link_libraries(petsird_helpers INTERFACE petsird xtensor-blas)
target_include_directories(petsird_helpers INTERFACE "${PROJECT_SOURCE_DIR}/helpers/include")
add_library(petsird_helpers ${PETSIRD_HELPERS_SOURCES})

target_include_directories(petsird_helpers
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)

target_link_libraries(petsird_helpers
PUBLIC
petsird_generated
xtensor-blas
)

add_executable(petsird_generator petsird_generator.cpp)
target_link_libraries(petsird_generator petsird_helpers)
target_link_libraries(petsird_generator PRIVATE petsird_generated petsird_helpers)

add_executable(petsird_analysis petsird_analysis.cpp)
target_link_libraries(petsird_analysis petsird_helpers)
target_link_libraries(petsird_analysis PRIVATE petsird_generated petsird_helpers)

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()
Comment on lines +25 to +34
Copy link
Contributor

Choose a reason for hiding this comment

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

why did you need this? (probably because you removed target_link_libraries)

Copy link
Author

Choose a reason for hiding this comment

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

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.

Copy link
Contributor

Choose a reason for hiding this comment

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

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