Skip to content
Merged
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
93 changes: 93 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,96 @@ jobs:
flags: windows
fail_ci_if_error: true
token: ${{ secrets.CODECOV_TOKEN }}

zlib-only-host-build:
name: zlib-only host (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4

- name: Cache vcpkg (Windows)
if: runner.os == 'Windows'
uses: actions/cache@v4
with:
path: ${{ github.workspace }}\vcpkg_cache
key: zlib-only-vcpkg-${{ runner.os }}-${{ hashFiles('.github/workflows/ci.yml') }}

- name: Install dependencies (Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y \
cmake \
g++ \
ninja-build \
zlib1g-dev \
libgtest-dev

- name: Install dependencies (macOS)
if: runner.os == 'macOS'
run: |
brew update
brew install ninja zlib googletest

- name: Install dependencies (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: |
choco install ninja -y
New-Item -ItemType Directory -Force "$env:GITHUB_WORKSPACE\vcpkg_cache" | Out-Null
git clone https://github.com/microsoft/vcpkg "$env:GITHUB_WORKSPACE\vcpkg"
& "$env:GITHUB_WORKSPACE\vcpkg\bootstrap-vcpkg.bat"
$env:VCPKG_BINARY_SOURCES="clear;files,$env:GITHUB_WORKSPACE\vcpkg_cache,readwrite"
& "$env:GITHUB_WORKSPACE\vcpkg\vcpkg.exe" install `
zlib `
gtest `
--triplet x64-windows

- name: Setup MSVC environment (Windows)
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1

- name: Configure (Ubuntu)
if: runner.os == 'Linux'
run: |
cmake -S . -B build-zlib-only \
-G Ninja \
-DTRX_USE_CONAN=OFF \
-DTRX_BUILD_TESTS=ON \
-DTRX_BUILD_EXAMPLES=ON \
-DTRX_ENABLE_NIFTI=ON \
-DCMAKE_BUILD_TYPE=Release

- name: Configure (macOS)
if: runner.os == 'macOS'
run: |
BREW_PREFIX="$(brew --prefix)"
cmake -S . -B build-zlib-only \
-G Ninja \
-DTRX_USE_CONAN=OFF \
-DTRX_BUILD_TESTS=ON \
-DTRX_BUILD_EXAMPLES=ON \
-DTRX_ENABLE_NIFTI=ON \
-DCMAKE_PREFIX_PATH="${BREW_PREFIX}" \
-DCMAKE_BUILD_TYPE=Release

- name: Configure (Windows)
if: runner.os == 'Windows'
run: >
cmake -S . -B build-zlib-only
-G Ninja
-DTRX_USE_CONAN=OFF
-DTRX_BUILD_TESTS=ON
-DTRX_ENABLE_NIFTI=ON
-DCMAKE_BUILD_TYPE=Release
-DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake

- name: Build
run: cmake --build build-zlib-only --config Release

- name: Test
run: ctest --test-dir build-zlib-only --output-on-failure -C Release
43 changes: 41 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ option(TRX_ENABLE_CLANG_TIDY "Run clang-tidy during builds" OFF)
option(TRX_ENABLE_INSTALL "Install trx-cpp targets" ${TRX_IS_TOP_LEVEL})
option(TRX_BUILD_DOCS "Build API documentation with Doxygen/Sphinx" OFF)
option(TRX_ENABLE_NIFTI "Enable optional NIfTI header utilities" ${TRX_BUILD_EXAMPLES})
option(TRX_FETCH_EIGEN "Fetch Eigen3 via FetchContent if not found" ON)

if(TRX_ENABLE_CLANG_TIDY)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
Expand Down Expand Up @@ -127,8 +128,27 @@ else()
list(PREPEND CMAKE_PREFIX_PATH "${Eigen3_ROOT}")
endif()
find_package(Eigen3 3.4 CONFIG QUIET)
if(NOT Eigen3_FOUND)
find_package(Eigen3 REQUIRED) # try module mode
if(NOT TARGET Eigen3::Eigen)
# Try module mode for distributions that ship FindEigen3.cmake.
find_package(Eigen3 3.4 QUIET MODULE)
endif()
if(NOT TARGET Eigen3::Eigen AND TRX_FETCH_EIGEN)
message(STATUS "Eigen3 not found; fetching v3.4.0")
# Eigen 3.4.0's CMakeLists.txt unconditionally enters blas/ and lapack/
# which call enable_language(Fortran). Use SOURCE_SUBDIR to skip running
# Eigen's CMake entirely — Eigen is header-only so we just need the
# include path.
FetchContent_Declare(
eigen
URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
SOURCE_SUBDIR _nonexistent
)
FetchContent_MakeAvailable(eigen)
add_library(Eigen3::Eigen INTERFACE IMPORTED)
set_target_properties(Eigen3::Eigen PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${eigen_SOURCE_DIR}"
)
endif()
# Create an imported target if the package did not provide one (module mode)
if(NOT TARGET Eigen3::Eigen AND EXISTS "${EIGEN3_INCLUDE_DIR}")
Expand All @@ -137,6 +157,9 @@ else()
INTERFACE_INCLUDE_DIRECTORIES "${EIGEN3_INCLUDE_DIR}"
)
endif()
if(NOT TARGET Eigen3::Eigen)
message(FATAL_ERROR "Eigen3 target not found. Install Eigen3 or set TRX_FETCH_EIGEN=ON.")
endif()
set(TRX_EIGEN3_TARGET Eigen3::Eigen)
endif()

Expand Down Expand Up @@ -277,6 +300,22 @@ if(TRX_BUILD_DOCS)
endif()

# ── Installation and package config ─────────────────────────────────────────
# Installation requires that link dependencies are IMPORTED targets (so they
# don't need to be in the export set). This is the case when libzip and Eigen
# were found via find_package (libzip::zip, Eigen3::Eigen). When they were
# built via FetchContent (bare "zip" target), installation is not supported —
# the FetchContent path is a developer/CI convenience, not an installable
# configuration.
if(TRX_ENABLE_INSTALL AND TARGET zip)
get_target_property(_zip_imported zip IMPORTED)
if(NOT _zip_imported)
message(STATUS "trx-cpp: skipping install — libzip was built via FetchContent. "
"Install libzip separately and reconfigure to enable installation.")
set(TRX_ENABLE_INSTALL OFF)
endif()
unset(_zip_imported)
endif()

if(TRX_ENABLE_INSTALL)
set(TRX_INSTALL_CONFIGDIR "${CMAKE_INSTALL_LIBDIR}/cmake/trx-cpp")

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ A C++17 library for reading, writing, and memory-mapping the [TRX tractography f

## Quick start

**Dependencies:** a C++17 compiler, [libzip](https://libzip.org/), [Eigen 3.4+](https://eigen.tuxfamily.org/)
**Dependencies:** a C++17 compiler and zlib (`zlib1g-dev` / `zlib-devel` / Homebrew `zlib`). `libzip` and Eigen 3.4+ are found locally when available, otherwise fetched automatically by CMake.

```cmake
# CMakeLists.txt
Expand Down
1 change: 1 addition & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ coverage:
status:
project:
default:
informational: true
paths:
- "include/trx"
- "src"
Expand Down
16 changes: 7 additions & 9 deletions docs/building.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ Dependencies
Required:

- C++17 compiler
- libzip
- Eigen3
- zlib (required by libzip)


Installing dependencies
------------------------

The examples below include GoogleTest, which is only required when building
the tests. Ninja is optional but recommended. zlib is only required for the
NIfTI I/O features.
the tests. Ninja is optional but recommended. libzip and Eigen are resolved by
CMake: it uses local installs when present and otherwise fetches them.

On Debian-based systems the zip tools have been split into separate packages
on recent Ubuntu versions.
Expand All @@ -25,8 +24,6 @@ on recent Ubuntu versions.

sudo apt-get install \
zlib1g-dev \
libeigen3-dev \
libzip-dev \
zipcmp \
zipmerge \
ziptool \
Expand All @@ -37,15 +34,15 @@ On Mac OS, you can install the dependencies with brew:

.. code-block:: bash

brew install libzip eigen googletest ninja zlib
brew install googletest ninja zlib


On Windows, you can install the dependencies through vcpkg and chocolatey:

.. code-block:: powershell

choco install ninja -y
vcpkg install libzip eigen3 gtest zlib
vcpkg install gtest zlib


Building to use in other projects
Expand All @@ -70,6 +67,7 @@ Key CMake options:
- ``TRX_BUILD_DOCS``: Build docs with Doxygen/Sphinx (default OFF)
- ``TRX_ENABLE_CLANG_TIDY``: Run clang-tidy during builds (default OFF)
- ``TRX_USE_CONAN``: Use Conan setup in ``cmake/ConanSetup.cmake`` (default OFF)
- ``TRX_FETCH_EIGEN``: Fetch Eigen3 with FetchContent when not found locally (default ON)

To use trx-cpp from another CMake project after installation:

Expand Down Expand Up @@ -103,7 +101,7 @@ Building for testing

Tests require GTest to be discoverable by CMake (e.g., via a system package or
``GTest_DIR``). If GTest is not found, tests will be skipped.
NIfTI I/O tests additionally require zlib to be discoverable (``ZLIB::ZLIB``).
zlib must be discoverable by CMake (``ZLIB::ZLIB``), including for NIfTI I/O.


Building documentation:
Expand Down
6 changes: 4 additions & 2 deletions docs/quick_start.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ Prerequisites

- A C++17 compiler (GCC ≥ 7, Clang ≥ 5, MSVC 2019+)
- CMake ≥ 3.14
- `libzip <https://libzip.org/>`_
- `Eigen 3.4+ <https://eigen.tuxfamily.org/>`_
- zlib development headers/libraries

``libzip`` and ``Eigen 3.4+`` are discovered from the local system when
available and fetched automatically by CMake otherwise.

See :doc:`building` for platform-specific installation commands.

Expand Down
Loading