diff --git a/packages/HighFive/.github/run_examples.sh b/packages/HighFive/.github/run_examples.sh
index 77861f38846c279d551ec355b481892b34d4f89a..9af9a6ef1ba930f00b6c4b3d75265a67a06cfe4d 100755
--- a/packages/HighFive/.github/run_examples.sh
+++ b/packages/HighFive/.github/run_examples.sh
@@ -1,6 +1,6 @@
 #! /usr/bin/env bash
 
-set -e
+set -eu
 
 if [[ $# -eq 0 ]]
 then
diff --git a/packages/HighFive/.github/workflows/ci.yml b/packages/HighFive/.github/workflows/ci.yml
index 8730ed4104d319675090a633f66b18041631269a..49f415e829d3a1eaa17974da656634d8466aca9f 100644
--- a/packages/HighFive/.github/workflows/ci.yml
+++ b/packages/HighFive/.github/workflows/ci.yml
@@ -7,12 +7,14 @@ concurrency:
 on:
   push:
     branches:
-      - ci_test
-      - release/**
+      - master
+      - main
+      - v2.x
   pull_request:
     branches:
       - master
-      - release/**
+      - main
+      - v2.x
     paths-ignore:
       - '**.md'
       - '**.rst'
@@ -41,22 +43,21 @@ jobs:
           - config:
               os: ubuntu-20.04
               pkgs: ''
-              flags: '-DHIGHFIVE_USE_BOOST:Bool=OFF'
           - config:
               os: ubuntu-20.04
               pkgs: 'libboost-all-dev libopencv-dev'
-              flags: '-DHIGHFIVE_USE_OPENCV:Bool=ON -GNinja'
+              flags: '-DHIGHFIVE_TEST_BOOST:Bool=ON -DHIGHFIVE_TEST_OPENCV:Bool=ON -GNinja'
           - config:
               os: ubuntu-latest
               pkgs: 'libboost-all-dev libeigen3-dev libopencv-dev'
-              flags: '-DHIGHFIVE_USE_EIGEN:Bool=ON -DHIGHFIVE_USE_OPENCV:Bool=ON -GNinja'
+              flags: '-DHIGHFIVE_TEST_BOOST:Bool=ON -DHIGHFIVE_TEST_EIGEN:Bool=ON -DHIGHFIVE_TEST_OPENCV:Bool=ON -GNinja'
           - config:
               os: ubuntu-20.04
               pkgs: 'libboost-all-dev'
-              flags: '-DCMAKE_CXX_STANDARD=17'
+              flags: '-DCMAKE_CXX_STANDARD=17 -DHIGHFIVE_TEST_BOOST:Bool=ON'
           - config:
               os: ubuntu-22.04
-              flags: '-DHIGHFIVE_USE_BOOST=Off -DCMAKE_CXX_STANDARD=20'
+              flags: '-DHIGHFIVE_TEST_BOOST=Off -DCMAKE_CXX_STANDARD=20'
 
     steps:
     - uses: actions/checkout@v3
@@ -82,6 +83,10 @@ jobs:
       working-directory: ${{github.workspace}}/build
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
 
 
@@ -91,7 +96,7 @@ jobs:
     runs-on: ubuntu-latest
     strategy:
       matrix:
-        hdf5_version : [ hdf5-1_8_23, hdf5-1_10_11, hdf5-1_12_3, hdf5-1_14_3 ]
+        hdf5_version : [ hdf5-1_8_23, hdf5-1_10_11, hdf5-1_12_3, hdf5_1.14.4.1 ]
 
     steps:
     - uses: actions/checkout@v3
@@ -122,6 +127,10 @@ jobs:
       working-directory: ${{github.workspace}}/build
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
 
 
@@ -155,13 +164,17 @@ jobs:
     - name: Build
       env: ${{matrix.env}}
       run: |
-        CMAKE_OPTIONS=(-GNinja)
+        CMAKE_OPTIONS=(-DHIGHFIVE_TEST_BOOST=ON -GNinja)
         source $GITHUB_WORKSPACE/.github/build.sh
 
     - name: Test
       working-directory: ${{github.workspace}}/build
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
 
     - name: Examples
@@ -195,8 +208,8 @@ jobs:
       run: |
         CMAKE_OPTIONS=(
           -GNinja
-          -DHIGHFIVE_USE_BOOST:BOOL=ON
-          -DHIGHFIVE_USE_EIGEN:BOOL=ON
+          -DHIGHFIVE_TEST_BOOST:BOOL=ON
+          -DHIGHFIVE_TEST_EIGEN:BOOL=ON
           -DHIGHFIVE_BUILD_DOCS:BOOL=FALSE
           -DHIGHFIVE_GLIBCXX_ASSERTIONS=${HIGHFIVE_GLIBCXX_ASSERTIONS:-OFF}
           -DHIGHFIVE_SANITIZER=${HIGHFIVE_SANITIZER:-OFF}
@@ -207,6 +220,10 @@ jobs:
       working-directory: ${{github.workspace}}/build
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
 
     - name: Examples
@@ -246,7 +263,7 @@ jobs:
         sudo apt-get -qq install libhdf5-openmpi-dev
 
     - name: "CMake Project Integration"
-      run: bash tests/test_project_integration.sh
+      run: bash tests/cmake_integration/test_cmake_integration.sh
 
 
   # Job checking the benchmarks work
@@ -279,6 +296,10 @@ jobs:
         os: [ "macOS-12" ]
         cxxstd: ["14", "17", "20"]
 
+        include:
+          - os: "macOS-13"
+            cxxstd: "20"
+
     steps:
     - uses: actions/checkout@v3
       with:
@@ -291,9 +312,9 @@ jobs:
       run: |
         CMAKE_OPTIONS=(
           -GNinja
-          -DHIGHFIVE_USE_BOOST:BOOL=ON
-          -DHIGHFIVE_USE_EIGEN:BOOL=ON
-          -DHIGHFIVE_USE_XTENSOR:BOOL=ON
+          -DHIGHFIVE_TEST_BOOST:BOOL=ON
+          -DHIGHFIVE_TEST_EIGEN:BOOL=ON
+          -DHIGHFIVE_TEST_XTENSOR:BOOL=ON
           -DHIGHFIVE_BUILD_DOCS:BOOL=FALSE
           -DHIGHFIVE_TEST_SINGLE_INCLUDES=ON
           -DCMAKE_CXX_FLAGS="-coverage -O0"
@@ -305,6 +326,10 @@ jobs:
       working-directory: ${{github.workspace}}/build
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
 
     - name: Examples
@@ -348,9 +373,9 @@ jobs:
           -T ${{matrix.vs-toolset}}
           -DCMAKE_CXX_STANDARD=${{matrix.cxxstd}}
           -DHIGHFIVE_UNIT_TESTS=ON
-          -DHIGHFIVE_USE_BOOST:BOOL=ON
-          -DHIGHFIVE_USE_EIGEN:BOOL=ON
-          -DHIGHFIVE_USE_XTENSOR:BOOL=ON
+          -DHIGHFIVE_TEST_BOOST:BOOL=ON
+          -DHIGHFIVE_TEST_EIGEN:BOOL=ON
+          -DHIGHFIVE_TEST_XTENSOR:BOOL=ON
           -DHIGHFIVE_TEST_SINGLE_INCLUDES=ON
         )
         source $GITHUB_WORKSPACE/.github/build.sh
@@ -360,4 +385,9 @@ jobs:
       shell: bash -l {0}
       run: |
         ctest -j2 --output-on-failure -C $BUILD_TYPE
+
+    - name: Test No HDF5 Diagnositics
+      working-directory: ${{github.workspace}}/build
+      shell: bash -l {0}
+      run: |
         ! ctest --verbose -C $BUILD_TYPE | grep HDF5-DIAG
diff --git a/packages/HighFive/.github/workflows/clang_format.yml b/packages/HighFive/.github/workflows/clang_format.yml
index 56f2fd8d53b78f0d709ae0ccc937207f1ba57083..7b9be4909f266a82c4d7ac79a38380e9a5f511bc 100644
--- a/packages/HighFive/.github/workflows/clang_format.yml
+++ b/packages/HighFive/.github/workflows/clang_format.yml
@@ -8,10 +8,8 @@ on:
   pull_request:
     branches:
       - master
-    paths-ignore:
-      - '**.md'
-      - '**.rst'
-      - 'doc/**'
+      - main
+      - v2.x
 
 jobs:
   Code_Format:
diff --git a/packages/HighFive/.github/workflows/coverage.yml b/packages/HighFive/.github/workflows/coverage.yml
index b3f4a212bcc442cef74ade505681ff3a1e61ac28..e5f3ed5fddfe5b3a465bc440dcb93b0926039b55 100644
--- a/packages/HighFive/.github/workflows/coverage.yml
+++ b/packages/HighFive/.github/workflows/coverage.yml
@@ -8,12 +8,13 @@ on:
   push:
     branches:
       - master
-      - ci_test
-      - release/**
+      - main
+      - v2.x
   pull_request:
     branches:
       - master
-      - release/**
+      - main
+      - v2.x
     paths-ignore:
       - '**.md'
       - '**.rst'
@@ -45,10 +46,10 @@ jobs:
       run: |
         CMAKE_OPTIONS=(
           -GNinja
-          -DHIGHFIVE_USE_BOOST:BOOL=ON
-          -DHIGHFIVE_USE_EIGEN:BOOL=ON
-          -DHIGHFIVE_USE_OPENCV:BOOL=ON
-          #-DHIGHFIVE_USE_XTENSOR:BOOL=ON
+          -DHIGHFIVE_TEST_BOOST:BOOL=ON
+          -DHIGHFIVE_TEST_EIGEN:BOOL=ON
+          -DHIGHFIVE_TEST_OPENCV:BOOL=ON
+          #-DHIGHFIVE_TEST_XTENSOR:BOOL=ON
           -DHIGHFIVE_TEST_SINGLE_INCLUDES=ON
           -DHIGHFIVE_BUILD_DOCS:BOOL=FALSE
           -DCMAKE_CXX_FLAGS="-coverage -O0"
diff --git a/packages/HighFive/.github/workflows/gh-pages.yml b/packages/HighFive/.github/workflows/gh-pages.yml
index 2032f91abc042c9704b420b021e72abbf52241f3..101e7234d78d2f15bb9064f9d5199484ab00cba2 100644
--- a/packages/HighFive/.github/workflows/gh-pages.yml
+++ b/packages/HighFive/.github/workflows/gh-pages.yml
@@ -3,10 +3,12 @@ name: gh-pages
 on:
   push:
     branches:
-      - master
+      - v2.x
   pull_request:
     branches:
+      - v2.x
       - master
+      - main
 
 jobs:
 
@@ -39,7 +41,7 @@ jobs:
         cp -r doc/poster build/doc/html/
 
     - name: Deploy to GitHub Pages
-      if: ${{ success() && github.ref == 'refs/heads/master' && github.event_name == 'push' }}
+      if: ${{ success() && github.ref == 'refs/heads/v2.x' && github.event_name == 'push' }}
       uses: crazy-max/ghaction-github-pages@v2
       with:
         target_branch: gh-pages
diff --git a/packages/HighFive/.github/workflows/version_file.yml b/packages/HighFive/.github/workflows/version_file.yml
index 816137e955fe920c432cf985cbd3a43fa2e924ff..55cf0f6f53268149729f573af465ccace052346e 100644
--- a/packages/HighFive/.github/workflows/version_file.yml
+++ b/packages/HighFive/.github/workflows/version_file.yml
@@ -3,12 +3,14 @@ name: HighFive Check Version File
 on:
   push:
     branches:
-      - ci_test
-      - release/**
+      - master
+      - main
+      - v2.x
   pull_request:
     branches:
       - master
-      - release/**
+      - main
+      - v2.x
 
 jobs:
   CheckVersion:
@@ -27,7 +29,7 @@ jobs:
     - name: Build
       run: |
         # Will trigger `configure_file` for H5Version.hpp.
-        cmake -DHIGHFIVE_USE_BOOST=Off -B build .
+        cmake -B build .
 
     - name: Test
       run: |
diff --git a/packages/HighFive/.gitrepo b/packages/HighFive/.gitrepo
index 98988c87ecab65e9d9e9215ea6684fa53407fd3b..308a575ddc2a4967e74d3d8e44540c89ff1855d6 100644
--- a/packages/HighFive/.gitrepo
+++ b/packages/HighFive/.gitrepo
@@ -6,7 +6,7 @@
 [subrepo]
 	remote = git@github.com:BlueBrain/HighFive.git
 	branch = master
-	commit = d04789128123e1a643c6284e28087be1dafae2ee
-	parent = ce26d02b1f92356362dc4daede0babf8d4ac23b6
+	commit = 5e0204e272e4f71e3dd768287e400758f785527d
+	parent = 760bc7af37b9a29960a20602cfc91e35e22e24a6
 	method = merge
 	cmdver = 0.4.6
diff --git a/packages/HighFive/.zenodo.json b/packages/HighFive/.zenodo.json
new file mode 100644
index 0000000000000000000000000000000000000000..0e96eedbdb17835eb97cd787704e4f6096a116c6
--- /dev/null
+++ b/packages/HighFive/.zenodo.json
@@ -0,0 +1,38 @@
+{
+    "creators": [
+        {
+            "affiliation": "",
+            "name": "Devresse, Adrien"
+        },
+        {
+            "affiliation": "",
+            "name": "Cornu, Nicolas"
+        },
+        {
+            "affiliation": "",
+            "name": "Grosheintz-Laval, Luc"
+        },
+        {
+            "affiliation": "",
+            "name": "Awile, Omar"
+        },
+        {
+            "affiliation": "",
+            "name": "de Geus, Tom"
+        },
+        {
+            "affiliation": "",
+            "name": "Pereira, Fernando"
+        },
+        {
+            "affiliation": "",
+            "name": "Wolf, Matthias"
+        },
+        {
+            "affiliation": "",
+            "name": "HighFive Contributors"
+        }
+    ],
+
+    "title": "HighFive - Header-only C++ HDF5 interface"
+}
diff --git a/packages/HighFive/CMake/HighFiveConfig.cmake.in b/packages/HighFive/CMake/HighFiveConfig.cmake.in
deleted file mode 100644
index 464a645d038f8221583fd5019eb81f05662fdef4..0000000000000000000000000000000000000000
--- a/packages/HighFive/CMake/HighFiveConfig.cmake.in
+++ /dev/null
@@ -1,74 +0,0 @@
-function(copy_interface_properties target source)
-  foreach(prop
-          INTERFACE_COMPILE_DEFINITIONS
-          INTERFACE_COMPILE_FEATURES
-          INTERFACE_COMPILE_OPTIONS
-          INTERFACE_INCLUDE_DIRECTORIES
-          INTERFACE_LINK_LIBRARIES
-          INTERFACE_SOURCES
-          INTERFACE_SYSTEM_INCLUDE_DIRECTORIES)
-    set_property(TARGET ${target} APPEND PROPERTY ${prop} $<TARGET_PROPERTY:${source},${prop}>)
-  endforeach()
-endfunction()
-
-if(TARGET HighFive)
-    return()
-endif()
-
-@PACKAGE_INIT@
-
-# Get HighFive targets
-include("${CMAKE_CURRENT_LIST_DIR}/HighFiveTargets.cmake")
-
-# Recreate combined HighFive
-add_library(HighFive INTERFACE IMPORTED)
-set_property(TARGET HighFive APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS MPI_NO_CPPBIND)  # No c++ bindings
-
-# Ensure we activate required C++ std
-if(NOT DEFINED CMAKE_CXX_STANDARD)
-  if(CMAKE_VERSION VERSION_LESS 3.8)
-    message(WARNING "HighFive requires minimum C++11. (C++14 for XTensor) \
-        You may need to set CMAKE_CXX_STANDARD in you project")
-  else()
-    # A client request for a higher std overrides this
-    target_compile_features(HighFive INTERFACE cxx_std_11)
-  endif()
-endif()
-
-# If the user sets this flag, all dependencies are preserved.
-# Useful in central deployments where dependencies are not prepared later
-set(HIGHFIVE_USE_INSTALL_DEPS @HIGHFIVE_USE_INSTALL_DEPS@ CACHE BOOL "Use original Highfive dependencies")
-if(HIGHFIVE_USE_INSTALL_DEPS)
-  # If enabled in the deploy config, request c++14
-  if(@HIGHFIVE_USE_XTENSOR@ AND NOT CMAKE_VERSION VERSION_LESS 3.8)
-    set_property(TARGET HighFive APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_14)
-  endif()
-  message(STATUS "HIGHFIVE @PROJECT_VERSION@: Using original dependencies (HIGHFIVE_USE_INSTALL_DEPS=YES)")
-  copy_interface_properties(HighFive HighFive_HighFive)
-  return()
-endif()
-
-# When not using the pre-built dependencies, give user options
-if(DEFINED HIGHFIVE_USE_BOOST)
-  set(HIGHFIVE_USE_BOOST ${HIGHFIVE_USE_BOOST} CACHE BOOL "Enable Boost Support")
-else()
-  set(HIGHFIVE_USE_BOOST @HIGHFIVE_USE_BOOST@ CACHE BOOL "Enable Boost Support")
-endif()
-set(HIGHFIVE_USE_EIGEN "${HIGHFIVE_USE_EIGEN}" CACHE BOOL "Enable Eigen testing")
-set(HIGHFIVE_USE_XTENSOR "${HIGHFIVE_USE_XTENSOR}" CACHE BOOL "Enable xtensor testing")
-set(HIGHFIVE_PARALLEL_HDF5 @HIGHFIVE_PARALLEL_HDF5@ CACHE BOOL "Enable Parallel HDF5 support")
-option(HIGHFIVE_VERBOSE "Enable verbose logging" @HIGHFIVE_VERBOSE@)
-
-if(HIGHFIVE_USE_XTENSOR AND NOT CMAKE_VERSION VERSION_LESS 3.8)
-  set_property(TARGET HighFive APPEND PROPERTY INTERFACE_COMPILE_FEATURES cxx_std_14)
-endif()
-
-if(NOT HighFive_FIND_QUIETLY)
-  message(STATUS "HIGHFIVE @PROJECT_VERSION@: (Re)Detecting Highfive dependencies (HIGHFIVE_USE_INSTALL_DEPS=NO)")
-endif()
-include("${CMAKE_CURRENT_LIST_DIR}/HighFiveTargetDeps.cmake")
-foreach(dependency HighFive_libheaders libdeps)
-    copy_interface_properties(HighFive ${dependency})
-endforeach()
-
-check_required_components(HighFive)
diff --git a/packages/HighFive/CMake/HighFiveTargetDeps.cmake b/packages/HighFive/CMake/HighFiveTargetDeps.cmake
deleted file mode 100644
index 919b53544ea198e040d86d5620bb05f05ab5a7f2..0000000000000000000000000000000000000000
--- a/packages/HighFive/CMake/HighFiveTargetDeps.cmake
+++ /dev/null
@@ -1,122 +0,0 @@
-# Link against target system libs
-# -------------------------------
-
-if(NOT TARGET libdeps)
-
-  # Independent target to make it possible to have new dependencies each build
-  add_library(libdeps INTERFACE)
-
-  if(HIGHFIVE_VERBOSE)
-    target_compile_definitions(libdeps INTERFACE -DHIGHFIVE_LOG_LEVEL=0)
-  endif()
-
-  if(HIGHFIVE_GLIBCXX_ASSERTIONS)
-    target_compile_definitions(libdeps INTERFACE -D_GLIBCXX_ASSERTIONS)
-  endif()
-
-  if(HIGHFIVE_HAS_FRIEND_DECLARATIONS)
-    target_compile_definitions(libdeps INTERFACE -DHIGHFIVE_HAS_FRIEND_DECLARATIONS=1)
-  endif()
-
-  if(HIGHFIVE_SANITIZER)
-    target_compile_options(libdeps INTERFACE -fsanitize=${HIGHFIVE_SANITIZER})
-    target_link_options(libdeps INTERFACE -fsanitize=${HIGHFIVE_SANITIZER})
-  endif()
-
-  # HDF5
-  if(NOT DEFINED HDF5_C_LIBRARIES)
-    set(HDF5_PREFER_PARALLEL ${HIGHFIVE_PARALLEL_HDF5})
-    set(HDF5_USE_STATIC_LIBRARIES ${HIGHFIVE_STATIC_HDF5})
-    find_package(HDF5 REQUIRED)
-  endif()
-
-  if(HIGHFIVE_PARALLEL_HDF5 AND NOT HDF5_IS_PARALLEL)
-    message(WARNING "Parallel HDF5 requested but libhdf5 doesnt support it")
-  endif()
-
-  target_include_directories(libdeps SYSTEM INTERFACE ${HDF5_INCLUDE_DIRS})
-  target_link_libraries(libdeps INTERFACE ${HDF5_LIBRARIES})
-  target_compile_definitions(libdeps INTERFACE ${HDF5_DEFINITIONS})
-  target_compile_definitions(libdeps INTERFACE HIGHFIVE_HAS_CONCEPTS=$<BOOL:${HIGHFIVE_HAS_CONCEPTS}>)
-
-
-  # Boost
-  if(HIGHFIVE_USE_BOOST)
-    if(NOT DEFINED Boost_NO_BOOST_CMAKE)
-      # HighFive deactivated finding Boost via Boost's own CMake files
-      # in Oct 2016 (commit '25627b085'). Likely to appease one cluster.
-      # Boost's CMake support has since improved and likely this setting
-      # isn't needed anymore. It is kept for backwards compatibility.
-      # However, a rework of HighFive's CMake code should consider removing
-      # this default. Hard coding this to true has been reported to cause
-      # build failures.
-      set(Boost_NO_BOOST_CMAKE TRUE)
-    endif()
-    find_package(Boost REQUIRED COMPONENTS system serialization)
-    # Dont use imported targets yet, not avail before cmake 3.5
-    target_include_directories(libdeps SYSTEM INTERFACE ${Boost_INCLUDE_DIR})
-    target_compile_definitions(libdeps INTERFACE BOOST_ALL_NO_LIB H5_USE_BOOST)
-  endif()
-
-  # Half
-  if(HIGHFIVE_USE_HALF_FLOAT)
-    find_file(FOUND_HALF half.hpp)
-    if (NOT FOUND_HALF)
-      message(FATAL_ERROR "Half-precision floating-point support requested but file half.hpp not found")
-    endif()
-    target_compile_definitions(libdeps INTERFACE H5_USE_HALF_FLOAT)
-  endif()
-
-  # Eigen
-  if(HIGHFIVE_USE_EIGEN)
-    if (NOT EIGEN3_INCLUDE_DIRS)
-      find_package(Eigen3 NO_MODULE)
-      if(Eigen3_FOUND)
-        message(STATUS "Found Eigen ${Eigen3_VERSION}: ${EIGEN3_INCLUDE_DIRS}")
-      else()
-        find_package(PkgConfig)
-        pkg_check_modules(EIGEN3 REQUIRED eigen3)
-      endif()
-    endif()
-    if (NOT EIGEN3_INCLUDE_DIRS)
-      message(FATAL_ERROR "Eigen was requested but could not be found")
-    endif()
-    target_include_directories(libdeps SYSTEM INTERFACE ${EIGEN3_INCLUDE_DIRS})
-    target_compile_definitions(libdeps INTERFACE H5_USE_EIGEN)
-  endif()
-
-  # xtensor
-  if(HIGHFIVE_USE_XTENSOR)
-    if (NOT xtensor_INCLUDE_DIRS)
-      find_package(xtensor REQUIRED)
-    endif()
-    if (NOT xtl_INCLUDE_DIRS)
-      find_package(xtl REQUIRED)
-    endif()
-    target_include_directories(libdeps SYSTEM INTERFACE ${xtensor_INCLUDE_DIRS} ${xtl_INCLUDE_DIRS})
-    target_compile_definitions(libdeps INTERFACE H5_USE_XTENSOR)
-  endif()
-
-  # OpenCV
-  if(HIGHFIVE_USE_OPENCV)
-    if (NOT OpenCV_INCLUDE_DIRS)
-      find_package(OpenCV REQUIRED)
-    endif()
-    target_include_directories(libdeps SYSTEM INTERFACE ${OpenCV_INCLUDE_DIRS})
-    target_link_libraries(libdeps INTERFACE ${OpenCV_LIBS})
-    target_compile_definitions(libdeps INTERFACE H5_USE_OPENCV)
-  endif()
-
-  # MPI
-  if(HIGHFIVE_PARALLEL_HDF5 OR HDF5_IS_PARALLEL)
-    find_package(MPI REQUIRED)
-    target_include_directories(libdeps SYSTEM INTERFACE ${MPI_CXX_INCLUDE_PATH})
-    target_link_libraries(libdeps INTERFACE ${MPI_CXX_LIBRARIES})
-    if(CMAKE_VERSION VERSION_LESS 3.13)
-      target_link_libraries(libdeps INTERFACE ${MPI_CXX_LINK_FLAGS})
-    else()
-      target_link_options(libdeps INTERFACE "SHELL:${MPI_CXX_LINK_FLAGS}")
-    endif()
-  endif()
-
-endif()
diff --git a/packages/HighFive/CMake/HighFiveTargetExport.cmake b/packages/HighFive/CMake/HighFiveTargetExport.cmake
deleted file mode 100644
index 9906f39513c385e9dba2dca5194453fe9b2eec16..0000000000000000000000000000000000000000
--- a/packages/HighFive/CMake/HighFiveTargetExport.cmake
+++ /dev/null
@@ -1,48 +0,0 @@
-
-# Define the HighFive INTERFACE library
-add_library(libheaders INTERFACE)
-
-target_include_directories(libheaders INTERFACE
-  "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>"
-  "$<INSTALL_INTERFACE:include>")
-
-# Combined HighFive
-add_library(HighFive INTERFACE)
-target_compile_definitions(HighFive INTERFACE MPI_NO_CPPBIND)  # No c++ bindings
-target_link_libraries(HighFive INTERFACE libheaders libdeps)
-
-
-# Generate ${PROJECT_NAME}Config.cmake
-
-include(CMakePackageConfigHelpers)
-configure_package_config_file(${CMAKE_CURRENT_LIST_DIR}/HighFiveConfig.cmake.in
-  ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
-  INSTALL_DESTINATION share/${PROJECT_NAME}/CMake)
-
-write_basic_package_version_file(
-    ${PROJECT_NAME}ConfigVersion.cmake
-    VERSION ${PROJECT_VERSION}
-    COMPATIBILITY AnyNewerVersion)
-
-install(FILES
-    CMake/HighFiveTargetDeps.cmake
-    ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
-    ${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake
-  DESTINATION share/${PROJECT_NAME}/CMake)
-
-
-# Provides IMPORTED targets when using this project from build/install trees.
-
-# Specify targets to include in the HighFive Exports
-install(TARGETS HighFive libheaders libdeps
-        EXPORT HighFiveTargets)
-
-# Generate & install the Export for the INSTALL_INTERFACE
-install(EXPORT HighFiveTargets
-        NAMESPACE HighFive_
-        FILE HighFiveTargets.cmake
-        DESTINATION share/${PROJECT_NAME}/CMake)
-
-# Generate the Export for the BUILD_INTERACE (hardly used)
-export(EXPORT HighFiveTargets
-       FILE "${PROJECT_BINARY_DIR}/HighFiveTargets.cmake")
diff --git a/packages/HighFive/CMake/config/TestHelpers.cmake b/packages/HighFive/CMake/config/TestHelpers.cmake
deleted file mode 100644
index f3ca1cb74108a6a348f1c9739e83042c56096787..0000000000000000000000000000000000000000
--- a/packages/HighFive/CMake/config/TestHelpers.cmake
+++ /dev/null
@@ -1,113 +0,0 @@
-# TestHelpers.cmake
-# 
-# set of Convenience functions for unit testing with cmake
-#
-# License: BSD 3
-#
-# Copyright (c) 2016, Adrien Devresse
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
-#
-# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
-#
-# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
-#
-# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-
-
-
-##
-# enable or disable detection of SLURM and MPIEXEC
-option(AUTO_TEST_WITH_SLURM "automatically add srun as test prefix in a SLURM environment" TRUE)
-option(AUTO_TEST_WITH_MPIEXEC "automatically add mpiexec as test prefix in a MPICH2/OpenMPI environment" TRUE)
-
-###
-##
-## Basic SLURM support
-## the prefix "srun" is added to any test in the environment
-## For a slurm test execution, simply run "salloc [your_exec_parameters] ctest"
-##    
-##
-if(AUTO_TEST_WITH_SLURM)
-    if(NOT DEFINED SLURM_SRUN_COMMAND)
-        find_program(SLURM_SRUN_COMMAND
-                       NAMES "srun"
-                       HINTS "${SLURM_ROOT}/bin")
-    endif()
-    
-    if(SLURM_SRUN_COMMAND)
-        set(TEST_EXEC_PREFIX_DEFAULT "${SLURM_SRUN_COMMAND}")
-        set(TEST_MPI_EXEC_PREFIX_DEFAULT "${SLURM_SRUN_COMMAND}")
-        set(TEST_MPI_EXEC_BIN_DEFAULT "${SLURM_SRUN_COMMAND}")
-	set(TEST_WITH_SLURM ON)
-        message(STATUS " - AUTO_TEST_WITH_SLURM with slurm cmd ${TEST_EXEC_PREFIX_DEFAULT} ")
-        message(STATUS "  -- set test execution prefix to ${TEST_EXEC_PREFIX_DEFAULT} ")
-        message(STATUS "  -- set MPI test execution prefix to ${TEST_MPI_EXEC_PREFIX_DEFAULT} ")
-    endif()
-
-endif()
-
-###
-## Basic MPIExec support, will just forward mpiexec as prefix
-## 
-if(AUTO_TEST_WITH_MPIEXEC AND NOT TEST_WITH_SLURM)
-
-   if(NOT DEFINED MPIEXEC)
-        find_program(MPIEXEC
-                     NAMES "mpiexec"
-                     HINTS "${MPI_ROOT}/bin")
-   endif()
-
-
-   if(MPIEXEC)
-        set(TEST_MPI_EXEC_PREFIX_DEFAULT "${MPIEXEC}")
-        set(TEST_MPI_EXEC_BIN_DEFAULT "${MPIEXEC}")
-	set(TEST_WITH_MPIEXEC ON)
-        message(STATUS " - AUTO_TEST_WITH_MPIEXEC cmd ${MPIEXEC} ")
-        message(STATUS "  -- set MPI test execution prefix to ${TEST_MPI_EXEC_PREFIX_DEFAULT} ")
-
-   endif()
-
-endif()
-
-
-
-###
-##  MPI executor program path without arguments used for testing.
-##  default: srun or mpiexec if found
-##
-set(TEST_MPI_EXEC_BIN "${TEST_MPI_EXEC_BIN_DEFAULT}" CACHE STRING "path of the MPI executor (mpiexec, mpirun) for test execution")
-
-
-
-###
-## Test execution prefix. Override this variable for any execution prefix required in clustered environment
-## 
-## To specify manually a command with argument, e.g -DTEST_EXEC_PREFIX="/var/empty/bin/srun;-n;-4" for a srun execution
-## with 4 nodes
-##
-## default: srun if found
-##
-set(TEST_EXEC_PREFIX "${TEST_EXEC_PREFIX_DEFAULT}" CACHE STRING "prefix command for the test executions")
-
-
-
-###
-## Test execution prefix specific for MPI programs.
-## 
-## To specify manually a command with argument, use the cmake list syntax. e.g -DTEST_EXEC_PREFIX="/var/empty/bin/mpiexec;-n;-4" for an MPI execution
-## with 4 nodes
-##
-## default: srun or mpiexec if found
-##
-set(TEST_MPI_EXEC_PREFIX "${TEST_MPI_EXEC_PREFIX_DEFAULT}" CACHE STRING "prefix command for the MPI test executions")
-
-
-
-
-
-
-
diff --git a/packages/HighFive/CMakeLists.txt b/packages/HighFive/CMakeLists.txt
index 694960090842b6a8c27676a336fe4a40e1266b39..7060fe7135f47139b8e33f0471679b9d93290039 100644
--- a/packages/HighFive/CMakeLists.txt
+++ b/packages/HighFive/CMakeLists.txt
@@ -1,43 +1,11 @@
-cmake_minimum_required(VERSION 3.1)
-if(${CMAKE_VERSION} VERSION_LESS 3.13)
-  cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
-else()
-  cmake_policy(VERSION 3.13)
-endif()
+cmake_minimum_required(VERSION 3.13)
+cmake_policy(VERSION 3.13)
 
-project(HighFive VERSION 2.9.0)
+project(HighFive VERSION 3.0.0)
 
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/highfive/H5Version.hpp.in
-               ${CMAKE_CURRENT_SOURCE_DIR}/include/highfive/H5Version.hpp)
-# INCLUDES
-list(APPEND CMAKE_MODULE_PATH
-  ${CMAKE_CURRENT_SOURCE_DIR}/CMake
-  ${CMAKE_CURRENT_SOURCE_DIR}/CMake/config)
-
-# OPTIONS
-# Compatibility within Highfive 2.x series
-set(USE_BOOST ON CACHE BOOL "Enable Boost Support")
-set(USE_EIGEN OFF CACHE BOOL "Enable Eigen testing")
-set(USE_XTENSOR OFF CACHE BOOL "Enable xtensor testing")
-set(USE_OPENCV OFF CACHE BOOL "Enable OpenCV testing")
-mark_as_advanced(USE_BOOST USE_EIGEN USE_XTENSOR)
-
-set(HIGHFIVE_UNIT_TESTS AUTO CACHE STRING "Enable unit tests (requires Catch2 to be present)")
-set_property(CACHE HIGHFIVE_UNIT_TESTS PROPERTY STRINGS AUTO ON OFF)
-
-option(HIGHFIVE_USE_BOOST "Enable Boost Support" ${USE_BOOST})
-option(HIGHFIVE_USE_HALF_FLOAT "Enable half-precision floats" ${USE_HALF_FLOAT})
-option(HIGHFIVE_USE_EIGEN "Enable Eigen testing" ${USE_EIGEN})
-option(HIGHFIVE_USE_OPENCV "Enable OpenCV testing" ${USE_OPENCV})
-option(HIGHFIVE_USE_XTENSOR "Enable xtensor testing" ${USE_XTENSOR})
-option(HIGHFIVE_EXAMPLES "Compile examples" ON)
-option(HIGHFIVE_PARALLEL_HDF5 "Enable Parallel HDF5 support" OFF)
-option(HIGHFIVE_STATIC_HDF5 "Staticly link to HDF5 library" OFF)
-option(HIGHFIVE_BUILD_DOCS "Enable documentation building" ON)
+# Configure HighFive
+# ------------------
 option(HIGHFIVE_VERBOSE "Set logging level to verbose." OFF)
-option(HIGHFIVE_GLIBCXX_ASSERTIONS "Enable bounds check for STL." OFF)
-option(HIGHFIVE_HAS_CONCEPTS "Print readable compiler errors w/ C++20 concepts" ON)
-option(HIGHFIVE_HAS_WERROR "Convert warnings to errors." OFF)
 
 # Controls if HighFive classes are friends of each other.
 #
@@ -66,69 +34,119 @@ option(HIGHFIVE_HAS_WERROR "Convert warnings to errors." OFF)
 option(HIGHFIVE_HAS_FRIEND_DECLARATIONS "Enable additional friend declarations. Certain compiler require this On, others Off." OFF)
 mark_as_advanced(HIGHFIVE_HAS_FRIEND_DECLARATIONS)
 
-set(HIGHFIVE_SANITIZER OFF CACHE STRING "Enable a group of sanitizers, requires compiler support. Supported: 'address' and 'undefined'.")
-mark_as_advanced(HIGHFIVE_SANITIZER)
+option(HIGHFIVE_FIND_HDF5 "Find and link with HDF5." On)
 
-# In deployments we probably don't want/cant have dynamic dependencies
-option(HIGHFIVE_USE_INSTALL_DEPS "End applications by default use detected dependencies here" OFF)
-mark_as_advanced(HIGHFIVE_USE_INSTALL_DEPS)
+# Configure Tests & Examples
+# --------------------------
 
+# Internal variable that controls the default value for building
+# optional things like tests, examples and docs.
+if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
+  set(HIGHFIVE_EXTRAS_DEFAULT ON)
+else()
+  set(HIGHFIVE_EXTRAS_DEFAULT OFF)
+endif()
+
+option(HIGHFIVE_UNIT_TESTS "Compile unit-tests" ${HIGHFIVE_EXTRAS_DEFAULT})
+option(HIGHFIVE_EXAMPLES "Compile examples" ${HIGHFIVE_EXTRAS_DEFAULT})
+option(HIGHFIVE_BUILD_DOCS "Build documentation" ${HIGHFIVE_EXTRAS_DEFAULT})
+
+option(HIGHFIVE_TEST_BOOST "Enable Boost testing" OFF)
+option(HIGHFIVE_TEST_EIGEN "Enable Eigen testing" OFF)
+option(HIGHFIVE_TEST_OPENCV "Enable OpenCV testing" OFF)
+option(HIGHFIVE_TEST_XTENSOR "Enable xtensor testing" OFF)
+option(HIGHFIVE_TEST_HALF_FLOAT "Enable half-precision floats" OFF)
+
+# TODO remove entirely.
+option(HIGHFIVE_HAS_CONCEPTS "Print readable compiler errors w/ C++20 concepts" OFF)
+
+set(HIGHFIVE_MAX_ERROR 0 "Maximum number of compiler errors.")
+option(HIGHFIVE_HAS_WERROR "Convert warnings to errors." OFF)
+option(HIGHFIVE_GLIBCXX_ASSERTIONS "Enable bounds check for STL." OFF)
+# TODO these some magic to get a drop down menu in ccmake
+set(HIGHFIVE_SANITIZER OFF CACHE STRING "Enable a group of sanitizers, requires compiler support. Supported: 'address' and 'undefined'.")
+mark_as_advanced(HIGHFIVE_SANITIZER)
 
 # Check compiler cxx_std requirements
 # -----------------------------------
 
-if(CMAKE_CXX_STANDARD EQUAL 98)
-    message(FATAL_ERROR "HighFive needs to be compiled with at least C++11")
-endif()
-
 if(NOT DEFINED CMAKE_CXX_STANDARD)
-    set(CMAKE_CXX_STANDARD 11)
+    set(CMAKE_CXX_STANDARD 14)
     set(CMAKE_CXX_STANDARD_REQUIRED ON)
     set(CMAKE_CXX_EXTENSIONS OFF)
 endif()
 
-if(HIGHFIVE_USE_XTENSOR AND CMAKE_CXX_STANDARD LESS 14)
-    set(CMAKE_CXX_STANDARD 14)
-    set(CMAKE_CXX_STANDARD_REQUIRED ON)
+if(CMAKE_CXX_STANDARD EQUAL 98 OR CMAKE_CXX_STANDARD LESS 14)
+    message(FATAL_ERROR "HighFive needs to be compiled with at least C++14")
 endif()
 
 add_compile_definitions(HIGHFIVE_CXX_STD=${CMAKE_CXX_STANDARD})
 
-# Search dependencies (hdf5, boost, eigen, xtensor, mpi) and build target highfive_deps
-include(${PROJECT_SOURCE_DIR}/CMake/HighFiveTargetDeps.cmake)
+# HighFive
+# --------
+add_library(HighFiveInclude INTERFACE)
+add_library(HighFive::Include ALIAS HighFiveInclude)
+set_target_properties(HighFiveInclude PROPERTIES EXPORT_NAME Include)
+
+target_include_directories(HighFiveInclude INTERFACE
+  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+  $<INSTALL_INTERFACE:include>
+)
 
-# Set-up HighFive to be used in 3rd party project using exports. Create a HighFive target
-include(${PROJECT_SOURCE_DIR}/CMake/HighFiveTargetExport.cmake)
+add_library(HighFive INTERFACE)
+add_library(HighFive::HighFive ALIAS HighFive)
+
+target_link_libraries(HighFive INTERFACE HighFive::Include)
+
+if(HIGHFIVE_FIND_HDF5)
+  find_package(HDF5 REQUIRED)
+  target_link_libraries(HighFive INTERFACE HDF5::HDF5)
+endif()
+
+if(HDF5_IS_PARALLEL)
+  find_package(MPI REQUIRED)
+  target_link_libraries(HighFive
+    INTERFACE
+    $<BUILD_INTERFACE:MPI::MPI_C>
+    $<BUILD_INTERFACE:MPI::MPI_CXX>
+  )
+endif()
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/highfive/H5Version.hpp.in
+               ${CMAKE_CURRENT_SOURCE_DIR}/include/highfive/H5Version.hpp)
+
+# Install
+# -------
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/HighFiveConfigVersion.cmake
+  VERSION ${PACKAGE_VERSION}
+  COMPATIBILITY AnyNewerVersion
+)
 
-# Installation of headers (HighFive is only interface)
 install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
   DESTINATION "include"
   PATTERN "*.in" EXCLUDE)
 
+install(TARGETS HighFive HighFiveInclude EXPORT HighFiveTargets)
+install(EXPORT HighFiveTargets
+  FILE HighFiveTargets.cmake
+  NAMESPACE HighFive::
+  DESTINATION lib/cmake/HighFive
+)
+
+install(FILES
+  ${CMAKE_CURRENT_SOURCE_DIR}/cmake/HighFiveConfig.cmake
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/HighFiveConfigVersion.cmake
+  DESTINATION lib/cmake/HighFive
+)
+
 # Preparing local building (tests, examples)
 # ------------------------------------------
 
-# Disable test if Boost was expressly disabled, or if HighFive is a sub-project
-if (NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
-  if(HIGHFIVE_UNIT_TESTS AND NOT HighFive_FIND_QUIETLY)
-    message(WARNING "Unit tests have been DISABLED.")
-  endif()
-  set(HIGHFIVE_UNIT_TESTS FALSE)
-endif()
-
-if(HIGHFIVE_UNIT_TESTS)
-  if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/deps/catch2/CMakeLists.txt)
-    add_subdirectory(deps/catch2 EXCLUDE_FROM_ALL)
-    list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/deps/catch2/contrib)
-  else()
-    find_package(Catch2)
-    if(NOT HIGHFIVE_UNIT_TESTS STREQUAL "AUTO" AND HIGHFIVE_UNIT_TESTS AND NOT Catch2_FOUND)
-      message(FATAL_ERROR "Please provide a Catch2 installation or clone the submodule")
-    elseif(NOT Catch2_FOUND)
-      message(WARNING "No Catch2 installation was found; Disabling unit tests.")
-      set(HIGHFIVE_UNIT_TESTS OFF)
-    endif()
-  endif()
+if(HIGHFIVE_EXAMPLES OR HIGHFIVE_UNIT_TESTS)
+  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/HighFiveWarnings.cmake)
+  include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/HighFiveOptionalDependencies.cmake)
 endif()
 
 if(HIGHFIVE_EXAMPLES)
@@ -136,6 +154,8 @@ if(HIGHFIVE_EXAMPLES)
 endif()
 
 if(HIGHFIVE_UNIT_TESTS)
+  add_subdirectory(deps/catch2 EXCLUDE_FROM_ALL)
+  list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/deps/catch2/contrib)
   enable_testing()
   add_subdirectory(tests/unit)
 endif()
diff --git a/packages/HighFive/README.md b/packages/HighFive/README.md
index bc0d2752ed71792b5bfa95116efc7822d3812d66..8e04eb13c294cbf0aec95e87346300e872a6df96 100644
--- a/packages/HighFive/README.md
+++ b/packages/HighFive/README.md
@@ -1,14 +1,20 @@
+*Note:* In preparation of `v3` of HighFive, we've started merging breaking
+changes into the main branch. More information and opportunity to comment can
+be found at:
+https://github.com/BlueBrain/HighFive/issues/864
+
 # HighFive - HDF5 header-only C++ Library
 
 [![Doxygen -> gh-pages](https://github.com/BlueBrain/HighFive/workflows/gh-pages/badge.svg?branch=master)](https://BlueBrain.github.io/HighFive/actions/workflows/gh-pages.yml?query=branch%3Amaster)
 [![codecov](https://codecov.io/gh/BlueBrain/HighFive/branch/master/graph/badge.svg?token=UBKxHEn7RS)](https://codecov.io/gh/BlueBrain/HighFive)
 [![HighFive_Integration_tests](https://github.com/BlueBrain/HighFive-testing/actions/workflows/integration.yml/badge.svg)](https://github.com/BlueBrain/HighFive-testing/actions/workflows/integration.yml)
+[![Zenodo](https://zenodo.org/badge/47755262.svg)](https://zenodo.org/doi/10.5281/zenodo.10679422)
 
 Documentation: https://bluebrain.github.io/HighFive/
 
 ## Brief
 
-HighFive is a modern header-only C++11 friendly interface for libhdf5.
+HighFive is a modern header-only C++14 friendly interface for libhdf5.
 
 HighFive supports STL vector/string, Boost::UBLAS, Boost::Multi-array and Xtensor. It handles C++ from/to HDF5 with automatic type mapping.
 HighFive does not require additional libraries (see dependencies).
@@ -19,7 +25,7 @@ It integrates nicely with other CMake projects by defining (and exporting) a Hig
 - Simple C++-ish minimalist interface
 - No other dependency than libhdf5
 - Zero overhead
-- Support C++11
+- Support C++14
 
 ### Feature support
 - create/read/write files, datasets, attributes, groups, dataspaces.
@@ -34,12 +40,11 @@ It integrates nicely with other CMake projects by defining (and exporting) a Hig
 - etc... (see [ChangeLog](./CHANGELOG.md))
 
 ### Dependencies
-- hdf5 (dev)
-- hdf5-mpi (optional, opt-in with -D*HIGHFIVE_PARALLEL_HDF5*=ON)
-- boost >= 1.41 (recommended, opt-out with -D*HIGHFIVE_USE_BOOST*=OFF)
-- eigen3 (optional, opt-in with -D*HIGHFIVE_USE_EIGEN*=ON)
-- xtensor (optional, opt-in with -D*HIGHFIVE_USE_XTENSOR*=ON)
-- half (optional, opt-in with -D*HIGHFIVE_USE_HALF_FLOAT*=ON)
+- HDF5 or pHDF5, including headers
+- boost >= 1.41 (recommended)
+- eigen3 (optional)
+- xtensor (optional)
+- half (optional)
 
 ### Known flaws
 - HighFive is not thread-safe. At best it has the same limitations as the HDF5 library. However, HighFive objects modify their members without protecting these writes. Users have reported that HighFive is not thread-safe even when using the threadsafe HDF5 library, e.g., https://github.com/BlueBrain/HighFive/discussions/675.
@@ -119,11 +124,11 @@ For several 'standard' use cases the [highfive/H5Easy.hpp](include/highfive/H5Ea
     - scalars (to/from an extendible DataSet),
     - strings,
     - vectors (of standard types),
-    - [Eigen::Matrix](http://eigen.tuxfamily.org) (optional, enable CMake option `HIGHFIVE_USE_EIGEN`),
+    - [Eigen::Matrix](http://eigen.tuxfamily.org) (optional),
     - [xt::xarray](https://github.com/QuantStack/xtensor) and [xt::xtensor](https://github.com/QuantStack/xtensor)
-      (optional, enable CMake option `HIGHFIVE_USE_XTENSOR`).
+      (optional).
     - [cv::Mat_](https://docs.opencv.org/master/df/dfc/classcv_1_1Mat__.html)
-      (optional, enable CMake option `HIGHFIVE_USE_OPENCV`).
+      (optional).
 
 * Getting in a single line:
 
@@ -145,16 +150,29 @@ int main() {
 }
 ```
 
-whereby the `int` type of this example can be replaced by any of the above types. See [easy_load_dump.cpp](src/examples/easy_load_dump.cpp) for more details.
+whereby the `int` type of this example can be replaced by any of the above
+types. See [easy_load_dump.cpp](src/examples/easy_load_dump.cpp) for more
+details.
 
-**Note:** Classes such as `H5Easy::File` are just short for the regular `HighFive` classes (in this case `HighFive::File`). They can thus be used interchangeably.
+**Note:** Classes such as `H5Easy::File` are just short for the regular
+`HighFive` classes (in this case `HighFive::File`). They can thus be used
+interchangeably.
 
 
 ## CMake integration
 There's two common paths of integrating HighFive into a CMake based project.
 The first is to "vendor" HighFive, the second is to install HighFive as a
-normal C++ library. Due to how HighFive CMake code works, sometimes following
-the third Bailout Approach is needed.
+normal C++ library. Since HighFive makes choices about how to integrate HDF5,
+sometimes following the third Bailout Approach is needed.
+
+Regular HDF5 CMake variables can be used. Interesting variables include:
+
+* `HDF5_USE_STATIC_LIBRARIES` to link statically against the HDF5 library.
+* `HDF5_PREFER_PARALLEL` to prefer pHDF5.
+* `HDF5_IS_PARALLEL` to check if HDF5 is parallel.
+
+Please consult `tests/cmake_integration` for examples of how to write libraries
+or applications using HighFive.
 
 ### Vendoring HighFive
 
@@ -163,86 +181,63 @@ project (typically as a git submodule), for example in `third_party/HighFive`.
 
 The projects `CMakeLists.txt` add the following lines
 ```cmake
-add_executable(foo foo.cpp)
-
-# You might want to turn off Boost support:
-if(NOT DEFINED HIGHFIVE_USE_BOOST)
-  set(HIGHFIVE_USE_BOOST Off)
-endif()
-
-# Include the subdirectory and use the target HighFive.
 add_subdirectory(third_party/HighFive)
 target_link_libraries(foo HighFive)
 ```
 
 **Note:** `add_subdirectory(third_party/HighFive)` will search and "link" HDF5
-and optional dependencies such as Boost.
+but wont search or link any optional dependencies such as Boost.
 
 ### Regular Installation of HighFive
 
-Alternatively you can install HighFive once and use it in several projects via
-`find_package()`. First one should clone the sources:
-```bash
-git clone --recursive https://github.com/BlueBrain/HighFive.git HighFive-src
-```
-By default CMake will install systemwide, which is likely not appropriate. The
-instruction below allow users to select a custom path where HighFive will be
-installed, e.g. `HIGHFIVE_INSTALL_PREFIX=${HOME}/third_party/HighFive` or some
-other location. The CMake invocations would be
-```bash
-cmake -DHIGHFIVE_EXAMPLES=Off \
-      -DHIGHFIVE_USE_BOOST=Off \
-      -DHIGHFIVE_UNIT_TESTS=Off \
-      -DCMAKE_INSTALL_PREFIX=${HIGHFIVE_INSTALL_PREFIX} \
-      -B HighFive-src/build \
-      HighFive-src
-
-cmake --build HighFive-src/build
-cmake --install HighFive-src/build
-```
-This will install (i.e. copy) the headers to
-`${HIGHFIVE_INSTALL_PREFIX}/include` and some CMake files into an appropriate
-subfolder of `${HIGHFIVE_INSTALL_PREFIX}`.
+Alternatively, HighFive can be install and "found" like regular software.
 
-The projects `CMakeLists.txt` should add the following:
+The project's `CMakeLists.txt` should add the following:
 ```cmake
-# ...
-add_executable(foo foo.cpp)
-
 find_package(HighFive REQUIRED)
 target_link_libraries(foo HighFive)
 ```
 
-**Note:** If HighFive hasn't been installed in a default location, CMake needs
-to be told where to find it which can be done by adding
-`-DCMAKE_PREFIX_PATH=${HIGHFIVE_INSTALL_PREFIX}` to the CMake command for
-building the project using HighFive. The variable `CMAKE_PREFIX_PATH` is a
-semi-colon `;` separated list of directories.
+**Note:** `find_package(HighFive)` will search for HDF5. "Linking" to
+`HighFive` includes linking with HDF5. The two commands will not search for or
+"link" to optional dependencies such as Boost.
 
-**Note:** `find_package(HighFive)` will search and "link" HDF5 and optional
-dependencies such as Boost.
+### Bailout Approach
 
-### The Bailout Approach
-Since both `add_subdirectory` and `find_package` will trigger finding HDF5 and
-other optional dependencies of HighFive as well as the `target_link_libraries`
-code for "linking" with the dependencies, things can go wrong.
+To prevent HighFive from searching or "linking" to HDF5 the project's
+`CMakeLists.txt` should contain the following:
 
-Fortunately, HighFive is a header only library and all that's needed is the
-headers. Preferably, the version obtained by installing HighFive, since those
-include `H5Version.hpp`. Let's assume they've been copied to
-`third_party/HighFive`. Then one could create a target:
+```cmake
+# Prevent HighFive CMake code from searching for HDF5:
+set(HIGHFIVE_FIND_HDF5 Off)
 
-```bash
-add_library(HighFive INTERFACE)
-target_include_directory(HighFive INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/HighFive/include)
+# Then "find" HighFive as usual:
+find_package(HighFive REQUIRED)
+# alternatively, when vendoring:
+# add_subdirectory(third_party/HighFive)
 
+# Finally, use the target `HighFive::Include` which
+# doesn't add a dependency on HDF5.
+target_link_libraries(foo HighFive::Include)
 
-add_executable(foo foo.cpp)
-target_link_libraries(foo HighFive)
+# Proceed to find and link HDF5 as required.
 ```
 
-One known case where this is required is when vendoring the optional
-dependencies of HighFive.
+### Optional Dependencies
+
+HighFive does not attempt to find or "link" to any optional dependencies, such
+as Boost, Eigen, etc. Any project using HighFive with any of the optional
+dependencies must include the respective header:
+```
+#include <highfive/boost.hpp>
+#include <highfive/eigen.hpp>
+```
+and add the required CMake code to find and link against the dependencies. For
+Boost the required lines might be
+```
+find_package(Boost REQUIRED)
+target_link_libraries(foo PUBLIC Boost::headers)
+```
 
 # Questions?
 
@@ -255,6 +250,10 @@ For bugs and issues please use [Issues](https://github.com/BlueBrain/HighFive/is
 # Funding & Acknowledgment
  
 The development of this software was supported by funding to the Blue Brain Project, a research center of the École polytechnique fédérale de Lausanne (EPFL), from the Swiss government's ETH Board of the Swiss Federal Institutes of Technology.
+
+HighFive releases are uploaded to Zenodo. If you wish to cite HighFive in a
+scientific publication you can use the DOIs for the
+[Zenodo records](https://zenodo.org/doi/10.5281/zenodo.10679422).
  
 Copyright © 2015-2022 Blue Brain Project/EPFL
 
diff --git a/packages/HighFive/cmake/HighFiveConfig.cmake b/packages/HighFive/cmake/HighFiveConfig.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..33ce7b7b0ed225805954e8efedf3e2de0841778f
--- /dev/null
+++ b/packages/HighFive/cmake/HighFiveConfig.cmake
@@ -0,0 +1,19 @@
+include(CMakeFindDependencyMacro)
+
+if(NOT DEFINED HIGHFIVE_FIND_HDF5)
+  set(HIGHFIVE_FIND_HDF5 On)
+endif()
+
+if(HIGHFIVE_FIND_HDF5)
+  find_dependency(HDF5)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/HighFiveTargets.cmake")
+
+if(HDF5_IS_PARALLEL)
+  find_dependency(MPI)
+  target_link_libraries(HighFive::HighFive INTERFACE MPI::MPI_C MPI::MPI_CXX)
+endif()
+
+add_library(HighFive ALIAS HighFive::HighFive)
+add_library(HighFiveInclude ALIAS HighFive::Include)
diff --git a/packages/HighFive/cmake/HighFiveOptionalDependencies.cmake b/packages/HighFive/cmake/HighFiveOptionalDependencies.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1b27edd10e5a89d7b07b552f485f206352057554
--- /dev/null
+++ b/packages/HighFive/cmake/HighFiveOptionalDependencies.cmake
@@ -0,0 +1,48 @@
+if(NOT TARGET HighFiveBoostDependency)
+  add_library(HighFiveBoostDependency INTERFACE)
+  if(HIGHFIVE_TEST_BOOST)
+    find_package(Boost REQUIRED)
+    target_link_libraries(HighFiveBoostDependency INTERFACE Boost::headers)
+    # TODO check if we need Boost::disable_autolinking to cause:
+    # -DBOOST_ALL_NO_LIB (does something on MSVC).
+    target_compile_definitions(HighFiveBoostDependency INTERFACE HIGHFIVE_TEST_BOOST=1)
+  endif()
+endif()
+
+if(NOT TARGET HighFiveEigenDependency)
+  add_library(HighFiveEigenDependency INTERFACE)
+  if(HIGHFIVE_TEST_EIGEN)
+    find_package(Eigen3 REQUIRED NO_MODULE)
+    target_link_libraries(HighFiveEigenDependency INTERFACE Eigen3::Eigen)
+    target_compile_definitions(HighFiveEigenDependency INTERFACE HIGHFIVE_TEST_EIGEN=1)
+  endif()
+endif()
+
+if(NOT TARGET HighFiveXTensorDependency)
+  add_library(HighFiveXTensorDependency INTERFACE)
+  if(HIGHFIVE_TEST_XTENSOR)
+    find_package(xtensor REQUIRED)
+    target_link_libraries(HighFiveXTensorDependency INTERFACE xtensor)
+    target_compile_definitions(HighFiveXTensorDependency INTERFACE HIGHFIVE_TEST_XTENSOR=1)
+  endif()
+endif()
+
+if(NOT TARGET HighFiveOpenCVDependency)
+  add_library(HighFiveOpenCVDependency INTERFACE)
+  if(HIGHFIVE_TEST_OPENCV)
+    find_package(OpenCV REQUIRED)
+    target_include_directories(HighFiveOpenCVDependency SYSTEM INTERFACE ${OpenCV_INCLUDE_DIRS})
+    target_link_libraries(HighFiveOpenCVDependency INTERFACE ${OpenCV_LIBS})
+    target_compile_definitions(HighFiveOpenCVDependency INTERFACE HIGHFIVE_TEST_OPENCV=1)
+  endif()
+endif()
+
+if(NOT TARGET HighFiveOptionalDependencies)
+  add_library(HighFiveOptionalDependencies INTERFACE)
+  target_link_libraries(HighFiveOptionalDependencies INTERFACE
+    HighFiveBoostDependency
+    HighFiveEigenDependency
+    HighFiveXTensorDependency
+    HighFiveOpenCVDependency
+  )
+endif()
diff --git a/packages/HighFive/CMake/HighFiveWarnings.cmake b/packages/HighFive/cmake/HighFiveWarnings.cmake
similarity index 67%
rename from packages/HighFive/CMake/HighFiveWarnings.cmake
rename to packages/HighFive/cmake/HighFiveWarnings.cmake
index 16896b6489367481efdf00142df7e3fee7d0ec18..3f569d5d568078faccd91de2f5755d99578bd73f 100644
--- a/packages/HighFive/CMake/HighFiveWarnings.cmake
+++ b/packages/HighFive/cmake/HighFiveWarnings.cmake
@@ -6,6 +6,7 @@ if(TARGET HighFiveWarnings)
 endif()
 
 add_library(HighFiveWarnings INTERFACE)
+add_library(HighFiveFlags INTERFACE)
 
 if(CMAKE_CXX_COMPILER_ID MATCHES "Clang"
    OR CMAKE_CXX_COMPILER_ID MATCHES "GNU"
@@ -31,13 +32,25 @@ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang"
                 -Wcast-align
                 -Wdouble-promotion
         )
-    endif()
 
-    if(HIGHFIVE_HAS_WERROR)
         target_compile_options(HighFiveWarnings
             INTERFACE
-                -Werror
-                -Wno-error=deprecated-declarations
+                -ftemplate-backtrace-limit=0
         )
+
+      if(HIGHFIVE_MAX_ERRORS)
+          target_compile_options(HighFiveFlags
+              INTERFACE
+              -fmax-errors=${HIGHFIVE_MAX_ERRORS}
+          )
+      endif()
+
+      if(HIGHFIVE_HAS_WERROR)
+          target_compile_options(HighFiveWarnings
+              INTERFACE
+                  -Werror
+                  -Wno-error=deprecated-declarations
+          )
+      endif()
     endif()
 endif()
diff --git a/packages/HighFive/deps/catch2 b/packages/HighFive/deps/catch2
new file mode 160000
index 0000000000000000000000000000000000000000..3f0283de7a9c43200033da996ff9093be3ac84dc
--- /dev/null
+++ b/packages/HighFive/deps/catch2
@@ -0,0 +1 @@
+Subproject commit 3f0283de7a9c43200033da996ff9093be3ac84dc
diff --git a/packages/HighFive/doc/developer_guide.md b/packages/HighFive/doc/developer_guide.md
index fc388f3b5f7449dfa110a74e170b951ffec2dd21..13e360fc3dd209653ac185da1159f1e3de6f453a 100644
--- a/packages/HighFive/doc/developer_guide.md
+++ b/packages/HighFive/doc/developer_guide.md
@@ -23,8 +23,13 @@ cmake --build build --parallel
 ctest --test-dir build
 ```
 
-You might want to turn off Boost `-DHIGHFIVE_USE_BOOST=Off` or turn on other
-optional dependencies.
+You might want to add:
+* `-DHIGHFIVE_TEST_BOOST=On` or other optional dependencies on,
+* `-DHIGHFIVE_MAX_ERROR=3` to only show the first three errors.
+
+Generic CMake reminders:
+* `-DCMAKE_INSTALL_PREFIX` defines where HighFive will be installed,
+* `-DCMAKE_PREFIX_PATH` defines where `*Config.cmake` files are found.
 
 ## Contributing
 There's numerous HDF5 features that haven't been wrapped yet. HighFive is a
@@ -90,6 +95,7 @@ release. Once this is done perform a final round of updates:
 * Download the archive (`*.tar.gz`) and compute its SHA256.
 * Update BlueBrain Spack recipe to use the archive and not the Git commit.
 * Update the upstream Spack recipe.
+* A Zenodo record should be generated automatically, check if it's sensible.
 
 ## Writing Tests
 ### Generate Multi-Dimensional Test Data
diff --git a/packages/HighFive/doc/doxygen-awesome-css/doxygen-awesome.css b/packages/HighFive/doc/doxygen-awesome-css/doxygen-awesome.css
index ac7f0608ec69a90204ed8a599c159d2c5c8054e4..a44945b366e56d59fde2db58361f213f2ae0f79c 100644
--- a/packages/HighFive/doc/doxygen-awesome-css/doxygen-awesome.css
+++ b/packages/HighFive/doc/doxygen-awesome-css/doxygen-awesome.css
@@ -313,7 +313,7 @@ body {
 body, table, div, p, dl, #nav-tree .label, .title,
 .sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname,
 .SelectItem, #MSearchField, .navpath li.navelem a,
-.navpath li.navelem a:hover, p.reference, p.definition {
+.navpath li.navelem a:hover, p.reference, p.definition, div.toc li, div.toc h3 {
     font-family: var(--font-family);
 }
 
@@ -334,6 +334,7 @@ p.reference, p.definition {
 a:link, a:visited, a:hover, a:focus, a:active {
     color: var(--primary-color) !important;
     font-weight: 500;
+    background: none;
 }
 
 a.anchor {
@@ -806,6 +807,10 @@ html.dark-mode iframe#MSearchResults {
     line-height: var(--tree-item-height);
 }
 
+#nav-tree .item > a:focus {
+    outline: none;
+}
+
 #nav-sync {
     bottom: 12px;
     right: 12px;
@@ -843,6 +848,7 @@ html.dark-mode iframe#MSearchResults {
 
 #nav-tree .arrow {
     opacity: var(--side-nav-arrow-opacity);
+    background: none;
 }
 
 .arrow {
@@ -2460,17 +2466,17 @@ h2:hover a.anchorlink, h1:hover a.anchorlink, h3:hover a.anchorlink, h4:hover a.
  Optional tab feature
 */
 
-.tabbed ul {
+.tabbed > ul {
     padding-inline-start: 0px;
     margin: 0;
     padding: var(--spacing-small) 0;
 }
 
-.tabbed li {
+.tabbed > ul > li {
     display: none;
 }
 
-.tabbed li.selected {
+.tabbed > ul > li.selected {
     display: block;
 }
 
diff --git a/packages/HighFive/doc/installation.md b/packages/HighFive/doc/installation.md
index e9c5b2e6e1884e9e2ea7cc99a88335b2020b6040..3dfb3dc4b50f4f04f66e1f25322e33cd28066b54 100644
--- a/packages/HighFive/doc/installation.md
+++ b/packages/HighFive/doc/installation.md
@@ -211,7 +211,7 @@ this you type
 
 Okay, on to configure, compile and install. The CMake commands are
 
-    cmake -DCMAKE_INSTALL_PREFIX=build/install -DHIGHFIVE_USE_BOOST=Off -B build .
+    cmake -DCMAKE_INSTALL_PREFIX=build/install -B build .
     cmake --build build --parallel
     cmake --install build
 
diff --git a/packages/HighFive/doc/migration_guide.md b/packages/HighFive/doc/migration_guide.md
index e85002b150c5c002a9d896736946c0260429cc58..2ffe9e2570de2cea0747b13b4f2020c54e4facdc 100644
--- a/packages/HighFive/doc/migration_guide.md
+++ b/packages/HighFive/doc/migration_guide.md
@@ -14,3 +14,121 @@ replaced with an `std::vector<std::string>` (for example).
 
 If desired one can silence warnings by replacing `FixedLenStringArray` with
 `deprecated::FixedLenStringArray`.
+
+
+## Deprecation of `read(T*, ...)`.
+A "raw read" is when the user allocates sufficient bytes and provides HighFive
+with the pointer to the first byte. "Regular reads" take a detour via the
+inspector and might resize the container, etc.
+
+The issue is that HighFive `v2` had the following two overloads:
+```
+template<class T>
+DataSet::read(T& x, /* skipped */);
+
+template<class T>
+DataSet::read(T* x, /* skipped */);
+```
+and the analogous for `Attribute`.
+
+The issue is that the second overload will also match things like `T**` and
+`T[][]`. For example the following code used the removed overload:
+```
+double x[2][3];
+dset.read(x);
+```
+which is fine because is a contiguous sequence of doubles. It's equivalent to
+following `v3` code:
+```
+double x[2][3];
+dset.read_raw((double*) x);
+```
+
+### Accidental Raw Read
+We consider the example above to be accidentally using a raw read, when it
+could be performing a regular read. We suggest to not change the above, i.e.
+```
+double x[2][3];
+dset.read(x);
+```
+continues to be correct in `v3` and can check that the dimensions match. The
+inspector recognizes `double[2][3]` as a contiguous array of doubles.
+Therefore, it'll use the shallow-copy buffer and avoid the any additional
+allocations or copies.
+
+### Intentional Raw Read
+When genuinely performing a "raw read", one must replace `read` with
+`read_raw`. For example:
+
+```
+double* x = malloc(2*3 * sizeof(double));
+dset.read_raw(x);
+```
+is correct in `v3`.
+
+## Reworked CMake
+In `v3` we completely rewrote the CMake code of HighFive. Since HighFive is a
+header only library, it needs to perform two tasks:
+
+1. Copy the sources during installation.
+2. Export a target that sets `-I ${HIGHFIVE_DIR}` and links with HDF5.
+
+We've removed all flags for optional dependencies, such as
+`-DHIGHFIVE_USE_BOOST`. Instead user that want to read/write into/from
+optionally supported containers, include a header with the corresponding name
+and make sure to adjust their CMake code to link with the dependency.
+
+The C++ code should have:
+```
+#include <highfive/boost.hpp>
+
+// Code the reads or write `boost::multi_array`.
+```
+and the CMake code would have
+```
+add_executable(app)
+
+# These lines might work, but depend on how exactly the user intends to use
+# Boost. They are not specific to HighFive, but previously added automatically
+# (and sometimes correctly) by HighFive.
+find_package(Boost)
+target_link_libraries(add PUBLIC boost::boost)
+
+# For HighFive there's two options for adding `-I ${HIGHFIVE_DIR}` and the
+# flags for HDF5.
+#
+# Option 1: HighFive is install (systemwide) as a regular library:
+find_package(HighFive)
+target_link_libraries(app PUBLIC HighFive::HighFive)
+
+# Option 2: HighFive is vendored as part of the project:
+add_subdirectory(third_party/HighFive)
+target_link_libraries(app PUBLIC HighFive::HighFive)
+```
+
+There are extensive examples of project integration in `tests/cmake_integration`,
+including how those projects in turn can be included in other projects. If these
+examples don't help, please feel free to open an Issue.
+
+## Type change `DataSpace::DataSpaceType`.
+We've converted the `enum` `DataSpace::DataSpaceType` to an `enum class`. We've
+added static `constexpr` members `dataspace_null` and `dataspace_scalar` to
+`DataSpace`. This minimizes the risk of breaking user code.
+
+Note that objects of type `DataSpace::DataSpaceType` will no longer silently
+convert to an integer. Including the two constants
+`DataSpace::dataspace_{scalar,null}`.
+
+## Deprecation `FileDriver` and `MPIOFileDriver`.
+These have been deprecated to stick more closely with familiar HDF5 concepts.
+The `FileDriver` is synonymous to `FileAccessProps`; and `MPIOFileDriver` is
+the same as:
+```
+auto fapl = FileAccessProps{};
+fapl.add(MPIOFileAccess(mpi_comm, mpi_info));
+```
+
+We felt that the savings in typing effort weren't worth introducing the concept
+of a "file driver". Removing the concept hopefully makes it easier to add a
+better abstraction for the handling of the property lists, when we discover
+such an abstraction.
diff --git a/packages/HighFive/include/highfive/H5Attribute.hpp b/packages/HighFive/include/highfive/H5Attribute.hpp
index 810d388ae8ef555ff2417c3e5cf56edef212f003..c34f9e49f88ee9cac0ee3763ec4a46f84cc2305b 100644
--- a/packages/HighFive/include/highfive/H5Attribute.hpp
+++ b/packages/HighFive/include/highfive/H5Attribute.hpp
@@ -132,7 +132,7 @@ class Attribute: public Object, public PathTraits<Attribute> {
     /// \endcode
     /// \since 2.2.2
     template <typename T>
-    void read(T* array, const DataType& mem_datatype) const;
+    void read_raw(T* array, const DataType& mem_datatype) const;
 
     /// \brief Read the attribute into a buffer.
     /// Behaves like Attribute::read(T*, const DataType&) const but
@@ -154,7 +154,7 @@ class Attribute: public Object, public PathTraits<Attribute> {
     /// \endcode
     /// \since 2.2.2
     template <typename T>
-    void read(T* array) const;
+    void read_raw(T* array) const;
 
     /// \brief Write the value into the Attribute.
     ///
diff --git a/packages/HighFive/include/highfive/H5DataSet.hpp b/packages/HighFive/include/highfive/H5DataSet.hpp
index 0236f06c23054fa9e4d937ca87e78a260511cadc..566eb17ffe263e19b40d520afe1ce36775cb3de5 100644
--- a/packages/HighFive/include/highfive/H5DataSet.hpp
+++ b/packages/HighFive/include/highfive/H5DataSet.hpp
@@ -98,8 +98,6 @@ class DataSet: public Object,
         return details::get_plist<DataSetAccessProps>(*this, H5Dget_access_plist);
     }
 
-    /// \deprecated Default constructor creates unsafe uninitialized objects
-    H5_DEPRECATED("Default constructor creates unsafe uninitialized objects")
     DataSet() = default;
 
   protected:
diff --git a/packages/HighFive/include/highfive/H5DataSpace.hpp b/packages/HighFive/include/highfive/H5DataSpace.hpp
index 7c7c5860abf93239befb9c77d791e617c9c27136..463648507a9fea2c7ffd27cbca1230348b4c3385 100644
--- a/packages/HighFive/include/highfive/H5DataSpace.hpp
+++ b/packages/HighFive/include/highfive/H5DataSpace.hpp
@@ -45,12 +45,16 @@ class DataSpace: public Object {
     /// This enum is needed otherwise we will not be able to distringuish between both with normal
     /// constructors. Both have a dimension of 0.
     /// \since 1.3
-    enum DataspaceType {
+    enum class DataspaceType {
         dataspace_scalar,  ///< Value to create scalar DataSpace
         dataspace_null,    ///< Value to create null DataSpace
         // simple dataspace are handle directly from their dimensions
     };
 
+    // For backward compatibility: `DataSpace::dataspace_scalar`.
+    constexpr static DataspaceType dataspace_scalar = DataspaceType::dataspace_scalar;
+    constexpr static DataspaceType dataspace_null = DataspaceType::dataspace_null;
+
     /// \brief Create a DataSpace of N-dimensions from a std::vector<size_t>.
     /// \param dims Dimensions of the new DataSpace
     ///
diff --git a/packages/HighFive/include/highfive/H5DataType.hpp b/packages/HighFive/include/highfive/H5DataType.hpp
index b15f62165afcf5adc4254d79dc41acbb9889404c..985eb6dd457fea7037df20386a6e553e8ec3b4ee 100644
--- a/packages/HighFive/include/highfive/H5DataType.hpp
+++ b/packages/HighFive/include/highfive/H5DataType.hpp
@@ -340,133 +340,6 @@ DataType create_datatype();
 /// \brief Create a DataType instance representing type T and perform a sanity check on its size
 template <typename T>
 DataType create_and_check_datatype();
-
-
-namespace deprecated {
-///
-/// \brief A structure representing a set of fixed-length strings
-///
-/// Although fixed-len arrays can be created 'raw' without the need for
-/// this structure, to retrieve results efficiently it must be used.
-///
-/// \tparam N Size of the string in bytes, including the null character. Note,
-///           that all string must be null-terminated.
-///
-template <std::size_t N>
-class FixedLenStringArray {
-  public:
-    FixedLenStringArray() = default;
-
-    ///
-    /// \brief Create a FixedStringArray from a raw contiguous buffer.
-    ///
-    /// The argument `n_strings` specifies the number of strings.
-    ///
-    FixedLenStringArray(const char array[][N], std::size_t n_strings);
-
-    ///
-    /// \brief Create a FixedStringArray from a sequence of strings.
-    ///
-    /// Such conversion involves a copy, original vector is not modified
-    ///
-    explicit FixedLenStringArray(const std::vector<std::string>& vec);
-
-    FixedLenStringArray(const std::string* iter_begin, const std::string* iter_end);
-
-    FixedLenStringArray(const std::initializer_list<std::string>&);
-
-    ///
-    /// \brief Append an std::string to the buffer structure
-    ///
-    void push_back(const std::string&);
-
-    void push_back(const std::array<char, N>&);
-
-    ///
-    /// \brief Retrieve a string from the structure as std::string
-    ///
-    std::string getString(std::size_t index) const;
-
-    // Container interface
-    inline const char* operator[](std::size_t i) const noexcept {
-        return datavec[i].data();
-    }
-    inline const char* at(std::size_t i) const {
-        return datavec.at(i).data();
-    }
-    inline bool empty() const noexcept {
-        return datavec.empty();
-    }
-    inline std::size_t size() const noexcept {
-        return datavec.size();
-    }
-    inline void resize(std::size_t n) {
-        datavec.resize(n);
-    }
-    inline const char* front() const {
-        return datavec.front().data();
-    }
-    inline const char* back() const {
-        return datavec.back().data();
-    }
-    inline char* data() noexcept {
-        return datavec[0].data();
-    }
-    inline const char* data() const noexcept {
-        return datavec[0].data();
-    }
-
-  private:
-    using vector_t = typename std::vector<std::array<char, N>>;
-
-  public:
-    // Use the underlying iterator
-    using iterator = typename vector_t::iterator;
-    using const_iterator = typename vector_t::const_iterator;
-    using reverse_iterator = typename vector_t::reverse_iterator;
-    using const_reverse_iterator = typename vector_t::const_reverse_iterator;
-    using value_type = typename vector_t::value_type;
-
-    inline iterator begin() noexcept {
-        return datavec.begin();
-    }
-    inline iterator end() noexcept {
-        return datavec.end();
-    }
-    inline const_iterator begin() const noexcept {
-        return datavec.begin();
-    }
-    inline const_iterator cbegin() const noexcept {
-        return datavec.cbegin();
-    }
-    inline const_iterator end() const noexcept {
-        return datavec.end();
-    }
-    inline const_iterator cend() const noexcept {
-        return datavec.cend();
-    }
-    inline reverse_iterator rbegin() noexcept {
-        return datavec.rbegin();
-    }
-    inline reverse_iterator rend() noexcept {
-        return datavec.rend();
-    }
-    inline const_reverse_iterator rbegin() const noexcept {
-        return datavec.rbegin();
-    }
-    inline const_reverse_iterator rend() const noexcept {
-        return datavec.rend();
-    }
-
-  private:
-    vector_t datavec;
-};
-}  // namespace deprecated
-
-template <size_t N>
-using FixedLenStringArray H5_DEPRECATED_USING("Use 'std::vector<std::string>'.") =
-    deprecated::FixedLenStringArray<N>;
-
 }  // namespace HighFive
 
 
@@ -475,12 +348,15 @@ using FixedLenStringArray H5_DEPRECATED_USING("Use 'std::vector<std::string>'.")
 /// This macro has to be called outside of any namespace.
 ///
 /// \code{.cpp}
+/// namespace app {
 /// enum FooBar { FOO = 1, BAR = 2 };
 /// EnumType create_enum_foobar() {
 ///    return EnumType<FooBar>({{"FOO", FooBar::FOO},
 ///                             {"BAR", FooBar::BAR}});
 /// }
-/// HIGHFIVE_REGISTER_TYPE(FooBar, create_enum_foobar)
+/// }
+///
+/// HIGHFIVE_REGISTER_TYPE(FooBar, ::app::create_enum_foobar)
 /// \endcode
 #define HIGHFIVE_REGISTER_TYPE(type, function)                    \
     template <>                                                   \
diff --git a/packages/HighFive/include/highfive/H5File.hpp b/packages/HighFive/include/highfive/H5File.hpp
index 9b393e5a35ea28411d59a5d29b87e3f31bbbb23d..a8db5f2a13283da4926547c1d88e6a583d0c46b8 100644
--- a/packages/HighFive/include/highfive/H5File.hpp
+++ b/packages/HighFive/include/highfive/H5File.hpp
@@ -10,7 +10,6 @@
 
 #include <string>
 
-#include "H5FileDriver.hpp"
 #include "H5Object.hpp"
 #include "H5PropertyList.hpp"
 #include "bits/H5Annotate_traits.hpp"
diff --git a/packages/HighFive/include/highfive/H5FileDriver.hpp b/packages/HighFive/include/highfive/H5FileDriver.hpp
deleted file mode 100644
index 2cd4813a36112407166a3815828ba0918e4b88b0..0000000000000000000000000000000000000000
--- a/packages/HighFive/include/highfive/H5FileDriver.hpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Copyright (c), 2017, Adrien Devresse <adrien.devresse@epfl.ch>
- *
- *  Distributed under the Boost Software License, Version 1.0.
- *    (See accompanying file LICENSE_1_0.txt or copy at
- *          http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-#pragma once
-
-#include "H5PropertyList.hpp"
-#include "bits/H5_definitions.hpp"
-
-namespace HighFive {
-
-/// \brief file driver base concept
-/// \deprecated Use FileAccessProps directly
-class H5_DEPRECATED("Use FileAccessProps directly") FileDriver: public FileAccessProps {};
-
-#ifdef H5_HAVE_PARALLEL
-/// \brief MPIIO Driver for Parallel HDF5
-/// \deprecated Add MPIOFileAccess directly to FileAccessProps
-class H5_DEPRECATED("Add MPIOFileAccess directly to FileAccessProps") MPIOFileDriver
-    : public FileAccessProps {
-  public:
-    inline MPIOFileDriver(MPI_Comm mpi_comm, MPI_Info mpi_info);
-};
-#endif
-
-}  // namespace HighFive
-
-#include "bits/H5FileDriver_misc.hpp"
diff --git a/packages/HighFive/include/highfive/H5Group.hpp b/packages/HighFive/include/highfive/H5Group.hpp
index 0a6a4cdae605012f25ca541a9d584f743af1c93b..eebfcbb3ee0d0789c7d1e87bc26491e6ac3530da 100644
--- a/packages/HighFive/include/highfive/H5Group.hpp
+++ b/packages/HighFive/include/highfive/H5Group.hpp
@@ -47,8 +47,6 @@ class Group: public Object,
   public:
     const static ObjectType type = ObjectType::Group;
 
-    /// \deprecated Default constructor creates unsafe uninitialized objects
-    H5_DEPRECATED("Default constructor creates unsafe uninitialized objects")
     Group() = default;
 
     std::pair<unsigned int, unsigned int> getEstimatedLinkInfo() const;
diff --git a/packages/HighFive/include/highfive/H5Version.hpp b/packages/HighFive/include/highfive/H5Version.hpp
index bca2c3a83066e9e666840473c355c5ade91f1b87..4ffb036452953562b86ff2962de9045ccf518482 100644
--- a/packages/HighFive/include/highfive/H5Version.hpp
+++ b/packages/HighFive/include/highfive/H5Version.hpp
@@ -8,8 +8,8 @@
  */
 #pragma once
 
-#define HIGHFIVE_VERSION_MAJOR 2
-#define HIGHFIVE_VERSION_MINOR 9
+#define HIGHFIVE_VERSION_MAJOR 3
+#define HIGHFIVE_VERSION_MINOR 0
 #define HIGHFIVE_VERSION_PATCH 0
 
 /** \brief Concatenated representation of the HighFive version.
@@ -24,10 +24,10 @@
  *  std::cout << STRINGIFY_VALUE(HIGHFIVE_VERSION) << "\n";
  *  \endcode
  */
-#define HIGHFIVE_VERSION 2.9.0
+#define HIGHFIVE_VERSION 3.0.0
 
 /** \brief String representation of the HighFive version.
  *
  *  \warning This macro only exists from 2.7.1 onwards.
  */
-#define HIGHFIVE_VERSION_STRING "2.9.0"
+#define HIGHFIVE_VERSION_STRING "3.0.0"
diff --git a/packages/HighFive/include/highfive/bits/H5Attribute_misc.hpp b/packages/HighFive/include/highfive/bits/H5Attribute_misc.hpp
index cc235b50074f90f948e8b4b22678e1ee44091274..19eceb49fb81bbc003d138ccb1a54ce2f30a7213 100644
--- a/packages/HighFive/include/highfive/bits/H5Attribute_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Attribute_misc.hpp
@@ -31,6 +31,10 @@ inline std::string Attribute::getName() const {
 }
 
 inline size_t Attribute::getStorageSize() const {
+    if (!this->isValid()) {
+        throw AttributeException("Invalid call to `DataSet::getFile` for invalid object");
+    }
+
     return static_cast<size_t>(detail::h5a_get_storage_size(_hid));
 }
 
@@ -83,7 +87,7 @@ inline void Attribute::read(T& array) const {
     }
 
     auto r = details::data_converter::get_reader<T>(dims, array, file_datatype);
-    read(r.getPointer(), buffer_info.data_type);
+    read_raw(r.getPointer(), buffer_info.data_type);
     // re-arrange results
     r.unserialize(array);
 
@@ -102,7 +106,7 @@ inline void Attribute::read(T& array) const {
 }
 
 template <typename T>
-inline void Attribute::read(T* array, const DataType& mem_datatype) const {
+inline void Attribute::read_raw(T* array, const DataType& mem_datatype) const {
     static_assert(!std::is_const<T>::value,
                   "read() requires a non-const structure to read data into");
 
@@ -110,16 +114,17 @@ inline void Attribute::read(T* array, const DataType& mem_datatype) const {
 }
 
 template <typename T>
-inline void Attribute::read(T* array) const {
+inline void Attribute::read_raw(T* array) const {
     using element_type = typename details::inspector<T>::base_type;
     const DataType& mem_datatype = create_and_check_datatype<element_type>();
 
-    read(array, mem_datatype);
+    read_raw(array, mem_datatype);
 }
 
 template <typename T>
 inline void Attribute::write(const T& buffer) {
     const DataSpace& mem_space = getMemSpace();
+    auto dims = mem_space.getDimensions();
 
     if (mem_space.getElementCount() == 0) {
         return;
@@ -138,7 +143,7 @@ inline void Attribute::write(const T& buffer) {
            << " into dataset of dimensions " << mem_space.getNumberDimensions();
         throw DataSpaceException(ss.str());
     }
-    auto w = details::data_converter::serialize<T>(buffer, file_datatype);
+    auto w = details::data_converter::serialize<T>(buffer, dims, file_datatype);
     write_raw(w.getPointer(), buffer_info.data_type);
 }
 
diff --git a/packages/HighFive/include/highfive/bits/H5Converter_misc.hpp b/packages/HighFive/include/highfive/bits/H5Converter_misc.hpp
index ed387702fac981ef9b1169d0adca99b25f6cd6b5..d1ba132c45e05bcbeb30f2f27de4e6795e494496 100644
--- a/packages/HighFive/include/highfive/bits/H5Converter_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Converter_misc.hpp
@@ -69,7 +69,7 @@ struct DeepCopyBuffer {
     using hdf5_type = typename inspector<type>::hdf5_type;
 
     explicit DeepCopyBuffer(const std::vector<size_t>& _dims)
-        : buffer(inspector<T>::getSize(_dims))
+        : buffer(compute_total_size(_dims))
         , dims(_dims) {}
 
     hdf5_type* getPointer() {
@@ -344,23 +344,27 @@ struct Writer<T, typename enable_shallow_copy<T>::type>: public ShallowCopyBuffe
     using super = ShallowCopyBuffer<T, true>;
 
   public:
-    explicit Writer(const T& val, const DataType& /* file_datatype */)
+    explicit Writer(const T& val,
+                    const std::vector<size_t>& /* dims */,
+                    const DataType& /* file_datatype */)
         : super(val){};
 };
 
 template <typename T>
 struct Writer<T, typename enable_deep_copy<T>::type>: public DeepCopyBuffer<T> {
-    explicit Writer(const T& val, const DataType& /* file_datatype */)
-        : DeepCopyBuffer<T>(inspector<T>::getDimensions(val)) {
-        inspector<T>::serialize(val, this->begin());
+    explicit Writer(const T& val,
+                    const std::vector<size_t>& _dims,
+                    const DataType& /* file_datatype */)
+        : DeepCopyBuffer<T>(_dims) {
+        inspector<T>::serialize(val, _dims, this->begin());
     }
 };
 
 template <typename T>
 struct Writer<T, typename enable_string_copy<T>::type>: public StringBuffer<T, BufferMode::Write> {
-    explicit Writer(const T& val, const DataType& _file_datatype)
-        : StringBuffer<T, BufferMode::Write>(inspector<T>::getDimensions(val), _file_datatype) {
-        inspector<T>::serialize(val, this->begin());
+    explicit Writer(const T& val, const std::vector<size_t>& _dims, const DataType& _file_datatype)
+        : StringBuffer<T, BufferMode::Write>(_dims, _file_datatype) {
+        inspector<T>::serialize(val, _dims, this->begin());
     }
 };
 
@@ -402,8 +406,9 @@ struct Reader<T, typename enable_string_copy<T>::type>: public StringBuffer<T, B
 struct data_converter {
     template <typename T>
     static Writer<T> serialize(const typename inspector<T>::type& val,
+                               const std::vector<size_t>& dims,
                                const DataType& file_datatype) {
-        return Writer<T>(val, file_datatype);
+        return Writer<T>(val, dims, file_datatype);
     }
 
     template <typename T>
diff --git a/packages/HighFive/include/highfive/bits/H5DataSet_misc.hpp b/packages/HighFive/include/highfive/bits/H5DataSet_misc.hpp
index 4817fe00151f869dc6d352087a4d5cd713982365..45e530efc6284eeccbb985908303ca2316593e1e 100644
--- a/packages/HighFive/include/highfive/bits/H5DataSet_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5DataSet_misc.hpp
@@ -22,6 +22,10 @@
 namespace HighFive {
 
 inline uint64_t DataSet::getStorageSize() const {
+    if (!this->isValid()) {
+        throw DataSetException("Invalid call to `DataSet::getStorageSize` for invalid object");
+    }
+
     return detail::h5d_get_storage_size(_hid);
 }
 
diff --git a/packages/HighFive/include/highfive/bits/H5DataType_misc.hpp b/packages/HighFive/include/highfive/bits/H5DataType_misc.hpp
index 619e51e7189e47db7649100c63c1ef82837b8536..4321a4658882d0905993173a8c1b872a53400d7f 100644
--- a/packages/HighFive/include/highfive/bits/H5DataType_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5DataType_misc.hpp
@@ -206,13 +206,6 @@ class AtomicType<char[StrLen]>: public DataType {
         : DataType(create_string(StrLen)) {}
 };
 
-template <size_t StrLen>
-class AtomicType<deprecated::FixedLenStringArray<StrLen>>: public DataType {
-  public:
-    inline AtomicType()
-        : DataType(create_string(StrLen)) {}
-};
-
 template <typename T>
 class AtomicType<std::complex<T>>: public DataType {
   public:
@@ -239,51 +232,6 @@ AtomicType<T>::AtomicType() {
 }
 
 
-namespace deprecated {
-template <std::size_t N>
-inline FixedLenStringArray<N>::FixedLenStringArray(const char array[][N], std::size_t length) {
-    datavec.resize(length);
-    std::memcpy(datavec[0].data(), array[0].data(), N * length);
-}
-
-template <std::size_t N>
-inline FixedLenStringArray<N>::FixedLenStringArray(const std::string* iter_begin,
-                                                   const std::string* iter_end) {
-    datavec.reserve(static_cast<std::size_t>(iter_end - iter_begin));
-    for (std::string const* it = iter_begin; it != iter_end; ++it) {
-        push_back(*it);
-    }
-}
-
-template <std::size_t N>
-inline FixedLenStringArray<N>::FixedLenStringArray(const std::vector<std::string>& vec)
-    : FixedLenStringArray(vec.data(), vec.data() + vec.size()) {}
-
-template <std::size_t N>
-inline FixedLenStringArray<N>::FixedLenStringArray(
-    const std::initializer_list<std::string>& init_list)
-    : FixedLenStringArray(init_list.begin(), init_list.end()) {}
-
-template <std::size_t N>
-inline void FixedLenStringArray<N>::push_back(const std::string& src) {
-    datavec.emplace_back();
-    const size_t length = std::min(N - 1, src.length());
-    std::memcpy(datavec.back().data(), src.c_str(), length);
-    datavec.back()[length] = 0;
-}
-
-template <std::size_t N>
-inline void FixedLenStringArray<N>::push_back(const std::array<char, N>& src) {
-    datavec.emplace_back();
-    std::copy(src.begin(), src.end(), datavec.back().data());
-}
-
-template <std::size_t N>
-inline std::string FixedLenStringArray<N>::getString(std::size_t i) const {
-    return std::string(datavec[i].data());
-}
-}  // namespace deprecated
-
 // Internal
 // Reference mapping
 template <>
@@ -520,7 +468,3 @@ inline DataType create_datatype<bool>() {
 }
 
 }  // namespace HighFive
-
-#ifdef H5_USE_HALF_FLOAT
-#include <highfive/half_float.hpp>
-#endif
diff --git a/packages/HighFive/include/highfive/bits/H5FileDriver_misc.hpp b/packages/HighFive/include/highfive/bits/H5FileDriver_misc.hpp
deleted file mode 100644
index a6331bd5a9fc86a1ff182db46206fa4805b40a7d..0000000000000000000000000000000000000000
--- a/packages/HighFive/include/highfive/bits/H5FileDriver_misc.hpp
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- *  Copyright (c), 2017-2018, Adrien Devresse <adrien.devresse@epfl.ch>
- *                            Juan Hernando <juan.hernando@epfl.ch>
- *
- *  Distributed under the Boost Software License, Version 1.0.
- *    (See accompanying file LICENSE_1_0.txt or copy at
- *          http://www.boost.org/LICENSE_1_0.txt)
- *
- */
-#pragma once
-
-namespace HighFive {
-
-#ifdef H5_HAVE_PARALLEL
-inline MPIOFileDriver::MPIOFileDriver(MPI_Comm comm, MPI_Info info) {
-    add(MPIOFileAccess(comm, info));
-}
-#endif
-
-}  // namespace HighFive
diff --git a/packages/HighFive/include/highfive/bits/H5Inspector_misc.hpp b/packages/HighFive/include/highfive/bits/H5Inspector_misc.hpp
index 7ae90d84f167e3757b5246787971929cbb6a73bd..3f69276c45ac5f32b720f6369df7ff7103e872b4 100644
--- a/packages/HighFive/include/highfive/bits/H5Inspector_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Inspector_misc.hpp
@@ -77,7 +77,7 @@ inline std::vector<size_t> squeezeDimensions(const std::vector<size_t>& dims,
 
     if (n_dim_requested == 0) {
         if (!checkDimensions(dims, n_dim_requested)) {
-            throw std::invalid_argument(format_error_message());
+            throw std::invalid_argument("Failed dimensions check: " + format_error_message());
         }
 
         return {1ul};
@@ -85,7 +85,7 @@ inline std::vector<size_t> squeezeDimensions(const std::vector<size_t>& dims,
 
     auto n_dim = dims.size();
     if (n_dim < n_dim_requested) {
-        throw std::invalid_argument(format_error_message());
+        throw std::invalid_argument("Failed 'n_dim < n_dim_requested: " + format_error_message());
     }
 
     if (n_dim_requested == 1ul) {
@@ -95,7 +95,8 @@ inline std::vector<size_t> squeezeDimensions(const std::vector<size_t>& dims,
                 if (non_singleton_dim == size_t(-1)) {
                     non_singleton_dim = i;
                 } else {
-                    throw std::invalid_argument(format_error_message());
+                    throw std::invalid_argument("Failed one-dimensional: " +
+                                                format_error_message());
                 }
             }
         }
@@ -106,7 +107,7 @@ inline std::vector<size_t> squeezeDimensions(const std::vector<size_t>& dims,
     size_t n_dim_excess = dims.size() - n_dim_requested;
     for (size_t i = 1; i <= n_dim_excess; ++i) {
         if (dims[n_dim - i] != 1) {
-            throw std::invalid_argument(format_error_message());
+            throw std::invalid_argument("Failed stripping from back:" + format_error_message());
         }
     }
 
@@ -128,14 +129,12 @@ inspector<T> {
     static constexpr size_t recursive_ndim
     // Is the inner type trivially copyable for optimisation
     // If this value is true: data() is mandatory
-    // If this value is false: getSizeVal, getSize, serialize, unserialize are mandatory
+    // If this value is false: serialize, unserialize are mandatory
     static constexpr bool is_trivially_copyable
 
     // Reading:
     // Allocate the value following dims (should be recursive)
     static void prepare(type& val, const std::vector<std::size_t> dims)
-    // Return the size of the vector pass to/from hdf5 from a vector of dims
-    static size_t getSize(const std::vector<size_t>& dims)
     // Return a pointer of the first value of val (for reading)
     static hdf5_type* data(type& val)
     // Take a serialized vector 'in', some dims and copy value to val (for reading)
@@ -143,12 +142,10 @@ inspector<T> {
 
 
     // Writing:
-    // Return the size of the vector pass to/from hdf5 from a value
-    static size_t getSizeVal(const type& val)
     // Return a point of the first value of val
     static const hdf5_type* data(const type& val)
     // Take a val and serialize it inside 'out'
-    static void serialize(const type& val, hdf5_type* out)
+    static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* out)
     // Return an array of dimensions of the space needed for writing val
     static std::vector<size_t> getDimensions(const type& val)
 }
@@ -170,14 +167,6 @@ struct type_helper {
         return {};
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& /* val */, const std::vector<size_t>& /* dims */) {}
 
     static hdf5_type* data(type& val) {
@@ -190,7 +179,7 @@ struct type_helper {
         return &val;
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
+    static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
         static_assert(is_trivially_copyable, "The type is not trivially copyable");
         *m = val;
     }
@@ -232,7 +221,7 @@ struct inspector<bool>: type_helper<bool> {
         val = vec[0] != 0 ? true : false;
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
+    static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
         *m = val ? 1 : 0;
     }
 };
@@ -250,7 +239,7 @@ struct inspector<std::string>: type_helper<std::string> {
     }
 
     template <class It>
-    static void serialize(const type& val, It m) {
+    static void serialize(const type& val, const std::vector<size_t>& /* dims*/, It m) {
         (*m).assign(val.data(), val.size(), StringPadding::NullTerminated);
     }
 
@@ -275,7 +264,7 @@ struct inspector<Reference>: type_helper<Reference> {
         throw DataSpaceException("A Reference cannot be written directly.");
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
+    static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
         hobj_ref_t ref;
         val.create_ref(&ref);
         *m = ref;
@@ -288,61 +277,6 @@ struct inspector<Reference>: type_helper<Reference> {
     }
 };
 
-template <size_t N>
-struct inspector<deprecated::FixedLenStringArray<N>> {
-    using type = deprecated::FixedLenStringArray<N>;
-    using value_type = char*;
-    using base_type = deprecated::FixedLenStringArray<N>;
-    using hdf5_type = char;
-
-    static constexpr size_t ndim = 1;
-    static constexpr size_t recursive_ndim = ndim;
-    static constexpr bool is_trivially_copyable = false;
-
-    static std::vector<size_t> getDimensions(const type& val) {
-        return std::vector<size_t>{val.size()};
-    }
-
-    static size_t getSizeVal(const type& val) {
-        return N * compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return N * compute_total_size(dims);
-    }
-
-    static void prepare(type& /* val */, const std::vector<size_t>& dims) {
-        if (dims[0] > N) {
-            std::ostringstream os;
-            os << "Size of FixedlenStringArray (" << N << ") is too small for dims (" << dims[0]
-               << ").";
-            throw DataSpaceException(os.str());
-        }
-    }
-
-    static hdf5_type* data(type& val) {
-        return val.data();
-    }
-
-    static const hdf5_type* data(const type& val) {
-        return val.data();
-    }
-
-    static void serialize(const type& val, hdf5_type* m) {
-        for (size_t i = 0; i < val.size(); ++i) {
-            std::memcpy(m + i * N, val[i], N);
-        }
-    }
-
-    static void unserialize(const hdf5_type* vec, const std::vector<size_t>& dims, type& val) {
-        for (size_t i = 0; i < dims[0]; ++i) {
-            std::array<char, N> s;
-            std::memcpy(s.data(), vec + (i * N), N);
-            val.push_back(s);
-        }
-    }
-};
-
 template <typename T>
 struct inspector<std::vector<T>> {
     using type = std::vector<T>;
@@ -368,14 +302,6 @@ struct inspector<std::vector<T>> {
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         val.resize(dims[0]);
         std::vector<size_t> next_dims(dims.begin() + 1, dims.end());
@@ -393,11 +319,12 @@ struct inspector<std::vector<T>> {
     }
 
     template <class It>
-    static void serialize(const type& val, It m) {
+    static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
         if (!val.empty()) {
-            size_t subsize = inspector<value_type>::getSizeVal(val[0]);
+            auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
+            size_t subsize = compute_total_size(subdims);
             for (auto&& e: val) {
-                inspector<value_type>::serialize(e, m);
+                inspector<value_type>::serialize(e, subdims, m);
                 m += subsize;
             }
         }
@@ -429,17 +356,6 @@ struct inspector<std::vector<bool>> {
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return val.size();
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        if (dims.size() > 1) {
-            throw DataSpaceException("std::vector<bool> is only 1 dimension.");
-        }
-        return dims[0];
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         if (dims.size() > 1) {
             throw DataSpaceException("std::vector<bool> is only 1 dimension.");
@@ -455,7 +371,7 @@ struct inspector<std::vector<bool>> {
         throw DataSpaceException("A std::vector<bool> cannot be written directly.");
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
+    static void serialize(const type& val, const std::vector<size_t>& /* dims*/, hdf5_type* m) {
         for (size_t i = 0; i < val.size(); ++i) {
             m[i] = val[i] ? 1 : 0;
         }
@@ -492,14 +408,6 @@ struct inspector<std::array<T, N>> {
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         if (dims[0] > N) {
             std::ostringstream os;
@@ -522,10 +430,11 @@ struct inspector<std::array<T, N>> {
     }
 
     template <class It>
-    static void serialize(const type& val, It m) {
-        size_t subsize = inspector<value_type>::getSizeVal(val[0]);
+    static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
+        auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
+        size_t subsize = compute_total_size(subdims);
         for (auto& e: val) {
-            inspector<value_type>::serialize(e, m);
+            inspector<value_type>::serialize(e, subdims, m);
             m += subsize;
         }
     }
@@ -559,10 +468,6 @@ struct inspector<T*> {
     static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
                                                   inspector<value_type>::is_trivially_copyable;
 
-    static size_t getSizeVal(const type& /* val */) {
-        throw DataSpaceException("Not possible to have size of a T*");
-    }
-
     static std::vector<size_t> getDimensions(const type& /* val */) {
         throw DataSpaceException("Not possible to have size of a T*");
     }
@@ -573,7 +478,9 @@ struct inspector<T*> {
 
     /* it works because there is only T[][][] currently
        we will fix it one day */
-    static void serialize(const type& /* val */, hdf5_type* /* m */) {
+    static void serialize(const type& /* val */,
+                          const std::vector<size_t>& /* dims*/,
+                          hdf5_type* /* m */) {
         throw DataSpaceException("Not possible to serialize a T*");
     }
 };
@@ -606,10 +513,6 @@ struct inspector<T[N]> {
         }
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
     static std::vector<size_t> getDimensions(const type& val) {
         std::vector<size_t> sizes{N};
         if (N > 0) {
@@ -629,21 +532,14 @@ struct inspector<T[N]> {
 
     /* it works because there is only T[][][] currently
        we will fix it one day */
-    static void serialize(const type& val, hdf5_type* m) {
-        size_t subsize = inspector<value_type>::getSizeVal(val[0]);
+    static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
+        auto subdims = std::vector<size_t>(dims.begin() + 1, dims.end());
+        size_t subsize = compute_total_size(subdims);
         for (size_t i = 0; i < N; ++i) {
-            inspector<value_type>::serialize(val[i], m + i * subsize);
+            inspector<value_type>::serialize(val[i], subdims, m + i * subsize);
         }
     }
 };
 
 }  // namespace details
 }  // namespace HighFive
-
-#ifdef H5_USE_BOOST
-#include <highfive/boost.hpp>
-#endif
-
-#ifdef H5_USE_EIGEN
-#include <highfive/eigen.hpp>
-#endif
diff --git a/packages/HighFive/include/highfive/bits/H5Node_traits.hpp b/packages/HighFive/include/highfive/bits/H5Node_traits.hpp
index 6f4a93ce6a963d6d3d4fb9e1f1c65fa57380dc12..56d9f8d3aba2c7b74a2ad4d115048dbddc0da0a1 100644
--- a/packages/HighFive/include/highfive/bits/H5Node_traits.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Node_traits.hpp
@@ -78,14 +78,6 @@ class NodeTraits {
                           bool parents = true);
 
 
-    template <std::size_t N>
-    H5_DEPRECATED("Use 'std::vector<std::string>'.")
-    DataSet createDataSet(const std::string& dataset_name,
-                          const deprecated::FixedLenStringArray<N>& data,
-                          const DataSetCreateProps& createProps = DataSetCreateProps::Default(),
-                          const DataSetAccessProps& accessProps = DataSetAccessProps::Default(),
-                          bool parents = true);
-
     ///
     /// \brief get an existing dataset in the current file
     /// \param dataset_name
diff --git a/packages/HighFive/include/highfive/bits/H5Node_traits_misc.hpp b/packages/HighFive/include/highfive/bits/H5Node_traits_misc.hpp
index a98600598ad7647598633378456230706ff99a5a..49cfc639db3a80807ba55d05f91c05cc54d56884 100644
--- a/packages/HighFive/include/highfive/bits/H5Node_traits_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Node_traits_misc.hpp
@@ -80,19 +80,6 @@ inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_na
     return ds;
 }
 
-template <typename Derivate>
-template <std::size_t N>
-inline DataSet NodeTraits<Derivate>::createDataSet(const std::string& dataset_name,
-                                                   const deprecated::FixedLenStringArray<N>& data,
-                                                   const DataSetCreateProps& createProps,
-                                                   const DataSetAccessProps& accessProps,
-                                                   bool parents) {
-    DataSet ds = createDataSet<char[N]>(
-        dataset_name, DataSpace(data.size()), createProps, accessProps, parents);
-    ds.write(data);
-    return ds;
-}
-
 template <typename Derivate>
 inline DataSet NodeTraits<Derivate>::getDataSet(const std::string& dataset_name,
                                                 const DataSetAccessProps& accessProps) const {
diff --git a/packages/HighFive/include/highfive/bits/H5Path_traits.hpp b/packages/HighFive/include/highfive/bits/H5Path_traits.hpp
index 46a038c4ffa1f3a9e91ae617fb634b0b668a8c09..a58f96187451f023565a7e12ccc028a9eccf9471 100644
--- a/packages/HighFive/include/highfive/bits/H5Path_traits.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Path_traits.hpp
@@ -25,8 +25,7 @@ class PathTraits {
     ///
     /// \brief Return a reference to the File object this object belongs
     /// \return the File object ref
-    File& getFile() const noexcept;
-
+    File& getFile() const;
 
   protected:
     std::shared_ptr<File> _file_obj;  // keep a ref to file so we keep its ref count > 0
diff --git a/packages/HighFive/include/highfive/bits/H5Path_traits_misc.hpp b/packages/HighFive/include/highfive/bits/H5Path_traits_misc.hpp
index acde06d1ee9061e0701f14af3ac6a8297f8b4df6..0893599c62f8406a29dea691b3a971c7cf404408 100644
--- a/packages/HighFive/include/highfive/bits/H5Path_traits_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Path_traits_misc.hpp
@@ -35,7 +35,11 @@ inline std::string PathTraits<Derivate>::getPath() const {
 }
 
 template <typename Derivate>
-inline File& PathTraits<Derivate>::getFile() const noexcept {
+inline File& PathTraits<Derivate>::getFile() const {
+    const auto& obj = static_cast<const Derivate&>(*this);
+    if (!obj.isValid()) {
+        throw ObjectException("Invalid call to `PathTraits::getFile` for invalid object");
+    }
     return *_file_obj;
 }
 
diff --git a/packages/HighFive/include/highfive/bits/H5Slice_traits.hpp b/packages/HighFive/include/highfive/bits/H5Slice_traits.hpp
index c753026c3d20a68cb8c3442c4e32ba69951e053f..fd8c31d2704232fb6118913f647c81c56e9fb371 100644
--- a/packages/HighFive/include/highfive/bits/H5Slice_traits.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Slice_traits.hpp
@@ -292,6 +292,7 @@ class SliceTraits {
 
     ///
     /// Read the entire dataset into a buffer
+    ///
     /// An exception is raised is if the numbers of dimension of the buffer and
     /// of the dataset are different.
     ///
@@ -312,9 +313,9 @@ class SliceTraits {
     /// \param dtype: The type of the data, in case it cannot be automatically guessed
     /// \param xfer_props: Data Transfer properties
     template <typename T>
-    void read(T* array,
-              const DataType& dtype,
-              const DataTransferProps& xfer_props = DataTransferProps()) const;
+    void read_raw(T* array,
+                  const DataType& dtype,
+                  const DataTransferProps& xfer_props = DataTransferProps()) const;
 
     ///
     /// Read the entire dataset into a raw buffer
@@ -326,7 +327,8 @@ class SliceTraits {
     /// \param array: A buffer containing enough space for the data
     /// \param xfer_props: Data Transfer properties
     template <typename T>
-    void read(T* array, const DataTransferProps& xfer_props = DataTransferProps()) const;
+    void read_raw(T* array, const DataTransferProps& xfer_props = DataTransferProps()) const;
+
 
     ///
     /// Write the integrality N-dimension buffer to this dataset
diff --git a/packages/HighFive/include/highfive/bits/H5Slice_traits_misc.hpp b/packages/HighFive/include/highfive/bits/H5Slice_traits_misc.hpp
index dd7e45b1d4682c3da46274695fb477bfceca4bfd..2ae6640b051df2a4a45f8cdfa47347a61055c5ec 100644
--- a/packages/HighFive/include/highfive/bits/H5Slice_traits_misc.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Slice_traits_misc.hpp
@@ -186,7 +186,7 @@ inline void SliceTraits<Derivate>::read(T& array, const DataTransferProps& xfer_
     auto dims = mem_space.getDimensions();
 
     auto r = details::data_converter::get_reader<T>(dims, array, file_datatype);
-    read(r.getPointer(), buffer_info.data_type, xfer_props);
+    read_raw(r.getPointer(), buffer_info.data_type, xfer_props);
     // re-arrange results
     r.unserialize(array);
 
@@ -210,9 +210,9 @@ inline void SliceTraits<Derivate>::read(T& array, const DataTransferProps& xfer_
 
 template <typename Derivate>
 template <typename T>
-inline void SliceTraits<Derivate>::read(T* array,
-                                        const DataType& mem_datatype,
-                                        const DataTransferProps& xfer_props) const {
+inline void SliceTraits<Derivate>::read_raw(T* array,
+                                            const DataType& mem_datatype,
+                                            const DataTransferProps& xfer_props) const {
     static_assert(!std::is_const<T>::value,
                   "read() requires a non-const structure to read data into");
 
@@ -226,13 +226,14 @@ inline void SliceTraits<Derivate>::read(T* array,
                      static_cast<void*>(array));
 }
 
+
 template <typename Derivate>
 template <typename T>
-inline void SliceTraits<Derivate>::read(T* array, const DataTransferProps& xfer_props) const {
+inline void SliceTraits<Derivate>::read_raw(T* array, const DataTransferProps& xfer_props) const {
     using element_type = typename details::inspector<T>::base_type;
     const DataType& mem_datatype = create_and_check_datatype<element_type>();
 
-    read(array, mem_datatype, xfer_props);
+    read_raw(array, mem_datatype, xfer_props);
 }
 
 
@@ -241,6 +242,7 @@ template <typename T>
 inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProps& xfer_props) {
     const auto& slice = static_cast<const Derivate&>(*this);
     const DataSpace& mem_space = slice.getMemSpace();
+    auto dims = mem_space.getDimensions();
 
     auto file_datatype = slice.getDataType();
 
@@ -256,7 +258,7 @@ inline void SliceTraits<Derivate>::write(const T& buffer, const DataTransferProp
            << " into dataset with n = " << buffer_info.n_dimensions << " dimensions.";
         throw DataSpaceException(ss.str());
     }
-    auto w = details::data_converter::serialize<T>(buffer, file_datatype);
+    auto w = details::data_converter::serialize<T>(buffer, dims, file_datatype);
     write_raw(w.getPointer(), buffer_info.data_type, xfer_props);
 }
 
@@ -276,6 +278,7 @@ inline void SliceTraits<Derivate>::write_raw(const T* buffer,
                       static_cast<const void*>(buffer));
 }
 
+
 template <typename Derivate>
 template <typename T>
 inline void SliceTraits<Derivate>::write_raw(const T* buffer, const DataTransferProps& xfer_props) {
diff --git a/packages/HighFive/include/highfive/bits/H5Utils.hpp b/packages/HighFive/include/highfive/bits/H5Utils.hpp
index b3f039e20d29377269a12cfe6126df7bb3027ed6..c005bd22bd5f84c3221bb7dea1ed04a22ed7e913 100644
--- a/packages/HighFive/include/highfive/bits/H5Utils.hpp
+++ b/packages/HighFive/include/highfive/bits/H5Utils.hpp
@@ -25,12 +25,6 @@
 
 namespace HighFive {
 
-namespace deprecated {
-// If ever used, recognize dimensions of FixedLenStringArray
-template <std::size_t N>
-class FixedLenStringArray;
-}  // namespace deprecated
-
 namespace details {
 // converter function for hsize_t -> size_t when hsize_t != size_t
 template <typename Size>
diff --git a/packages/HighFive/include/highfive/bits/H5_definitions.hpp b/packages/HighFive/include/highfive/bits/H5_definitions.hpp
index ad4b95af2a9af52f92e14196eff5247c848ab96e..56993c855e6cfe0a57d656725ce7d590c1576c6e 100644
--- a/packages/HighFive/include/highfive/bits/H5_definitions.hpp
+++ b/packages/HighFive/include/highfive/bits/H5_definitions.hpp
@@ -45,11 +45,6 @@ class AtomicType;
 template <typename Derivate>
 class AnnotateTraits;
 
-namespace deprecated {
-template <std::size_t N>
-class FixedLenStringArray;
-}
-
 template <typename Derivate>
 class NodeTraits;
 
diff --git a/packages/HighFive/include/highfive/boost.hpp b/packages/HighFive/include/highfive/boost.hpp
index 8992159a2df1fca5a4bcbefaed2fd5e3dfcf5b2e..fb8a709c512d6e5c46aad7edac6f4d48f2f06d26 100644
--- a/packages/HighFive/include/highfive/boost.hpp
+++ b/packages/HighFive/include/highfive/boost.hpp
@@ -1,12 +1,9 @@
 #pragma once
-#ifdef H5_USE_BOOST
 
 #include "bits/H5Inspector_decl.hpp"
 #include "H5Exception.hpp"
 
 #include <boost/multi_array.hpp>
-// starting Boost 1.64, serialization header must come before ublas
-#include <boost/serialization/vector.hpp>
 #include <boost/numeric/ublas/matrix.hpp>
 
 namespace HighFive {
@@ -34,14 +31,6 @@ struct inspector<boost::multi_array<T, Dims>> {
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         if (dims.size() < ndim) {
             std::ostringstream os;
@@ -71,11 +60,12 @@ struct inspector<boost::multi_array<T, Dims>> {
     }
 
     template <class It>
-    static void serialize(const type& val, It m) {
+    static void serialize(const type& val, const std::vector<size_t>& dims, It m) {
         size_t size = val.num_elements();
-        size_t subsize = inspector<value_type>::getSizeVal(*val.origin());
+        auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
+        size_t subsize = compute_total_size(subdims);
         for (size_t i = 0; i < size; ++i) {
-            inspector<value_type>::serialize(*(val.origin() + i), m + i * subsize);
+            inspector<value_type>::serialize(*(val.origin() + i), subdims, m + i * subsize);
         }
     }
 
@@ -110,14 +100,6 @@ struct inspector<boost::numeric::ublas::matrix<T>> {
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         if (dims.size() < ndim) {
             std::ostringstream os;
@@ -136,11 +118,12 @@ struct inspector<boost::numeric::ublas::matrix<T>> {
         return inspector<value_type>::data(val(0, 0));
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
+    static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
         size_t size = val.size1() * val.size2();
-        size_t subsize = inspector<value_type>::getSizeVal(val(0, 0));
+        auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
+        size_t subsize = compute_total_size(subdims);
         for (size_t i = 0; i < size; ++i) {
-            inspector<value_type>::serialize(*(&val(0, 0) + i), m + i * subsize);
+            inspector<value_type>::serialize(*(&val(0, 0) + i), subdims, m + i * subsize);
         }
     }
 
@@ -160,5 +143,3 @@ struct inspector<boost::numeric::ublas::matrix<T>> {
 
 }  // namespace details
 }  // namespace HighFive
-
-#endif
diff --git a/packages/HighFive/include/highfive/eigen.hpp b/packages/HighFive/include/highfive/eigen.hpp
index c47095ddeeea3698ae76366d7c72fb443450241d..aaad280effe45955afdd3b38a6f98a029a24a61a 100644
--- a/packages/HighFive/include/highfive/eigen.hpp
+++ b/packages/HighFive/include/highfive/eigen.hpp
@@ -1,93 +1,153 @@
 #pragma once
-#ifdef H5_USE_EIGEN
 
 #include "bits/H5Inspector_decl.hpp"
 #include "H5Exception.hpp"
 
-#include <Eigen/Eigen>
-
+#include <Eigen/Core>
+#include <Eigen/Dense>
 
 namespace HighFive {
 namespace details {
 
-template <typename T, int M, int N>
-struct inspector<Eigen::Matrix<T, M, N>> {
-    using type = Eigen::Matrix<T, M, N>;
-    using value_type = T;
+template <class EigenType>
+struct eigen_inspector {
+    using type = EigenType;
+    using value_type = typename EigenType::Scalar;
     using base_type = typename inspector<value_type>::base_type;
     using hdf5_type = base_type;
 
+    static_assert(int(EigenType::ColsAtCompileTime) == int(EigenType::MaxColsAtCompileTime),
+                  "Padding isn't supported.");
+    static_assert(int(EigenType::RowsAtCompileTime) == int(EigenType::MaxRowsAtCompileTime),
+                  "Padding isn't supported.");
+
+    static constexpr bool is_row_major() {
+        return EigenType::ColsAtCompileTime == 1 || EigenType::RowsAtCompileTime == 1 ||
+               EigenType::IsRowMajor;
+    }
+
     static constexpr size_t ndim = 2;
     static constexpr size_t recursive_ndim = ndim + inspector<value_type>::recursive_ndim;
-    static constexpr bool is_trivially_copyable = std::is_trivially_copyable<value_type>::value &&
+    static constexpr bool is_trivially_copyable = is_row_major() &&
+                                                  std::is_trivially_copyable<value_type>::value &&
                                                   inspector<value_type>::is_trivially_copyable;
 
-
-    static void assert_not_buggy(Eigen::Index nrows, Eigen::Index ncols) {
-        if (nrows > 1 && ncols > 1) {
-            throw std::runtime_error(
-                "HighFive has been broken for Eigen::Matrix. Please check "
-                "https://github.com/BlueBrain/HighFive/issues/532.");
-        }
-    }
-
     static std::vector<size_t> getDimensions(const type& val) {
-        assert_not_buggy(val.rows(), val.cols());
-
         std::vector<size_t> sizes{static_cast<size_t>(val.rows()), static_cast<size_t>(val.cols())};
         auto s = inspector<value_type>::getDimensions(val.data()[0]);
         sizes.insert(sizes.end(), s.begin(), s.end());
         return sizes;
     }
 
-    static size_t getSizeVal(const type& val) {
-        return compute_total_size(getDimensions(val));
-    }
-
-    static size_t getSize(const std::vector<size_t>& dims) {
-        return compute_total_size(dims);
-    }
-
     static void prepare(type& val, const std::vector<size_t>& dims) {
         if (dims[0] != static_cast<size_t>(val.rows()) ||
             dims[1] != static_cast<size_t>(val.cols())) {
             val.resize(static_cast<typename type::Index>(dims[0]),
                        static_cast<typename type::Index>(dims[1]));
         }
-
-        assert_not_buggy(val.rows(), val.cols());
     }
 
     static hdf5_type* data(type& val) {
-        assert_not_buggy(val.rows(), val.cols());
+        if (!is_trivially_copyable) {
+            throw DataSetException("Invalid used of `inspector<Eigen::Matrix<...>>::data`.");
+        }
+
         return inspector<value_type>::data(*val.data());
     }
 
     static const hdf5_type* data(const type& val) {
-        assert_not_buggy(val.rows(), val.cols());
+        if (!is_trivially_copyable) {
+            throw DataSetException("Invalid used of `inspector<Eigen::Matrix<...>>::data`.");
+        }
+
         return inspector<value_type>::data(*val.data());
     }
 
-    static void serialize(const type& val, hdf5_type* m) {
-        assert_not_buggy(val.rows(), val.cols());
-        std::memcpy(m, val.data(), static_cast<size_t>(val.size()) * sizeof(hdf5_type));
+    static void serialize(const type& val, const std::vector<size_t>& dims, hdf5_type* m) {
+        Eigen::Index n_rows = val.rows();
+        Eigen::Index n_cols = val.cols();
+
+        auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
+        auto subsize = compute_total_size(subdims);
+        for (Eigen::Index i = 0; i < n_rows; ++i) {
+            for (Eigen::Index j = 0; j < n_cols; ++j) {
+                inspector<value_type>::serialize(val(i, j), dims, m);
+                m += subsize;
+            }
+        }
     }
 
     static void unserialize(const hdf5_type* vec_align,
                             const std::vector<size_t>& dims,
                             type& val) {
-        assert_not_buggy(val.rows(), val.cols());
         if (dims.size() < 2) {
             std::ostringstream os;
             os << "Impossible to pair DataSet with " << dims.size()
                << " dimensions into an eigen-matrix.";
             throw DataSpaceException(os.str());
         }
-        std::memcpy(val.data(), vec_align, compute_total_size(dims) * sizeof(hdf5_type));
+
+        auto n_rows = static_cast<Eigen::Index>(dims[0]);
+        auto n_cols = static_cast<Eigen::Index>(dims[1]);
+
+        auto subdims = std::vector<size_t>(dims.begin() + ndim, dims.end());
+        auto subsize = compute_total_size(subdims);
+        for (Eigen::Index i = 0; i < n_rows; ++i) {
+            for (Eigen::Index j = 0; j < n_cols; ++j) {
+                inspector<value_type>::unserialize(vec_align, subdims, val(i, j));
+                vec_align += subsize;
+            }
+        }
     }
 };
 
+template <typename T, int M, int N, int Options>
+struct inspector<Eigen::Matrix<T, M, N, Options>>
+    : public eigen_inspector<Eigen::Matrix<T, M, N, Options>> {
+  private:
+    using super = eigen_inspector<Eigen::Matrix<T, M, N, Options>>;
+
+  public:
+    using type = typename super::type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+    using hdf5_type = typename super::hdf5_type;
+};
+
+template <typename T, int M, int N, int Options>
+struct inspector<Eigen::Array<T, M, N, Options>>
+    : public eigen_inspector<Eigen::Array<T, M, N, Options>> {
+  private:
+    using super = eigen_inspector<Eigen::Array<T, M, N, Options>>;
+
+  public:
+    using type = typename super::type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+    using hdf5_type = typename super::hdf5_type;
+};
+
+
+template <typename PlainObjectType, int MapOptions>
+struct inspector<Eigen::Map<PlainObjectType, MapOptions>>
+    : public eigen_inspector<Eigen::Map<PlainObjectType, MapOptions>> {
+  private:
+    using super = eigen_inspector<Eigen::Map<PlainObjectType, MapOptions>>;
+
+  public:
+    using type = typename super::type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+    using hdf5_type = typename super::hdf5_type;
+
+    static void prepare(type& val, const std::vector<size_t>& dims) {
+        if (dims[0] != static_cast<size_t>(val.rows()) ||
+            dims[1] != static_cast<size_t>(val.cols())) {
+            throw DataSetException("Eigen::Map has invalid shape and can't be resized.");
+        }
+    }
+};
+
+
 }  // namespace details
 }  // namespace HighFive
-
-#endif
diff --git a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_Eigen.hpp b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_Eigen.hpp
index 5b5d3b9a5f45e72e832eba821e3ab993b2997250..a2e23bc0fa7c3ed5fdf3f09988127d0cc66ca281 100644
--- a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_Eigen.hpp
+++ b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_Eigen.hpp
@@ -98,7 +98,7 @@ struct io_impl<T, typename std::enable_if<std::is_base_of<Eigen::DenseBase<T>, T
         DataSet dataset = file.getDataSet(path);
         std::vector<typename T::Index> dims = shape(file, path, dataset, T::RowsAtCompileTime);
         T data(dims[0], dims[1]);
-        dataset.read(data.data());
+        dataset.read_raw(data.data());
         if (data.IsVectorAtCompileTime || data.IsRowMajor) {
             return data;
         }
@@ -130,7 +130,7 @@ struct io_impl<T, typename std::enable_if<std::is_base_of<Eigen::DenseBase<T>, T
         DataSpace dataspace = attribute.getSpace();
         std::vector<typename T::Index> dims = shape(file, path, dataspace, T::RowsAtCompileTime);
         T data(dims[0], dims[1]);
-        attribute.read(data.data());
+        attribute.read_raw(data.data());
         if (data.IsVectorAtCompileTime || data.IsRowMajor) {
             return data;
         }
diff --git a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_opencv.hpp b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_opencv.hpp
index b640cd854362f3bb55af6edf26888d466a2f27ce..7be19f1e35484def4a378d7b0e188b3aa40dbedc 100644
--- a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_opencv.hpp
+++ b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_opencv.hpp
@@ -61,7 +61,7 @@ struct io_impl<T, typename std::enable_if<is_opencv<T>::value>::type> {
         DataSet dataset = file.getDataSet(path);
         std::vector<int> dims = shape(file, path, dataset.getDimensions());
         T data(dims[0], dims[1]);
-        dataset.read(reinterpret_cast<value_type*>(data.data));
+        dataset.read_raw(reinterpret_cast<value_type*>(data.data));
         return data;
     }
 
@@ -89,7 +89,7 @@ struct io_impl<T, typename std::enable_if<is_opencv<T>::value>::type> {
         DataSpace dataspace = attribute.getSpace();
         std::vector<int> dims = shape(file, path, dataspace.getDimensions());
         T data(dims[0], dims[1]);
-        attribute.read(reinterpret_cast<value_type*>(data.data));
+        attribute.read_raw(reinterpret_cast<value_type*>(data.data));
         return data;
     }
 };
diff --git a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_xtensor.hpp b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_xtensor.hpp
index 6b0238c4db86c2aa8b2a492825d7b4bc54a3b5d2..9b737f03bd190a33428078452c3876142926a2cc 100644
--- a/packages/HighFive/include/highfive/h5easy_bits/H5Easy_xtensor.hpp
+++ b/packages/HighFive/include/highfive/h5easy_bits/H5Easy_xtensor.hpp
@@ -44,7 +44,7 @@ struct io_impl<T, typename std::enable_if<xt::is_xexpression<T>::value>::type> {
         DataSet dataset = file.getDataSet(path);
         std::vector<size_t> dims = dataset.getDimensions();
         T data = T::from_shape(dims);
-        dataset.read(data.data());
+        dataset.read_raw(data.data());
         return data;
     }
 
@@ -73,7 +73,7 @@ struct io_impl<T, typename std::enable_if<xt::is_xexpression<T>::value>::type> {
         DataSpace dataspace = attribute.getSpace();
         std::vector<size_t> dims = dataspace.getDimensions();
         T data = T::from_shape(dims);
-        attribute.read(data.data());
+        attribute.read_raw(data.data());
         return data;
     }
 };
diff --git a/packages/HighFive/include/highfive/half_float.hpp b/packages/HighFive/include/highfive/half_float.hpp
index 998e693ffe37c15b8ebba08f83f13c521f46423b..dc2464c225398fb23ff241021dec25a7144f2392 100644
--- a/packages/HighFive/include/highfive/half_float.hpp
+++ b/packages/HighFive/include/highfive/half_float.hpp
@@ -1,5 +1,4 @@
 #pragma once
-#ifdef H5_USE_HALF_FLOAT
 
 #include <half.hpp>
 
@@ -16,6 +15,5 @@ inline AtomicType<float16_t>::AtomicType() {
     // Floating point exponent bias
     detail::h5t_set_ebias(_hid, 15);
 }
-}  // namespace HighFive
 
-#endif
+}  // namespace HighFive
diff --git a/packages/HighFive/include/highfive/highfive.hpp b/packages/HighFive/include/highfive/highfive.hpp
index f5e20cae9131ae7e6440f6fa7f16bc8b3430b336..543fe80bcfda4519fe33c8ac31bbf9ff65029fc3 100644
--- a/packages/HighFive/include/highfive/highfive.hpp
+++ b/packages/HighFive/include/highfive/highfive.hpp
@@ -5,7 +5,6 @@
 #include <highfive/H5DataSpace.hpp>
 #include <highfive/H5DataType.hpp>
 #include <highfive/H5File.hpp>
-#include <highfive/H5FileDriver.hpp>
 #include <highfive/H5Group.hpp>
 #include <highfive/H5PropertyList.hpp>
 #include <highfive/H5Reference.hpp>
diff --git a/packages/HighFive/src/examples/CMakeLists.txt b/packages/HighFive/src/examples/CMakeLists.txt
index 8b5f8b0affb8f68478582b66ac4c8ba01c0bb6d3..5a1384557d2809163af2d2958d1d3737870d8fc3 100644
--- a/packages/HighFive/src/examples/CMakeLists.txt
+++ b/packages/HighFive/src/examples/CMakeLists.txt
@@ -1,51 +1,102 @@
-include(HighFiveWarnings)
+set(core_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/compound_types.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_attribute_string_integer.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_dataset_double.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_datatype.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_extensible_dataset.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_large_attribute.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_page_allocated_files.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/readme_snippet.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_dataset_string.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_raw_ptr.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_single_scalar.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_std_strings.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_vector_dataset.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/read_write_vector_dataset_references.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/renaming_objects.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/select_by_id_dataset_cpp11.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/select_partial_dataset_cpp11.cpp
+)
 
-function(compile_example example_source)
+set(easy_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/easy_attribute.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/easy_dumpoptions.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/easy_load_dump.cpp
+)
+
+set(boost_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/boost_multi_array_2D.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/boost_multiarray_complex.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/boost_ublas_double.cpp
+)
+
+set(eigen_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/eigen_matrix.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/eigen_vector.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/eigen_map.cpp
+)
+
+set(hl_hdf5_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/hl_hdf5_inmemory_files.cpp
+)
 
-    get_filename_component(example_filename ${example_source} NAME)
-    string(REPLACE ".cpp" "_bin" example_name ${example_filename})
-
-    if(${example_filename} MATCHES ".*eigen.*")
-        if(NOT HIGHFIVE_USE_EIGEN)
-            return()
-        endif()
-    endif()
-
-    if(${example_filename} MATCHES ".*boost.*")
-        if(NOT HIGHFIVE_USE_BOOST)
-            return()
-        endif()
-    endif()
-
-    if(${example_filename} MATCHES ".*parallel_hdf5.*")
-        if(NOT HIGHFIVE_PARALLEL_HDF5)
-            return()
-        endif()
-    endif()
-
-    if(${example_filename} MATCHES ".*half_float.*")
-        if(NOT HIGHFIVE_USE_HALF_FLOAT)
-            return()
-        endif()
-    endif()
-
-    if(${example_name} MATCHES ".*hl_hdf5.*")
-        find_package(HDF5 QUIET COMPONENTS HL NAMES HDF5_HL)
-        if(${HDF5_HL_FOUND})
-            message("HDF5 HL: ${HDF5_HL_LIBRARIES}")
-            add_executable(${example_name} ${example_source})
-            target_link_libraries(${example_name} HighFive HighFiveWarnings ${HDF5_HL_LIBRARIES})
-        endif()
-        return()
-    endif()
-
-    add_executable(${example_name} ${example_source})
-    target_link_libraries(${example_name} HighFive HighFiveWarnings)
+set(parallel_hdf5_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/parallel_hdf5_collective_io.cpp
+  ${CMAKE_CURRENT_SOURCE_DIR}/parallel_hdf5_independent_io.cpp
+)
 
+set(half_float_examples
+  ${CMAKE_CURRENT_SOURCE_DIR}/create_dataset_half_float.cpp
+)
+
+function(compile_example example_source)
+  get_filename_component(example_filename ${example_source} NAME)
+  string(REPLACE ".cpp" "_bin" example_name ${example_filename})
+  message("example_name: ${example_name}")
+
+  add_executable(${example_name} ${example_source})
+  target_link_libraries(${example_name} PUBLIC HighFive HighFiveWarnings HighFiveFlags)
+  if(${ARGC} EQUAL 2)
+    target_link_libraries(${example_name} PUBLIC ${ARGV1})
+  endif()
 endfunction()
 
-file(GLOB list_example "*.cpp")
 
-foreach(example_src ${list_example})
-    compile_example(${example_src})
+foreach(example_source ${core_examples})
+  compile_example(${example_source})
 endforeach()
+
+foreach(example_source ${easy_examples})
+  compile_example(${example_source})
+endforeach()
+
+if(HIGHFIVE_TEST_BOOST)
+  foreach(example_source ${boost_examples})
+    compile_example(${example_source} HighFiveBoostDependency)
+  endforeach()
+endif()
+
+if(HIGHFIVE_TEST_EIGEN)
+  foreach(example_source ${eigen_examples})
+    compile_example(${example_source} HighFiveEigenDependency)
+  endforeach()
+endif()
+
+if(HDF5_IS_PARALLEL)
+  foreach(example_source ${parallel_hdf5_examples})
+    compile_example(${example_source})
+  endforeach()
+endif()
+
+add_library(HighFiveHlHdf5Dependency INTERFACE)
+find_package(HDF5 QUIET COMPONENTS HL NAMES HDF5_HL)
+if(${HDF5_HL_FOUND})
+    message("HDF5 HL: ${HDF5_HL_LIBRARIES}")
+    target_link_libraries(HighFiveHlHdf5Dependency ${HDF5_HL_LIBRARIES})
+
+    foreach(example_source ${hl_hdf5_examples})
+      compile_examples(${example_source} HighFiveHlHdf5Dependency)
+    endforeach()
+endif()
+
+# TODO Half-float examples
diff --git a/packages/HighFive/src/examples/boost_multi_array_2D.cpp b/packages/HighFive/src/examples/boost_multi_array_2D.cpp
index 4bec1ec12991391a58549e8fb044294523f4a74b..508c3a880f7d8deb1b571b87fc397580263c73d3 100644
--- a/packages/HighFive/src/examples/boost_multi_array_2D.cpp
+++ b/packages/HighFive/src/examples/boost_multi_array_2D.cpp
@@ -8,11 +8,9 @@
  */
 #include <iostream>
 
-#undef H5_USE_BOOST
-#define H5_USE_BOOST
-
 #include <boost/multi_array.hpp>
 #include <highfive/highfive.hpp>
+#include <highfive/boost.hpp>
 
 using namespace HighFive;
 
diff --git a/packages/HighFive/src/examples/boost_multiarray_complex.cpp b/packages/HighFive/src/examples/boost_multiarray_complex.cpp
index 37481db625b5b21d7d13c0ae7da4223c9d7eb327..34f18f55191fadcc81a8d226fc3805a0bac63e43 100644
--- a/packages/HighFive/src/examples/boost_multiarray_complex.cpp
+++ b/packages/HighFive/src/examples/boost_multiarray_complex.cpp
@@ -9,12 +9,9 @@
 #include <algorithm>
 #include <complex>
 
-#undef H5_USE_BOOST
-#define H5_USE_BOOST
-
 #include <highfive/highfive.hpp>
 
-#include <boost/multi_array.hpp>
+#include <highfive/boost.hpp>
 
 typedef std::complex<double> complex_t;
 
diff --git a/packages/HighFive/src/examples/boost_ublas_double.cpp b/packages/HighFive/src/examples/boost_ublas_double.cpp
index b025475b9584b2f27c6dbfcd51e3ee402898031a..3889df6807eb58a18132fd3bdc429dbb2786221b 100644
--- a/packages/HighFive/src/examples/boost_ublas_double.cpp
+++ b/packages/HighFive/src/examples/boost_ublas_double.cpp
@@ -8,11 +8,10 @@
  */
 #include <iostream>
 
-#undef H5_USE_BOOST
-#define H5_USE_BOOST
-
 #include <highfive/highfive.hpp>
 
+#include <highfive/boost.hpp>
+
 // In some versions of Boost (starting with 1.64), you have to include the serialization header
 // before ublas
 #include <boost/serialization/vector.hpp>
diff --git a/packages/HighFive/src/examples/create_dataset_half_float.cpp b/packages/HighFive/src/examples/create_dataset_half_float.cpp
index 837c58704c5d4e4d7a030bd3d784286004ca1030..01577669982c67fbf4e3ebee42203de0dcb2bebb 100644
--- a/packages/HighFive/src/examples/create_dataset_half_float.cpp
+++ b/packages/HighFive/src/examples/create_dataset_half_float.cpp
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include <highfive/highfive.hpp>
+#include <highfive/half_float.hpp>
 
 const std::string FILE_NAME("create_dataset_half_float_example.h5");
 const std::string DATASET_NAME("dset");
diff --git a/packages/HighFive/src/examples/eigen_map.cpp b/packages/HighFive/src/examples/eigen_map.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7cdd15cd460e6cfaf5935bcdf589c14007ba0eb8
--- /dev/null
+++ b/packages/HighFive/src/examples/eigen_map.cpp
@@ -0,0 +1,48 @@
+#include <highfive/highfive.hpp>
+#include <highfive/eigen.hpp>
+
+// Example showing reading and writing of `Eigen::Map`. Using
+// `Map<Matrix, ...>` as an example, but `Map<Array, ...>` works
+// analogously.
+//
+// Both `Eigen::Matrix` and `Eigen::Vector` have their own examples.
+
+int main() {
+    HighFive::File file("eigen_map.h5", HighFive::File::Truncate);
+
+    // Somehow allocate some memory:
+    double* p1 = (double*) malloc(4 * 3 * sizeof(double));
+
+    Eigen::Map<Eigen::MatrixXd> A(p1, 4, 3);
+
+    // clang-format off
+    A <<  1,  2,  3,
+          4,  5,  6,
+          7,  8,  9,
+         10, 11, 12;
+    // clang-format on
+    std::cout << "A = \n" << A << "\n\n";
+
+    // Write it to the file:
+    file.createDataSet("mat", A);
+
+    // ... and read it back as fixed-size and row-major:
+    using Matrix43d = Eigen::Matrix<double, 4, 3, Eigen::RowMajor>;
+
+    // Again, memory was obtain somehow, and we create an `Eigen::Map`
+    // from it:
+    double* p2 = (double*) malloc(4 * 3 * sizeof(double));
+    Eigen::Map<Matrix43d> B(p2, 4, 3);
+
+    // Since, we've pre-allocated the memory, we use the overload of `read`
+    // accepts `B` and an argument. Note, this will throw if `B` needs to be
+    // resized, because a map shouldn't resize the underlying memory:
+    file.getDataSet("mat").read(B);
+
+    std::cout << "B = \n" << B << "\n";
+
+    free(p1);
+    free(p2);
+
+    return 0;
+}
diff --git a/packages/HighFive/src/examples/eigen_matrix.cpp b/packages/HighFive/src/examples/eigen_matrix.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7a40445d7da4579bda0c5787d3f1966c133d4e65
--- /dev/null
+++ b/packages/HighFive/src/examples/eigen_matrix.cpp
@@ -0,0 +1,33 @@
+#include <highfive/highfive.hpp>
+#include <highfive/eigen.hpp>
+
+// Example showing reading and writing of `Eigen::Matrix`. Using
+// `Eigen::Matrix` as an example, but `Eigen::Array` works analogously.
+//
+// Both `Eigen::Vector` and `Eigen::Map` have their own examples.
+
+int main() {
+    HighFive::File file("eigen_matrix.h5", HighFive::File::Truncate);
+
+    // Create a matrix.
+    Eigen::MatrixXd A(4, 3);
+    // clang-format off
+    A <<  1,  2,  3,
+          4,  5,  6,
+          7,  8,  9,
+         10, 11, 12;
+    // clang-format on
+    //
+    std::cout << "A = \n" << A << "\n\n";
+
+    // Write it to the file:
+    file.createDataSet("mat", A);
+
+    // ... and read it back as fixed-size and row-major:
+    using Matrix43d = Eigen::Matrix<double, 4, 3, Eigen::RowMajor>;
+    auto B = file.getDataSet("mat").read<Matrix43d>();
+
+    std::cout << "B = \n" << B << "\n";
+
+    return 0;
+}
diff --git a/packages/HighFive/src/examples/eigen_vector.cpp b/packages/HighFive/src/examples/eigen_vector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..aa4772ce78c7b218c0c6b244f6b435e92b1f7a8c
--- /dev/null
+++ b/packages/HighFive/src/examples/eigen_vector.cpp
@@ -0,0 +1,33 @@
+#include <highfive/highfive.hpp>
+#include <highfive/eigen.hpp>
+
+// Example showing reading and writing of `Eigen::Matrix`. Using
+// `Eigen::Matrix` as an example, but `Eigen::Array` works analogously.
+//
+// Both `Eigen::Vector` and `Eigen::Map` have their own examples.
+
+int main() {
+    HighFive::File file("eigen_vector.h5", HighFive::File::Truncate);
+
+    // Create a matrix.
+    Eigen::VectorXd v(3);
+    v << 1, 2, 3;
+    std::cout << "v = \n" << v << "\n\n";
+
+    // Write it to the file:
+    file.createDataSet("col_vec", v);
+
+    // The twist is that Eigen typedefs:
+    //   using VectorXd = Matrix<double, Dynamic, 1>;
+    //
+    // Therefore, for HighFive it's indistinguishable from a Nx1 matrix. Since,
+    // Eigen distinguishes row and column vectors, the HighFive chooses to
+    // respect the distinction and deduces the shape of vector as Nx1.
+
+    // ... and read it back as fixed-size:
+    auto w = file.getDataSet("col_vec").read<Eigen::Vector3d>();
+
+    std::cout << "w = \n" << w << "\n";
+
+    return 0;
+}
diff --git a/packages/HighFive/src/examples/read_write_raw_ptr.cpp b/packages/HighFive/src/examples/read_write_raw_ptr.cpp
index b6cd9eda59e74e842a988f777ca5c95ffb26b702..4c8b563cb96916bd55d3fc32556b1028a74baa1d 100644
--- a/packages/HighFive/src/examples/read_write_raw_ptr.cpp
+++ b/packages/HighFive/src/examples/read_write_raw_ptr.cpp
@@ -66,7 +66,7 @@ int main(void) {
         auto nd_array = std::vector<double>(n_elements);
 
         // Finally, read into the memory by passing a raw pointer to the library.
-        dataset.read<double>(nd_array.data());
+        dataset.read_raw<double>(nd_array.data());
     }
 
     return 0;
diff --git a/packages/HighFive/tests/cmake_integration/README.md b/packages/HighFive/tests/cmake_integration/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c69df2ced07b04daddb277df30f00a95dcda69e4
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/README.md
@@ -0,0 +1,22 @@
+# Examples of CMake Integration.
+This folder container examples of projects using CMake to integrate HighFive in
+the project. The following examples have been provided:
+
+*  `application` contains an application/executable
+  that uses HighFive and the optional Boost dependency.
+
+* `dependent_library` contains a library that uses HighFive in its API. It
+  consists of a shared and static library; and includes, as an optional
+  component, a Boost dependency.
+
+* `test_dependent_library` is an application to test that (or demonstrate how)
+  `dependent_library` can be consumed easily.
+
+## Vendoring and Integration Strategy
+Note that all examples have been written to pick different vendoring and
+integration strategies. This is for testing purposes only. Any real project
+would pick a single integration strategy and at most two vendoring strategies.
+
+## Testing
+Run `bash test_cmake_integration.sh` to check if the CMake integration example
+are working as expected.
diff --git a/packages/HighFive/tests/cmake_integration/application/CMakeLists.txt b/packages/HighFive/tests/cmake_integration/application/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..8f2a71423cc6625ac1a9119762d4cbe4c3442055
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/application/CMakeLists.txt
@@ -0,0 +1,87 @@
+# This is an example of an application/executable using HighFive. It
+# demonstrates the different vendoring strategies and targets provided by
+# HighFive.
+
+cmake_minimum_required(VERSION 3.14)
+project(Hi5Application VERSION 0.1)
+
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 14)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+set(INTEGRATION_STRATEGY "short" CACHE STRING "Use 'Include' for HighFive::Include, 'full' for HighFive::HighFive, 'short' for HighFive.")
+set(VENDOR_STRATEGY "submodule" CACHE STRING "Use 'submodule' for Git submodules, 'fetch_content' for FetchContent, 'external' for `find_package`.")
+option(USE_STATIC_HDF5 "Link against static HDF5" OFF)
+option(USE_BOOST "Simulates an application using Boost" OFF)
+
+# Controlling HDF5 features is done by directly setting the HDF5 flags. The
+# interesting ones are probably:
+#  * HDF5_USE_STATIC_LIBRARIES
+#  * HDF5_PREFER_PARALLEL
+if(USE_STATIC_HDF5)
+  set(HDF5_USE_STATIC_LIBRARIES On)
+else()
+  set(HDF5_USE_STATIC_LIBRARIES Off)
+endif()
+
+if(${INTEGRATION_STRATEGY} STREQUAL "bailout")
+  set(HIGHFIVE_FIND_HDF5 Off)
+endif()
+
+if(${VENDOR_STRATEGY} STREQUAL "submodule")
+  # When vendoring via a Git submodule, this is the correct
+  # line to include HighFive.
+  add_subdirectory("deps/HighFive" EXCLUDE_FROM_ALL)
+elseif(${VENDOR_STRATEGY} STREQUAL "fetch_content")
+  include(FetchContent)
+  FetchContent_Declare(HighFive
+    GIT_REPOSITORY $ENV{HIGHFIVE_GIT_REPOSITORY}
+    GIT_TAG $ENV{HIGHFIVE_GIT_TAG}
+  )
+  FetchContent_MakeAvailable(HighFive)
+elseif(${VENDOR_STRATEGY} STREQUAL "external")
+  # When HighFive is installed like regular software and then "found", do the
+  # following:
+  find_package(HighFive REQUIRED)
+endif()
+
+add_executable(Hi5Application "hi5_application.cpp")
+
+if(   ${INTEGRATION_STRATEGY} STREQUAL "Include"
+   OR ${INTEGRATION_STRATEGY} STREQUAL "bailout")
+  # Only add `-I${HIGHFIVE_DIR}/include`.
+  target_link_libraries(Hi5Application PUBLIC HighFive::Include)
+
+  # Now link to HDF5 in whatever fashion you desire.
+  find_package(HDF5 REQUIRED)
+  target_link_libraries(Hi5Application PUBLIC HDF5::HDF5)
+
+  # You might need to take care of MPI.
+  find_package(MPI REQUIRED)
+  target_link_libraries(Hi5Application PUBLIC MPI::MPI_C MPI::MPI_CXX)
+elseif(${INTEGRATION_STRATEGY} STREQUAL "short")
+  # Highest chance of being backwards compatible with v2.
+  target_link_libraries(Hi5Application PUBLIC HighFive)
+elseif(${INTEGRATION_STRATEGY} STREQUAL "full")
+  target_link_libraries(Hi5Application PUBLIC HighFive::HighFive)
+endif()
+
+if(USE_BOOST)
+  find_package(Boost REQUIRED)
+  target_link_libraries(Hi5Application PUBLIC Boost::headers)
+  target_compile_definitions(Hi5Application PUBLIC HI5_APPLICATION_HAS_BOOST=1)
+endif()
+
+if(USE_STATIC_HDF5)
+  find_package(ZLIB REQUIRED)
+  target_link_libraries(${target} PUBLIC ZLIB::ZLIB)
+endif()
+
+# Install
+# -------
+install(TARGETS Hi5Application RUNTIME DESTINATION bin)
+
+enable_testing()
+add_test(NAME test_hi5_application COMMAND ${CMAKE_CURRENT_BINARY_DIR}/Hi5Application)
diff --git a/packages/HighFive/tests/cmake_integration/application/deps/.gitignore b/packages/HighFive/tests/cmake_integration/application/deps/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d6b7ef32c8478a48c3994dcadc86837f4371184d
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/application/deps/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/packages/HighFive/tests/cmake_integration/application/hi5_application.cpp b/packages/HighFive/tests/cmake_integration/application/hi5_application.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dd27260aa4014adae56462de4eab84c12bdc30d6
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/application/hi5_application.cpp
@@ -0,0 +1,36 @@
+#include <highfive/highfive.hpp>
+#if HI5_APPLICATION_HAS_BOOST == 1
+#include <highfive/boost.hpp>
+#endif
+
+int main() {
+    {
+        auto file = HighFive::File("foo.h5", HighFive::File::Truncate);
+
+        auto dset = file.createDataSet("foo", std::vector<double>{1.0, 2.0, 3.0});
+        auto x = dset.read<std::vector<double>>();
+
+        for (size_t i = 0; i < x.size(); i++) {
+            if (x[i] != double(i + 1)) {
+                throw std::runtime_error("HighFiveDemo is broken.");
+            }
+        }
+
+        std::cout << "Hi5Application: success \n";
+    }
+
+#if HI5_APPLICATION_HAS_BOOST == 1
+    {
+        using matrix_t = boost::numeric::ublas::matrix<double>;
+
+        auto file = HighFive::File("bar.h5", HighFive::File::Truncate);
+        matrix_t x(3, 5);
+        auto dset = file.createDataSet("foo", x);
+        auto y = dset.read<matrix_t>();
+
+        std::cout << "Hi5BoostApplication: success \n";
+    }
+#endif
+
+    return 0;
+}
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/CMakeLists.txt b/packages/HighFive/tests/cmake_integration/dependent_library/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ad76d99b200f5bf281181e6940bc7ca350f44334
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/CMakeLists.txt
@@ -0,0 +1,134 @@
+# Do NOT document the available components and targets. Guessing CMake targets
+# and components is an essential part of the game. This library for example has
+# one component called `boost` and three targets. Use
+#
+#   # Without Boost:
+#   find_package(Hi5Dependent REQUIRED)
+#   target_link_libraries(foo PUBLIC Hi5Dependent::Read Hi5Dependent::Write)
+#
+#   # With Boost:
+#   find_package(Hi5Dependent REQUIRED COMPONENTS boost)
+#   target_link_libraries(foo PUBLIC Hi5Dependent::Read Hi5Dependent::Write)
+#   target_link_libraries(foo PUBLIC Hi5Dependent::Boost)
+
+cmake_minimum_required(VERSION 3.14)
+project(Hi5Dependent VERSION 0.1)
+
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 14)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+set(INTEGRATION_STRATEGY "short" CACHE STRING "Use 'Include' for HighFive::Include, 'full' for HighFive::HighFive, 'short' for HighFive.")
+option(USE_STATIC_HDF5 "Link against static HDF5" OFF)
+option(USE_BOOST "Build '${PROJECT_NAME}' with optional Boost dependency." OFF)
+
+if(USE_STATIC_HDF5)
+  set(HDF5_USE_STATIC_LIBRARIES On)
+else()
+  set(HDF5_USE_STATIC_LIBRARIES Off)
+endif()
+
+if(${INTEGRATION_STRATEGY} STREQUAL "bailout")
+  set(HIGHFIVE_FIND_HDF5 Off)
+endif()
+
+# Since any project depending on 'Hi5Dependent' also needs HighFive, it doesn't
+# make sense to vendor HighFive. Therefore, use
+find_package(HighFive REQUIRED)
+
+# For demonstration purposes it consists of a shared and static library
+add_library(${PROJECT_NAME}Write SHARED "src/hi5_dependent/write_vector.cpp")
+add_library(${PROJECT_NAME}::Write ALIAS ${PROJECT_NAME}Write)
+set_target_properties(${PROJECT_NAME}Write PROPERTIES EXPORT_NAME Write)
+
+add_library(${PROJECT_NAME}Read STATIC "src/hi5_dependent/read_vector.cpp")
+add_library(${PROJECT_NAME}::Read ALIAS ${PROJECT_NAME}Read)
+set_target_properties(${PROJECT_NAME}Read PROPERTIES EXPORT_NAME Read)
+
+set(Hi5DependentCoreTargets ${PROJECT_NAME}Write ${PROJECT_NAME}Read)
+set(Hi5DependentAllTargets ${Hi5DependentCoreTargets})
+
+# ... and two more for demonstrating an optional dependency (on Boost).
+if(USE_BOOST)
+  add_library(${PROJECT_NAME}Boost SHARED "src/hi5_dependent/boost.cpp")
+  add_library(${PROJECT_NAME}::Boost ALIAS ${PROJECT_NAME}Boost)
+  set_target_properties(${PROJECT_NAME}Boost PROPERTIES EXPORT_NAME Boost)
+
+  find_package(Boost REQUIRED)
+  target_link_libraries(${PROJECT_NAME}Boost PUBLIC Boost::headers)
+  target_compile_definitions(${PROJECT_NAME}Boost PUBLIC HI5_DEPENDENT_HAS_BOOST=1)
+
+  list(APPEND Hi5DependentAllTargets ${PROJECT_NAME}Boost)
+endif()
+
+foreach(target IN LISTS Hi5DependentAllTargets)
+  target_include_directories(${target}
+      PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
+      PUBLIC $<INSTALL_INTERFACE:include>
+  )
+
+  # Remember to pick one. Writing out all variation serves testing and
+  # demonstration purposes only. Minimizing lines of code is probably a good
+  # strategy.
+  if(   ${INTEGRATION_STRATEGY} STREQUAL "Include"
+     OR ${INTEGRATION_STRATEGY} STREQUAL "bailout")
+    target_link_libraries(${target} PUBLIC HighFive::Include)
+
+    find_package(HDF5 REQUIRED)
+    target_link_libraries(${target} PUBLIC HDF5::HDF5)
+
+    find_package(MPI REQUIRED)
+    target_link_libraries(${target} PUBLIC MPI::MPI_C MPI::MPI_CXX)
+  elseif(${INTEGRATION_STRATEGY} STREQUAL "short")
+    target_link_libraries(${target} PUBLIC HighFive)
+  elseif(${INTEGRATION_STRATEGY} STREQUAL "full")
+    target_link_libraries(${target} PUBLIC HighFive::HighFive)
+  endif()
+
+  if(USE_STATIC_HDF5)
+    find_package(ZLIB REQUIRED)
+    target_link_libraries(${target} PUBLIC ZLIB::ZLIB)
+  endif()
+endforeach()
+
+# Install
+# -------
+include(CMakePackageConfigHelpers)
+write_basic_package_version_file(
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake
+  VERSION ${PACKAGE_VERSION}
+  COMPATIBILITY AnyNewerVersion
+)
+
+install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/
+  DESTINATION "include")
+
+install(TARGETS ${PROJECT_NAME}Read ${PROJECT_NAME}Write EXPORT ${PROJECT_NAME}Targets)
+install(EXPORT ${PROJECT_NAME}Targets
+  FILE ${PROJECT_NAME}Targets.cmake
+  NAMESPACE ${PROJECT_NAME}::
+  DESTINATION cmake
+)
+
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/cmake/${PROJECT_NAME}Config.cmake.in
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
+  @ONLY
+)
+
+install(FILES
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}Config.cmake
+  ${CMAKE_CURRENT_BINARY_DIR}/cmake/${PROJECT_NAME}ConfigVersion.cmake
+  DESTINATION cmake
+)
+
+if(USE_BOOST)
+  install(TARGETS ${PROJECT_NAME}Boost EXPORT ${PROJECT_NAME}BoostTargets)
+  install(EXPORT ${PROJECT_NAME}BoostTargets
+    FILE ${PROJECT_NAME}BoostTargets.cmake
+    NAMESPACE ${PROJECT_NAME}::
+    DESTINATION cmake
+  )
+endif()
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/cmake/Hi5DependentConfig.cmake.in b/packages/HighFive/tests/cmake_integration/dependent_library/cmake/Hi5DependentConfig.cmake.in
new file mode 100644
index 0000000000000000000000000000000000000000..b5df933b9d443605276230db24e6def65160324c
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/cmake/Hi5DependentConfig.cmake.in
@@ -0,0 +1,24 @@
+include(CMakeFindDependencyMacro)
+
+find_dependency(HighFive)
+
+set(Hi5Dependent_INTEGRATION_STRATEGY @INTEGRATION_STRATEGY@)
+if(   ${Hi5Dependent_INTEGRATION_STRATEGY} STREQUAL "Include"
+   OR ${Hi5Dependent_INTEGRATION_STRATEGY} STREQUAL "bailout")
+  # Remember to 'find' any dependencies you introduce, including HDF5 if you
+  # use additional COMPONENTS; or MPI if you unconditionally use it.
+  find_dependency(MPI)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/Hi5DependentTargets.cmake")
+
+if(boost IN_LIST Hi5Dependent_FIND_COMPONENTS)
+  set(Hi5Dependent_USE_BOOST @USE_BOOST@)
+
+  if(NOT Hi5Dependent_USE_BOOST)
+    message(FATAL_ERROR "Library was built without the component: boost")
+  endif()
+
+  find_dependency(Boost)
+  include("${CMAKE_CURRENT_LIST_DIR}/Hi5DependentBoostTargets.cmake")
+endif()
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/read.hpp b/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/read.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..7550efc8a9d54503e2fd374e4ae3b9f9b8d4de9a
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/read.hpp
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <highfive/highfive.hpp>
+#include <vector>
+
+#if HI5_DEPENDENT_HAS_BOOST == 1
+#include <highfive/boost.hpp>
+#endif
+
+namespace hi5_dependent {
+std::vector<double> read_vector(const HighFive::DataSet& dset);
+
+#if HI5_DEPENDENT_HAS_BOOST == 1
+boost::numeric::ublas::matrix<double> read_boost(const HighFive::DataSet& dset);
+HighFive::DataSet write_boost(HighFive::File& file, const boost::numeric::ublas::matrix<double>& x);
+#endif
+}  // namespace hi5_dependent
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/write.hpp b/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/write.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..469b378bf4d978708a860b8869374d7c7fda01cc
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/include/hi5_dependent/write.hpp
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <highfive/highfive.hpp>
+#include <vector>
+
+namespace hi5_dependent {
+HighFive::DataSet write_vector(HighFive::File& file, const std::vector<double>& x);
+}
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/boost.cpp b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/boost.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dc5f6909a1cd75686be54761e353a32410e3ee7d
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/boost.cpp
@@ -0,0 +1,17 @@
+#include <hi5_dependent/read.hpp>
+#include <hi5_dependent/write.hpp>
+
+#include <boost/numeric/ublas/matrix.hpp>
+
+namespace hi5_dependent {
+
+boost::numeric::ublas::matrix<double> read_boost(const HighFive::DataSet& dset) {
+    return dset.read<boost::numeric::ublas::matrix<double>>();
+}
+
+HighFive::DataSet write_boost(HighFive::File& file,
+                              const boost::numeric::ublas::matrix<double>& x) {
+    return file.createDataSet("foo", x);
+}
+
+}  // namespace hi5_dependent
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/read_vector.cpp b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/read_vector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e7e6d973fc0b78d14a49f990492d8a661da6d6dd
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/read_vector.cpp
@@ -0,0 +1,7 @@
+#include <hi5_dependent/read.hpp>
+
+namespace hi5_dependent {
+std::vector<double> read_vector(const HighFive::DataSet& dset) {
+    return dset.read<std::vector<double>>();
+}
+}  // namespace hi5_dependent
diff --git a/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/write_vector.cpp b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/write_vector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..595cd96784b30f154ea79e0cccac7485f32985d9
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/dependent_library/src/hi5_dependent/write_vector.cpp
@@ -0,0 +1,9 @@
+#include <hi5_dependent/write.hpp>
+
+namespace hi5_dependent {
+
+HighFive::DataSet write_vector(HighFive::File& file, const std::vector<double>& x) {
+    return file.createDataSet("foo", x);
+}
+
+}  // namespace hi5_dependent
diff --git a/packages/HighFive/tests/cmake_integration/test_cmake_integration.sh b/packages/HighFive/tests/cmake_integration/test_cmake_integration.sh
new file mode 100644
index 0000000000000000000000000000000000000000..cf80fbfdda5d518da026abaeb77a7fd2b2b07f12
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/test_cmake_integration.sh
@@ -0,0 +1,104 @@
+#!/usr/bin/env bash
+set -xeuo pipefail
+cd "$( dirname "${BASH_SOURCE[0]}")"  # cd here
+
+# All output should be within this directory.
+TMP_DIR="${PWD}/tmp"
+
+# Root of the cmake integration tests.
+TEST_DIR="${PWD}"
+
+# Path of the sources, build and install directory of HighFive.
+HIGHFIVE_DIR="${TEST_DIR}/../.."
+HIGHFIVE_BUILD_DIR="${TMP_DIR}/build-highfive"
+HIGHFIVE_INSTALL_DIR="${HIGHFIVE_BUILD_DIR}/install"
+
+export HIGHFIVE_GIT_REPOSITORY="file://$(realpath "$HIGHFIVE_DIR")"
+export HIGHFIVE_GIT_TAG=$(git rev-parse HEAD)
+
+test_dependent_library() {
+    local project="dependent_library"
+    local project_dir="${TEST_DIR}/${project}"
+
+    for use_boost in On Off
+    do
+      local build_dir="${TMP_DIR}/build"
+      local install_dir="${TMP_DIR}/build/install"
+
+      rm -rf ${build_dir} || true
+
+      cmake "$@" \
+            -DUSE_BOOST=${use_boost} \
+            -DCMAKE_PREFIX_PATH="${HIGHFIVE_INSTALL_DIR}" \
+            -DCMAKE_INSTALL_PREFIX="${install_dir}" \
+            -B "${build_dir}" "${project_dir}"
+
+      cmake --build "${build_dir}" --verbose --target install
+
+      local test_project="test_dependent_library"
+      local test_build_dir="${TMP_DIR}/test_build"
+      local test_install_dir="${TMP_DIR}/test_build/install"
+
+      rm -rf ${test_build_dir} || true
+
+      cmake -DUSE_BOOST=${use_boost} \
+            -DCMAKE_PREFIX_PATH="${HIGHFIVE_INSTALL_DIR};${install_dir}" \
+            -DCMAKE_INSTALL_PREFIX="${test_install_dir}" \
+            -B "${test_build_dir}" "${test_project}"
+
+      cmake --build "${test_build_dir}" --verbose
+      ctest --test-dir "${test_build_dir}" --verbose
+
+    done
+}
+
+test_application() {
+    local project="application"
+    local project_dir="${TEST_DIR}/${project}"
+    local dep_dir="${TEST_DIR}/${project}/deps/HighFive"
+
+    rm "${dep_dir}" || true
+    ln -sf "${HIGHFIVE_DIR}" "${dep_dir}"
+
+    echo ${HIGHFIVE_DIR}
+    echo ${dep_dir}
+
+    for vendor in submodule fetch_content external
+    do
+      for use_boost in On Off
+      do
+        local build_dir="${TMP_DIR}/build"
+        local install_dir="${TMP_DIR}/build/install"
+
+        rm -rf ${build_dir} || true
+
+        cmake "$@" \
+              -DUSE_BOOST=${use_boost} \
+              -DVENDOR_STRATEGY=${vendor} \
+              -DCMAKE_PREFIX_PATH="${HIGHFIVE_INSTALL_DIR}" \
+              -DCMAKE_INSTALL_PREFIX="${install_dir}" \
+              -B "${build_dir}" "${project_dir}"
+
+        cmake --build "${build_dir}" --verbose --target install
+        ctest --test-dir "${build_dir}"
+        "${install_dir}"/bin/Hi5Application
+      done
+    done
+}
+
+cmake -DHIGHFIVE_EXAMPLES=OFF \
+      -DHIGHFIVE_UNIT_TESTS=OFF \
+      -DCMAKE_INSTALL_PREFIX="${HIGHFIVE_INSTALL_DIR}" \
+      -B "${HIGHFIVE_BUILD_DIR}" \
+      "${HIGHFIVE_DIR}"
+
+cmake --build "${HIGHFIVE_BUILD_DIR}" --target install
+
+for integration in Include full short bailout
+do
+  test_dependent_library \
+      -DINTEGRATION_STRATEGY=${integration}
+
+  test_application \
+      -DINTEGRATION_STRATEGY=${integration}
+done
diff --git a/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeList.txt b/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeList.txt
new file mode 100644
index 0000000000000000000000000000000000000000..08bc4a4adfce66472faa808e8ae8e9b13204ea55
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeList.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.14)
+project(TestHi5Dependent VERSION 0.1)
+
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 14)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+add_executable(test_hi5_dependent test_dependent_library.cpp)
+
+if(NOT USE_BOOST)
+  find_package(Hi5Dependent REQUIRED)
+else()
+  find_package(Hi5Dependent REQUIRED COMPONENTS boost)
+  target_link_libraries(test_hi5_dependent PUBLIC Hi5Dependent::Boost)
+endif()
+
+target_link_libraries(test_hi5_dependent PUBLIC Hi5Dependent::Read Hi5Dependent::Write)
+
+enable_testing()
+add_test(NAME test_hi5_dependent COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_hi5_dependent)
diff --git a/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeLists.txt b/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c9023f98ac85600f0f6f8cc0b952373b72bf72e5
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/test_dependent_library/CMakeLists.txt
@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.14)
+project(TestHi5Dependent VERSION 0.1)
+
+if(NOT DEFINED CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 14)
+  set(CMAKE_CXX_STANDARD_REQUIRED ON)
+  set(CMAKE_CXX_EXTENSIONS OFF)
+endif()
+
+add_executable(test_hi5_dependent test_dependent_library.cpp)
+
+if(NOT USE_BOOST)
+  find_package(Hi5Dependent REQUIRED)
+  target_link_libraries(test_hi5_dependent PUBLIC Hi5Dependent::Read Hi5Dependent::Write)
+else()
+  find_package(Hi5Dependent REQUIRED COMPONENTS boost)
+  target_link_libraries(test_hi5_dependent PUBLIC Hi5Dependent::Read Hi5Dependent::Write)
+  target_link_libraries(test_hi5_dependent PUBLIC Hi5Dependent::Boost)
+endif()
+
+enable_testing()
+add_test(NAME run_test_hi5_dependent COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_hi5_dependent)
diff --git a/packages/HighFive/tests/cmake_integration/test_dependent_library/test_dependent_library.cpp b/packages/HighFive/tests/cmake_integration/test_dependent_library/test_dependent_library.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..40aef20a6b46bbf2eb7d21cdddbc49a50f3cbff3
--- /dev/null
+++ b/packages/HighFive/tests/cmake_integration/test_dependent_library/test_dependent_library.cpp
@@ -0,0 +1,34 @@
+#include <hi5_dependent/read.hpp>
+#include <hi5_dependent/write.hpp>
+
+
+int main() {
+    {
+        auto file = HighFive::File("foo.h5", HighFive::File::Truncate);
+
+        auto dset = hi5_dependent::write_vector(file, {1.0, 2.0, 3.0});
+        auto x = hi5_dependent::read_vector(dset);
+
+        for (size_t i = 0; i < x.size(); i++) {
+            if (x[i] != double(i + 1)) {
+                throw std::runtime_error("HighFiveDemo is broken.");
+            }
+        }
+
+        std::cout << "Hi5Dependent: success \n";
+    }
+
+#if HI5_DEPENDENT_HAS_BOOST == 1
+    {
+        auto file = HighFive::File("bar.h5", HighFive::File::Truncate);
+
+        boost::numeric::ublas::matrix<double> x(3, 5);
+        auto dset = hi5_dependent::write_boost(file, x);
+        auto y = hi5_dependent::read_boost(dset);
+
+        std::cout << "Hi5BoostDependent: success \n";
+    }
+#endif
+
+    return 0;
+}
diff --git a/packages/HighFive/tests/test_dependent_library/CMakeLists.txt b/packages/HighFive/tests/test_dependent_library/CMakeLists.txt
deleted file mode 100644
index 570dba224e65112c7af578f1337647b98daedc55..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_dependent_library/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-# This is a sample library to test integration via add_subdirectory and CMakeConfig
-cmake_minimum_required(VERSION 3.1)
-
-project(test_project VERSION 0.1)
-
-if(NOT DEFINED CMAKE_CXX_STANDARD)
-  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")  # For come compilers under cmake 3.1
-  set(CMAKE_CXX_STANDARD 11)
-  set(CMAKE_CXX_STANDARD_REQUIRED ON)
-  set(CMAKE_CXX_EXTENSIONS OFF)
-endif()
-
-option(USE_BUNDLED_HIGHFIVE "Use highfive from deps folder. Otherwise must be installed" ON)
-
-if(USE_BUNDLED_HIGHFIVE)
-    add_subdirectory("deps/HighFive" EXCLUDE_FROM_ALL)
-else()
-    find_package(HighFive REQUIRED QUIET)
-endif()
-
-add_library(simpleton SHARED "src/simpleton.cpp" "src/otherton.cpp")
-target_include_directories(simpleton
-    PUBLIC
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:include>)
-target_link_libraries(simpleton PUBLIC HighFive)
-set_property(TARGET simpleton PROPERTY POSITION_INDEPENDENT_CODE ON)
-
-add_library(otherton STATIC "src/simpleton.cpp" "src/otherton.cpp")
-target_include_directories(otherton
-    PUBLIC
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
-    $<INSTALL_INTERFACE:include>)
-target_link_libraries(otherton PUBLIC HighFive)
-set_property(TARGET otherton PROPERTY POSITION_INDEPENDENT_CODE OFF)
-
-install(
-    TARGETS simpleton otherton
-    EXPORT simpletonTarget
-    DESTINATION lib
-    ARCHIVE DESTINATION lib)
-install(EXPORT simpletonTarget DESTINATION lib)
diff --git a/packages/HighFive/tests/test_dependent_library/deps/.gitignore b/packages/HighFive/tests/test_dependent_library/deps/.gitignore
deleted file mode 100644
index 5e7d2734cfc60289debf74293817c0a8f572ff32..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_dependent_library/deps/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore
diff --git a/packages/HighFive/tests/test_dependent_library/include/simpleton.hpp b/packages/HighFive/tests/test_dependent_library/include/simpleton.hpp
deleted file mode 100644
index b98a09fda04045dbcb72444feff720cbb9db84c4..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_dependent_library/include/simpleton.hpp
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef H5_TEST_SIMPLETON_HPP
-#define H5_TEST_SIMPLETON_HPP
-
-// Include all headers here to catch any missing `inline` statements, since
-// they will be included by two different compilation units.
-#include <highfive/highfive.hpp>
-
-// Boost should always be found in this setup
-#include <boost/numeric/ublas/matrix.hpp>
-
-void function(const HighFive::Object& obj);
-void other_function(const boost::numeric::ublas::matrix<double>& m);
-
-#endif
diff --git a/packages/HighFive/tests/test_dependent_library/src/otherton.cpp b/packages/HighFive/tests/test_dependent_library/src/otherton.cpp
deleted file mode 100644
index 3e10a3630ddbec8d5883a67541d0ec4ea89fc15d..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_dependent_library/src/otherton.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "simpleton.hpp"
-
-void other_function(const boost::numeric::ublas::matrix<double>& m) {
-    m(0, 0) * 0.0;
-}
diff --git a/packages/HighFive/tests/test_dependent_library/src/simpleton.cpp b/packages/HighFive/tests/test_dependent_library/src/simpleton.cpp
deleted file mode 100644
index 12cef5bfc49022af397669d06c40048c223d17b8..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_dependent_library/src/simpleton.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-#include <stdexcept>
-
-#include "simpleton.hpp"
-
-void function(const HighFive::Object& obj) {
-    if (!obj.isValid()) {
-        throw std::exception();
-    }
-}
diff --git a/packages/HighFive/tests/test_project/CMakeLists.txt b/packages/HighFive/tests/test_project/CMakeLists.txt
deleted file mode 100644
index 1a8ef098ae0f68cd6317eb0f526913d1cb5c2b0b..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_project/CMakeLists.txt
+++ /dev/null
@@ -1,25 +0,0 @@
-# This is a sample project to test integration via add_subdirectory and CMakeConfig
-cmake_minimum_required(VERSION 3.1)
-
-project(test_project VERSION 0.1)
-
-if(NOT DEFINED CMAKE_CXX_STANDARD)
-  set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")  # For come compilers under cmake 3.1
-  set(CMAKE_CXX_STANDARD 11)
-  set(CMAKE_CXX_STANDARD_REQUIRED ON)
-  set(CMAKE_CXX_EXTENSIONS OFF)
-endif()
-
-option(USE_BUNDLED_HIGHFIVE "Use highfive from deps folder. Otherwise must be installed" ON)
-
-if(USE_BUNDLED_HIGHFIVE)
-    add_subdirectory("deps/HighFive" EXCLUDE_FROM_ALL)
-else()
-    find_package(HighFive REQUIRED)
-endif()
-
-add_executable(read_write_bin "read_write_vector_dataset.cpp")
-target_link_libraries(read_write_bin HighFive)
-
-enable_testing()
-add_test(NAME test_project COMMAND ${CMAKE_CURRENT_BINARY_DIR}/read_write_bin)
diff --git a/packages/HighFive/tests/test_project/deps/.gitignore b/packages/HighFive/tests/test_project/deps/.gitignore
deleted file mode 100644
index 5e7d2734cfc60289debf74293817c0a8f572ff32..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_project/deps/.gitignore
+++ /dev/null
@@ -1,4 +0,0 @@
-# Ignore everything in this directory
-*
-# Except this file
-!.gitignore
diff --git a/packages/HighFive/tests/test_project/read_write_vector_dataset.cpp b/packages/HighFive/tests/test_project/read_write_vector_dataset.cpp
deleted file mode 120000
index 84b5175b888472b478660178c7ec96b5edac3cf9..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_project/read_write_vector_dataset.cpp
+++ /dev/null
@@ -1 +0,0 @@
-../../src/examples/read_write_vector_dataset.cpp
\ No newline at end of file
diff --git a/packages/HighFive/tests/test_project_integration.sh b/packages/HighFive/tests/test_project_integration.sh
deleted file mode 100644
index 95521995269edcc75362c34cfd755ccad37e6888..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/test_project_integration.sh
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/sh
-set -xeo pipefail
-cd "$( dirname "${BASH_SOURCE[0]}")"  # cd here
-
-BUILD_DIR="${PWD}/build-highfive"
-ROOT="${PWD}/.."
-TEST_DIR="${PWD}"
-INSTALL_DIR="${BUILD_DIR}/install"
-
-test_install() {
-    local project="${1}"
-    local project_dir="${TEST_DIR}/${project}"
-    local dep_dir="${TEST_DIR}/${project}/deps/HighFive"
-    shift
-
-    pushd "${project_dir}"
-
-    local build_dir="build"
-
-    ln -sf ../../.. "${dep_dir}"
-
-    cmake "$@" -B "${build_dir}" .
-    cmake --build "${build_dir}" --verbose
-    ctest --test-dir "${build_dir}"
-
-    rm -f "${dep_dir}"
-    rm -rf "${build_dir}"
-
-    popd
-}
-
-cmake "${ROOT}" \
-    -DHIGHFIVE_EXAMPLES=OFF \
-    -DHIGHFIVE_UNIT_TESTS=OFF \
-    -DCMAKE_INSTALL_PREFIX="${INSTALL_DIR}" \
-    -B "${BUILD_DIR}"
-cmake --build "${BUILD_DIR}" --target install
-
-for project in test_project test_dependent_library; do
-    # Case 1. Base case: include subdirectory
-    test_install "${project}"
-
-    # Case 2. We use an install dir and all deps configuration
-    # Install highfive (no tests required)
-    test_install "${project}" \
-        -DUSE_BUNDLED_HIGHFIVE=NO \
-        -DHIGHFIVE_USE_INSTALL_DEPS=YES \
-        -DCMAKE_PREFIX_PATH="${INSTALL_DIR}"
-
-    # Case 3. We redetect-dependencies
-    test_install "${project}" \
-        -DUSE_BUNDLED_HIGHFIVE=NO \
-        -DHIGHFIVE_USE_INSTALL_DEPS=NO \
-        -DCMAKE_PREFIX_PATH="${INSTALL_DIR}"
-done
-
-rm -rf "${BUILD_DIR}"
diff --git a/packages/HighFive/tests/unit/CMakeLists.txt b/packages/HighFive/tests/unit/CMakeLists.txt
index 2f01bdd81473cbc46e8ca990127e85b1c6d7eb34..c5a07e8e8ec23df33c8fb4511ab0d927c390a71b 100644
--- a/packages/HighFive/tests/unit/CMakeLists.txt
+++ b/packages/HighFive/tests/unit/CMakeLists.txt
@@ -1,25 +1,26 @@
 include(CTest)
 include(Catch)
-include(HighFiveWarnings)
 
 if(MSVC)
   add_definitions(/bigobj)
 endif()
 
 ## Base tests
-foreach(test_name tests_high_five_base tests_high_five_multi_dims tests_high_five_easy test_all_types test_high_five_selection tests_high_five_data_type)
+foreach(test_name tests_high_five_base tests_high_five_multi_dims tests_high_five_easy test_all_types test_high_five_selection tests_high_five_data_type test_legacy)
   add_executable(${test_name} "${test_name}.cpp")
-  target_link_libraries(${test_name} HighFive HighFiveWarnings Catch2::Catch2WithMain)
+  target_link_libraries(${test_name} HighFive HighFiveWarnings HighFiveFlags Catch2::Catch2WithMain)
+  target_link_libraries(${test_name} HighFiveOptionalDependencies)
+
   catch_discover_tests(${test_name})
 endforeach()
 
 if(HIGHFIVE_PARALLEL_HDF5)
-  include(TestHelpers)
   set(tests_parallel_src "tests_high_five_parallel.cpp")
 
   ## parallel MPI tests
   add_executable(tests_parallel_bin ${tests_parallel_src})
-  target_link_libraries(tests_parallel_bin HighFive HighFiveWarnings Catch2::Catch2)
+  target_link_libraries(tests_parallel_bin HighFive HighFiveWarnings HighFiveFlags Catch2::Catch2)
+  target_link_libraries(tests_parallel_bin HighFiveOptionalDependencies)
 
   # We need to patch in a call to `mpirun` or equivalent when using
   # parallel tests. Somehow, this is not foreseen in Catch2, modify the
@@ -29,7 +30,7 @@ if(HIGHFIVE_PARALLEL_HDF5)
   file(READ "${original_catch_script}" original_catch_script_contents)
   string(REGEX REPLACE
          "(add_command\\(add_test.*TEST_EXECUTOR})"
-         "\\1 ${TEST_MPI_EXEC_PREFIX_DEFAULT} -n 2"
+         "\\1 ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 2"
          modified_catch_script_contents
          "${original_catch_script_contents}")
   if(original_catch_script_contents STREQUAL modified_catch_script_contents)
@@ -44,13 +45,23 @@ endif()
 option(HIGHFIVE_TEST_SINGLE_INCLUDES "Enable testing single includes" FALSE)
 
 if(HIGHFIVE_TEST_SINGLE_INCLUDES)
-    file(GLOB public_headers LIST_DIRECTORIES false RELATIVE ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include/highfive/*.hpp)
+  file(GLOB CONFIGURE_DEPENDS public_headers LIST_DIRECTORIES false RELATIVE ${PROJECT_SOURCE_DIR}/include ${PROJECT_SOURCE_DIR}/include/highfive/*.hpp)
     foreach(PUBLIC_HEADER ${public_headers})
+        if(PUBLIC_HEADER STREQUAL "highfive/boost.hpp" AND NOT HIGHFIVE_TEST_BOOST)
+          continue()
+        endif()
+
+        if(PUBLIC_HEADER STREQUAL "highfive/half_float.hpp" AND NOT HIGHFIVE_TEST_HALF_FLOAT)
+          continue()
+        endif()
+
+        if(PUBLIC_HEADER STREQUAL "highfive/eigen.hpp" AND NOT HIGHFIVE_TEST_EIGEN)
+          continue()
+        endif()
+
         get_filename_component(CLASS_NAME ${PUBLIC_HEADER} NAME_WE)
         configure_file(tests_import_public_headers.cpp "tests_${CLASS_NAME}.cpp" @ONLY)
         add_executable("tests_include_${CLASS_NAME}" "${CMAKE_CURRENT_BINARY_DIR}/tests_${CLASS_NAME}.cpp")
-        target_link_libraries("tests_include_${CLASS_NAME}" HighFive HighFiveWarnings)
+        target_link_libraries("tests_include_${CLASS_NAME}" HighFive HighFiveWarnings HighFiveFlags)
     endforeach()
 endif()
-
-add_subdirectory(deprecated)
diff --git a/packages/HighFive/tests/unit/data_generator.hpp b/packages/HighFive/tests/unit/data_generator.hpp
index 9a6712d53208a762a493ab257e8a54feea27cf9a..2964bf9fda9464365af27da9d5ad035211e3509a 100644
--- a/packages/HighFive/tests/unit/data_generator.hpp
+++ b/packages/HighFive/tests/unit/data_generator.hpp
@@ -7,11 +7,16 @@
 #include <vector>
 #include <array>
 
-#ifdef H5_USE_BOOST
-#include <boost/multi_array.hpp>
+#include <highfive/bits/H5Inspector_misc.hpp>
+
+#ifdef HIGHFIVE_TEST_BOOST
+#include <highfive/boost.hpp>
+#endif
+
+#ifdef HIGHFIVE_TEST_EIGEN
+#include <highfive/eigen.hpp>
 #endif
 
-#include <highfive/bits/H5Inspector_misc.hpp>
 
 namespace HighFive {
 namespace testing {
@@ -69,6 +74,8 @@ struct ScalarContainerTraits {
     using container_type = T;
     using base_type = T;
 
+    static constexpr bool is_view = false;
+
     static void set(container_type& array, std::vector<size_t> /* indices */, base_type value) {
         array = value;
     }
@@ -85,6 +92,8 @@ struct ScalarContainerTraits {
         return container_type{};
     }
 
+    static void deallocate(container_type& /* array */, const std::vector<size_t>& /* dims */) {}
+
     static void sanitize_dims(std::vector<size_t>& /* dims */, size_t /* axis */) {}
 };
 
@@ -106,6 +115,8 @@ struct ContainerTraits<std::vector<bool>> {
     using value_type = bool;
     using base_type = bool;
 
+    static constexpr bool is_view = false;
+
     static void set(container_type& array,
                     const std::vector<size_t>& indices,
                     const base_type& value) {
@@ -125,6 +136,8 @@ struct ContainerTraits<std::vector<bool>> {
         return array;
     }
 
+    static void deallocate(container_type& /* array */, const std::vector<size_t>& /* dims */) {}
+
     static void sanitize_dims(std::vector<size_t>& dims, size_t axis) {
         ContainerTraits<value_type>::sanitize_dims(dims, axis + 1);
     }
@@ -136,6 +149,8 @@ struct STLLikeContainerTraits {
     using value_type = ValueType;
     using base_type = typename ContainerTraits<value_type>::base_type;
 
+    static constexpr bool is_view = ContainerTraits<value_type>::is_view;
+
     static void set(container_type& array,
                     const std::vector<size_t>& indices,
                     const base_type& value) {
@@ -151,15 +166,22 @@ struct STLLikeContainerTraits {
     }
 
     static container_type allocate(const std::vector<size_t>& dims) {
-        container_type array(dims[0]);
+        container_type array;
+        array.reserve(dims[0]);
         for (size_t i = 0; i < dims[0]; ++i) {
             auto value = ContainerTraits<value_type>::allocate(lstrip(dims, 1));
-            ContainerTraits<value_type>::assign(array[i], value);
+            array.push_back(value);
         }
 
         return array;
     }
 
+    static void deallocate(container_type& array, const std::vector<size_t>& dims) {
+        for (size_t i = 0; i < dims[0]; ++i) {
+            ContainerTraits<value_type>::deallocate(array[i], lstrip(dims, 1));
+        }
+    }
+
     static void sanitize_dims(std::vector<size_t>& dims, size_t axis) {
         ContainerTraits<value_type>::sanitize_dims(dims, axis + 1);
     }
@@ -200,13 +222,15 @@ struct ContainerTraits<std::array<T, N>>: public STLLikeContainerTraits<std::arr
 };
 
 // -- Boost  -------------------------------------------------------------------
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 template <class T, size_t n>
 struct ContainerTraits<boost::multi_array<T, n>> {
     using container_type = typename boost::multi_array<T, n>;
     using value_type = T;
     using base_type = typename ContainerTraits<value_type>::base_type;
 
+    static constexpr bool is_view = ContainerTraits<value_type>::is_view;
+
     static void set(container_type& array,
                     const std::vector<size_t>& indices,
                     const base_type& value) {
@@ -238,6 +262,14 @@ struct ContainerTraits<boost::multi_array<T, n>> {
         return array;
     }
 
+    static void deallocate(container_type& array, const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + n);
+        size_t n_elements = flat_size(local_dims);
+        for (size_t i = 0; i < n_elements; ++i) {
+            ContainerTraits<value_type>::deallocate(array(unravel(i, local_dims)), lstrip(dims, n));
+        }
+    }
+
     static void sanitize_dims(std::vector<size_t>& dims, size_t axis) {
         ContainerTraits<value_type>::sanitize_dims(dims, axis + n);
     }
@@ -249,6 +281,8 @@ struct ContainerTraits<boost::numeric::ublas::matrix<T>> {
     using value_type = T;
     using base_type = typename ContainerTraits<value_type>::base_type;
 
+    static constexpr bool is_view = ContainerTraits<value_type>::is_view;
+
     static void set(container_type& array,
                     const std::vector<size_t>& indices,
                     const base_type& value) {
@@ -282,11 +316,158 @@ struct ContainerTraits<boost::numeric::ublas::matrix<T>> {
         return array;
     }
 
+    static void deallocate(container_type& array, const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + 2);
+        size_t n_elements = flat_size(local_dims);
+        for (size_t i = 0; i < n_elements; ++i) {
+            auto indices = unravel(i, local_dims);
+            ContainerTraits<value_type>::deallocate(array(indices[0], indices[1]), lstrip(dims, 2));
+        }
+    }
+
+    static void sanitize_dims(std::vector<size_t>& dims, size_t axis) {
+        ContainerTraits<value_type>::sanitize_dims(dims, axis + 2);
+    }
+};
+
+#endif
+
+#if HIGHFIVE_TEST_EIGEN
+
+template <typename EigenType>
+struct EigenContainerTraits {
+    using container_type = EigenType;
+    using value_type = typename EigenType::Scalar;
+    using base_type = typename ContainerTraits<value_type>::base_type;
+
+    static constexpr bool is_view = ContainerTraits<value_type>::is_view;
+
+    static void set(container_type& array,
+                    const std::vector<size_t>& indices,
+                    const base_type& value) {
+        auto i = static_cast<Eigen::Index>(indices[0]);
+        auto j = static_cast<Eigen::Index>(indices[1]);
+        return ContainerTraits<value_type>::set(array(i, j), lstrip(indices, 2), value);
+    }
+
+    static base_type get(const container_type& array, const std::vector<size_t>& indices) {
+        auto i = static_cast<Eigen::Index>(indices[0]);
+        auto j = static_cast<Eigen::Index>(indices[1]);
+        return ContainerTraits<value_type>::get(array(i, j), lstrip(indices, 2));
+    }
+
+    static void assign(container_type& dst, const container_type& src) {
+        dst = src;
+    }
+
+    static container_type allocate(const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + 2);
+        auto n_rows = static_cast<Eigen::Index>(local_dims[0]);
+        auto n_cols = static_cast<Eigen::Index>(local_dims[1]);
+        container_type array = container_type::Zero(n_rows, n_cols);
+
+        size_t n_elements = flat_size(local_dims);
+        for (size_t i = 0; i < n_elements; ++i) {
+            auto element = ContainerTraits<value_type>::allocate(lstrip(dims, 2));
+            set(array, unravel(i, local_dims), element);
+        }
+
+        return array;
+    }
+
+    static void deallocate(container_type& array, const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + 2);
+        size_t n_elements = flat_size(local_dims);
+        for (size_t i_flat = 0; i_flat < n_elements; ++i_flat) {
+            auto indices = unravel(i_flat, local_dims);
+            auto i = static_cast<Eigen::Index>(indices[0]);
+            auto j = static_cast<Eigen::Index>(indices[1]);
+            ContainerTraits<value_type>::deallocate(array(i, j), lstrip(dims, 2));
+        }
+    }
+
     static void sanitize_dims(std::vector<size_t>& dims, size_t axis) {
+        if (EigenType::RowsAtCompileTime != Eigen::Dynamic) {
+            dims[axis + 0] = static_cast<size_t>(EigenType::RowsAtCompileTime);
+        }
+
+        if (EigenType::ColsAtCompileTime != Eigen::Dynamic) {
+            dims[axis + 1] = static_cast<size_t>(EigenType::ColsAtCompileTime);
+        }
         ContainerTraits<value_type>::sanitize_dims(dims, axis + 2);
     }
 };
 
+template <class T, int N_ROWS, int N_COLS, int Options>
+struct ContainerTraits<Eigen::Matrix<T, N_ROWS, N_COLS, Options>>
+    : public EigenContainerTraits<Eigen::Matrix<T, N_ROWS, N_COLS, Options>> {
+  private:
+    using super = EigenContainerTraits<Eigen::Matrix<T, N_ROWS, N_COLS, Options>>;
+
+  public:
+    using container_type = typename super::container_type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+};
+
+template <class T, int N_ROWS, int N_COLS, int Options>
+struct ContainerTraits<Eigen::Array<T, N_ROWS, N_COLS, Options>>
+    : public EigenContainerTraits<Eigen::Array<T, N_ROWS, N_COLS, Options>> {
+  private:
+    using super = EigenContainerTraits<Eigen::Array<T, N_ROWS, N_COLS, Options>>;
+
+  public:
+    using container_type = typename super::container_type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+};
+
+template <class PlainObjectType, int MapOptions>
+struct ContainerTraits<Eigen::Map<PlainObjectType, MapOptions>>
+    : public EigenContainerTraits<Eigen::Map<PlainObjectType, MapOptions>> {
+  private:
+    using super = EigenContainerTraits<Eigen::Map<PlainObjectType, MapOptions>>;
+
+  public:
+    using container_type = typename super::container_type;
+    using value_type = typename super::value_type;
+    using base_type = typename super::base_type;
+
+    static constexpr bool is_view = true;
+
+    static container_type allocate(const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + 2);
+        auto n_rows = static_cast<Eigen::Index>(local_dims[0]);
+        auto n_cols = static_cast<Eigen::Index>(local_dims[1]);
+
+        size_t n_elements = flat_size(local_dims);
+        value_type* ptr = new value_type[n_elements];
+
+        container_type array = container_type(ptr, n_rows, n_cols);
+
+        for (size_t i = 0; i < n_elements; ++i) {
+            auto element = ContainerTraits<value_type>::allocate(lstrip(dims, 2));
+            ContainerTraits::set(array, unravel(i, local_dims), element);
+        }
+
+        return array;
+    }
+
+    static void deallocate(container_type& array, const std::vector<size_t>& dims) {
+        auto local_dims = std::vector<size_t>(dims.begin(), dims.begin() + 2);
+        size_t n_elements = flat_size(local_dims);
+        for (size_t i_flat = 0; i_flat < n_elements; ++i_flat) {
+            auto indices = unravel(i_flat, local_dims);
+            auto i = static_cast<Eigen::Index>(indices[0]);
+            auto j = static_cast<Eigen::Index>(indices[1]);
+            ContainerTraits<value_type>::deallocate(array(i, j), lstrip(dims, 2));
+        }
+
+        delete[] array.data();
+    }
+};
+
+
 #endif
 
 template <class T, class C>
diff --git a/packages/HighFive/tests/unit/deprecated/CMakeLists.txt b/packages/HighFive/tests/unit/deprecated/CMakeLists.txt
deleted file mode 100644
index 5e515374bfe5c67779613a6d8e165153ccebb735..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/unit/deprecated/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-foreach(test_name test_fixed_len_string_array)
-  add_executable(${test_name} "${test_name}.cpp")
-
-  target_link_libraries(${test_name} HighFive HighFiveWarnings Catch2::Catch2WithMain)
-  catch_discover_tests(${test_name})
-
-  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
-    target_compile_options(${test_name} PRIVATE -Wno-deprecated-declarations)
-  endif()
-endforeach()
diff --git a/packages/HighFive/tests/unit/deprecated/test_fixed_len_string_array.cpp b/packages/HighFive/tests/unit/deprecated/test_fixed_len_string_array.cpp
deleted file mode 100644
index 1d0c33aaa243134c3e99c3c2d769cc3b3902bb4c..0000000000000000000000000000000000000000
--- a/packages/HighFive/tests/unit/deprecated/test_fixed_len_string_array.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <catch2/catch_test_macros.hpp>
-
-#include <highfive/highfive.hpp>
-#include "../tests_high_five.hpp"
-
-namespace HighFive {
-
-TEST_CASE("HighFiveFixedLenStringArray") {
-    const std::string file_name("fixed_len_string_array.h5");
-
-    // Create a new file using the default property lists.
-    File file(file_name, File::ReadWrite | File::Create | File::Truncate);
-
-    {  // Dedicated FixedLenStringArray (now deprecated).
-        FixedLenStringArray<10> arr{"0000000", "1111111"};
-
-        // More API: test inserting something
-        arr.push_back("2222");
-        auto ds = file.createDataSet("ds7", arr);  // Short syntax ok
-
-        // Recover truncating
-        FixedLenStringArray<4> array_back;
-        ds.read(array_back);
-        CHECK(array_back.size() == 3);
-        CHECK(array_back[0] == std::string("000"));
-        CHECK(array_back[1] == std::string("111"));
-        CHECK(array_back[2] == std::string("222"));
-        CHECK(array_back.getString(1) == "111");
-        CHECK(array_back.front() == std::string("000"));
-        CHECK(array_back.back() == std::string("222"));
-        CHECK(array_back.data() == std::string("000"));
-        array_back.data()[0] = 'x';
-        CHECK(array_back.data() == std::string("x00"));
-
-        for (auto& raw_elem: array_back) {
-            raw_elem[1] = 'y';
-        }
-        CHECK(array_back.getString(1) == "1y1");
-        for (auto iter = array_back.cbegin(); iter != array_back.cend(); ++iter) {
-            CHECK((*iter)[1] == 'y');
-        }
-    }
-}
-
-template <size_t N>
-static void check_fixed_len_string_array_contents(const FixedLenStringArray<N>& array,
-                                                  const std::vector<std::string>& expected) {
-    REQUIRE(array.size() == expected.size());
-
-    for (size_t i = 0; i < array.size(); ++i) {
-        CHECK(array[i] == expected[i]);
-    }
-}
-
-
-TEST_CASE("HighFiveFixedLenStringArrayStructure") {
-    using fixed_array_t = FixedLenStringArray<10>;
-    // increment the characters of a string written in a std::array
-    auto increment_string = [](const fixed_array_t::value_type arr) {
-        fixed_array_t::value_type output(arr);
-        for (auto& c: output) {
-            if (c == 0) {
-                break;
-            }
-            ++c;
-        }
-        return output;
-    };
-
-    SECTION("create from std::vector (onpoint)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<4>(expected);
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-    SECTION("create from std::vector (oversized)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<8>(expected);
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-    SECTION("create from pointers (onpoint)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<4>(expected.data(), expected.data() + expected.size());
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-    SECTION("create from pointers (oversized)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<8>(expected.data(), expected.data() + expected.size());
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-
-    SECTION("create from std::initializer_list (onpoint)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<4>{"000", "111"};
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-    SECTION("create from std::initializer_list (oversized)") {
-        auto expected = std::vector<std::string>{"000", "111"};
-        auto actual = FixedLenStringArray<8>{"000", "111"};
-        check_fixed_len_string_array_contents(actual, expected);
-    }
-
-    // manipulate FixedLenStringArray with std::copy
-    SECTION("compatible with std::copy") {
-        const fixed_array_t arr1{"0000000", "1111111"};
-        fixed_array_t arr2{"0000000", "1111111"};
-        std::copy(arr1.begin(), arr1.end(), std::back_inserter(arr2));
-        CHECK(arr2.size() == 4);
-    }
-
-    SECTION("compatible with std::transform") {
-        fixed_array_t arr;
-        {
-            const fixed_array_t arr1{"0000000", "1111111"};
-            std::transform(arr1.begin(), arr1.end(), std::back_inserter(arr), increment_string);
-        }
-        CHECK(arr.size() == 2);
-        CHECK(arr[0] == std::string("1111111"));
-        CHECK(arr[1] == std::string("2222222"));
-    }
-
-    SECTION("compatible with std::transform (reverse iterator)") {
-        fixed_array_t arr;
-        {
-            const fixed_array_t arr1{"0000000", "1111111"};
-            std::copy(arr1.rbegin(), arr1.rend(), std::back_inserter(arr));
-        }
-        CHECK(arr.size() == 2);
-        CHECK(arr[0] == std::string("1111111"));
-        CHECK(arr[1] == std::string("0000000"));
-    }
-
-    SECTION("compatible with std::remove_copy_if") {
-        fixed_array_t arr2;
-        {
-            const fixed_array_t arr1{"0000000", "1111111"};
-            std::remove_copy_if(arr1.begin(),
-                                arr1.end(),
-                                std::back_inserter(arr2),
-                                [](const fixed_array_t::value_type& s) {
-                                    return std::strncmp(s.data(), "1111111", 7) == 0;
-                                });
-        }
-        CHECK(arr2.size() == 1);
-        CHECK(arr2[0] == std::string("0000000"));
-    }
-}
-
-TEST_CASE("HighFiveFixedLenStringArrayAttribute") {
-    const std::string file_name("fixed_array_attr.h5");
-    // Create a new file using the default property lists.
-    {
-        File file(file_name, File::ReadWrite | File::Create | File::Truncate);
-        FixedLenStringArray<10> arr{"Hello", "world"};
-        file.createAttribute("str", arr);
-    }
-    // Re-read it
-    {
-        File file(file_name);
-        FixedLenStringArray<8> arr;  // notice the output strings can be smaller
-        file.getAttribute("str").read(arr);
-        CHECK(arr.size() == 2);
-        CHECK(arr[0] == std::string("Hello"));
-        CHECK(arr[1] == std::string("world"));
-    }
-}
-
-}  // namespace HighFive
diff --git a/packages/HighFive/tests/unit/supported_types.hpp b/packages/HighFive/tests/unit/supported_types.hpp
index f708303b1dd55f7aced2e14f9b139fcd9b38fbc6..75e442c60f27c06ff3a1cc35f6e33298915e96cb 100644
--- a/packages/HighFive/tests/unit/supported_types.hpp
+++ b/packages/HighFive/tests/unit/supported_types.hpp
@@ -1,4 +1,3 @@
-
 #pragma once
 
 #include <type_traits>
@@ -6,10 +5,15 @@
 #include <array>
 #include <tuple>
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 #include <boost/multi_array.hpp>
 #endif
 
+#ifdef HIGHFIVE_TEST_EIGEN
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#endif
+
 namespace HighFive {
 namespace testing {
 
@@ -30,7 +34,7 @@ struct STDArray {
     using type = std::array<typename C::template type<T>, n>;
 };
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 template <size_t n, class C = type_identity>
 struct BoostMultiArray {
     template <class T>
@@ -44,6 +48,32 @@ struct BoostUblasMatrix {
 };
 #endif
 
+#ifdef HIGHFIVE_TEST_EIGEN
+template <int n, int m, int Option, class C = type_identity>
+struct EigenMatrix {
+    template <class T>
+    using type = Eigen::Matrix<typename C::template type<T>, n, m, Option>;
+};
+
+template <int n, int m, int Option, class C = type_identity>
+struct EigenArray {
+    template <class T>
+    using type = Eigen::Array<typename C::template type<T>, n, m, Option>;
+};
+
+template <int n, int m, int Option, class C = type_identity>
+struct EigenMapArray {
+    template <class T>
+    using type = Eigen::Map<Eigen::Array<typename C::template type<T>, n, m, Option>>;
+};
+
+template <int n, int m, int Option, class C = type_identity>
+struct EigenMapMatrix {
+    template <class T>
+    using type = Eigen::Map<Eigen::Matrix<typename C::template type<T>, n, m, Option>>;
+};
+#endif
+
 template <class C, class Tuple>
 struct ContainerProduct;
 
@@ -66,7 +96,7 @@ struct ConcatenateTuples<std::tuple<Args1...>> {
 };
 
 // clang-format off
-using numeric_scalar_types = std::tuple<
+using all_numeric_scalar_types = std::tuple<
     int,
     unsigned int,
     long,
@@ -79,11 +109,20 @@ using numeric_scalar_types = std::tuple<
     unsigned long long
 >;
 
-using scalar_types = typename ConcatenateTuples<numeric_scalar_types, std::tuple<bool, std::string>>::type;
-using scalar_types_boost = typename ConcatenateTuples<numeric_scalar_types, std::tuple<bool>>::type;
+
+// To reduce the explosion of combinations, we don't always need
+// to test against every numeric scalar type. These three should
+// suffice.
+using some_numeric_scalar_types = std::tuple<char, int, double>;
+
+using all_scalar_types = typename ConcatenateTuples<all_numeric_scalar_types, std::tuple<bool, std::string>>::type;
+using some_scalar_types = typename ConcatenateTuples<some_numeric_scalar_types, std::tuple<bool, std::string>>::type;
+
+using scalar_types_boost = some_numeric_scalar_types;
+using scalar_types_eigen = some_numeric_scalar_types;
 
 using supported_array_types = typename ConcatenateTuples<
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
   typename ContainerProduct<BoostMultiArray<3>, scalar_types_boost>::type,
   typename ContainerProduct<STDVector<BoostMultiArray<3>>, scalar_types_boost>::type,
   typename ContainerProduct<STDArray<5, BoostMultiArray<3>>, scalar_types_boost>::type,
@@ -92,14 +131,34 @@ using supported_array_types = typename ConcatenateTuples<
   typename ContainerProduct<STDVector<BoostUblasMatrix<>>, scalar_types_boost>::type,
   typename ContainerProduct<STDArray<5, BoostUblasMatrix<>>, scalar_types_boost>::type,
 #endif
-  typename ContainerProduct<STDVector<>, scalar_types>::type,
-  typename ContainerProduct<STDVector<STDVector<>>, scalar_types>::type,
-  typename ContainerProduct<STDVector<STDVector<STDVector<>>>, scalar_types>::type,
-  typename ContainerProduct<STDVector<STDVector<STDVector<STDVector<>>>>, scalar_types>::type,
-  typename ContainerProduct<STDArray<3>, scalar_types>::type,
-  typename ContainerProduct<STDArray<7, STDArray<5>>, scalar_types>::type,
-  typename ContainerProduct<STDVector<STDArray<5>>, scalar_types>::type,
-  typename ContainerProduct<STDArray<7, STDVector<>>, scalar_types>::type
+#ifdef HIGHFIVE_TEST_EIGEN
+  typename ContainerProduct<EigenMatrix<3, 5, Eigen::ColMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenMatrix<3, 5, Eigen::RowMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenMatrix<Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenMatrix<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenArray<3, 5, Eigen::ColMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenArray<3, 5, Eigen::RowMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenArray<Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>, scalar_types_eigen>::type,
+  typename ContainerProduct<EigenArray<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>, scalar_types_eigen>::type,
+  std::tuple<Eigen::Vector2d, Eigen::VectorXd>,
+  typename ContainerProduct<EigenMapMatrix<3, 5, Eigen::ColMajor>, scalar_types_eigen>::type,
+
+  typename ContainerProduct<STDVector<EigenMatrix<3, 5, Eigen::ColMajor>>, scalar_types_eigen>::type,
+  typename ContainerProduct<STDVector<EigenArray<Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>>, scalar_types_eigen>::type,
+  std::tuple<std::vector<Eigen::Vector3d>, std::vector<Eigen::VectorXd>>,
+
+  typename ContainerProduct<STDArray<7, EigenMatrix<3, 5, Eigen::RowMajor>>, scalar_types_eigen>::type,
+  typename ContainerProduct<STDArray<7, EigenArray<Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor>>, scalar_types_eigen>::type,
+  std::tuple<std::array<Eigen::VectorXd, 7>>,
+#endif
+  typename ContainerProduct<STDVector<>, all_scalar_types>::type,
+  typename ContainerProduct<STDVector<STDVector<>>, some_scalar_types>::type,
+  typename ContainerProduct<STDVector<STDVector<STDVector<>>>, some_scalar_types>::type,
+  typename ContainerProduct<STDVector<STDVector<STDVector<STDVector<>>>>, some_scalar_types>::type,
+  typename ContainerProduct<STDArray<3>, some_scalar_types>::type,
+  typename ContainerProduct<STDArray<7, STDArray<5>>, some_scalar_types>::type,
+  typename ContainerProduct<STDVector<STDArray<5>>, some_scalar_types>::type,
+  typename ContainerProduct<STDArray<7, STDVector<>>, some_scalar_types>::type
 >::type;
 
 // clang-format on
diff --git a/packages/HighFive/tests/unit/test_all_types.cpp b/packages/HighFive/tests/unit/test_all_types.cpp
index e772fd1d7d932a1d6905c0b9bec62794f4b693cf..cddc73312fa3a3b7c9f6b7622730749303357d25 100644
--- a/packages/HighFive/tests/unit/test_all_types.cpp
+++ b/packages/HighFive/tests/unit/test_all_types.cpp
@@ -12,6 +12,8 @@
 #include <catch2/catch_template_test_macros.hpp>
 
 #include <highfive/highfive.hpp>
+
+
 #include <type_traits>
 #include "tests_high_five.hpp"
 #include "data_generator.hpp"
@@ -303,10 +305,15 @@ void compare_arrays(const Actual& actual,
 }
 
 template <class Container, class Expected, class Obj>
-void check_read_auto(const Expected& expected, const std::vector<size_t>& dims, const Obj& obj) {
+auto check_read_auto(const Expected& expected, const std::vector<size_t>& dims, const Obj& obj) ->
+    typename std::enable_if<!testing::ContainerTraits<Container>::is_view>::type {
     compare_arrays(obj.template read<Container>(), expected, dims);
 }
 
+template <class Container, class Expected, class Obj>
+auto check_read_auto(const Expected&, const std::vector<size_t>&, const Obj&) ->
+    typename std::enable_if<testing::ContainerTraits<Container>::is_view>::type {}
+
 template <class Container, class Expected, class Obj>
 void check_read_preallocated(const Expected& expected,
                              const std::vector<size_t>& dims,
@@ -315,6 +322,8 @@ void check_read_preallocated(const Expected& expected,
     obj.read(actual);
 
     compare_arrays(actual, expected, dims);
+
+    testing::ContainerTraits<Container>::deallocate(actual, dims);
 }
 
 template <class Container>
@@ -349,6 +358,8 @@ void check_read_regular(const std::string& file_name, const std::vector<size_t>&
     SECTION("attr.read(values)") {
         check_read_preallocated<Container>(expected, dims, attr);
     }
+
+    testing::ContainerTraits<reference_type>::deallocate(expected, dims);
 }
 
 template <class Container>
@@ -378,10 +389,15 @@ void check_writing(const std::vector<size_t>& dims, Write write) {
     obj.read(actual);
 
     compare_arrays(actual, expected, dims);
+
+    testing::ContainerTraits<reference_type>::deallocate(actual, dims);
+    testing::ContainerTraits<Container>::deallocate(values, dims);
+    testing::ContainerTraits<reference_type>::deallocate(expected, dims);
 }
 
 template <class CreateTraits, class Container>
-void check_write_auto(File& file, const std::string& name, const std::vector<size_t>& dims) {
+auto check_write_auto(File& file, const std::string& name, const std::vector<size_t>& dims) ->
+    typename std::enable_if<!testing::ContainerTraits<Container>::is_view>::type {
     auto write_auto = [&](const Container& values) {
         return CreateTraits::create(file, "auto_" + name, values);
     };
@@ -389,6 +405,10 @@ void check_write_auto(File& file, const std::string& name, const std::vector<siz
     check_writing<Container>(dims, write_auto);
 }
 
+template <class CreateTraits, class Container>
+auto check_write_auto(File&, const std::string&, const std::vector<size_t>&) ->
+    typename std::enable_if<testing::ContainerTraits<Container>::is_view>::type {}
+
 template <class CreateTraits, class Container>
 void check_write_deduce_type(File& file, const std::string& name, const std::vector<size_t>& dims) {
     auto write_two_phase_auto = [&](const Container& values) {
diff --git a/packages/HighFive/tests/unit/test_legacy.cpp b/packages/HighFive/tests/unit/test_legacy.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7d7e67f26bf48079fc0ecd5d4e04d7ce01441350
--- /dev/null
+++ b/packages/HighFive/tests/unit/test_legacy.cpp
@@ -0,0 +1,38 @@
+// This file collects tests the require legacy behaviour of v2 (and older) to
+// pass. Tests in this file could be bugs too.
+
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/catch_template_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_vector.hpp>
+
+#include <highfive/highfive.hpp>
+
+using namespace HighFive;
+
+TEST_CASE("HighFiveReadWriteConsts") {
+    // This test seems really strange. Essentially, it malloc's a 3**3 doubles.
+    // Then reinterpret_cast's the pointer to the first double (a `double *`)
+    // as a `double***`. And then uses `inspector` based code to write from the
+    // `double***`.
+
+    const std::string file_name("3d_dataset_from_flat.h5");
+    const std::string dataset_name("dset");
+    const std::array<std::size_t, 3> DIMS{3, 3, 3};
+    using datatype = int;
+
+    File file(file_name, File::ReadWrite | File::Create | File::Truncate);
+    DataSpace dataspace = DataSpace(DIMS);
+
+    DataSet dataset = file.createDataSet<datatype>(dataset_name, dataspace);
+    std::vector<datatype> const t1(DIMS[0] * DIMS[1] * DIMS[2], 1);
+    auto raw_3d_vec_const = reinterpret_cast<datatype const* const* const*>(t1.data());
+    dataset.write_raw(raw_3d_vec_const);
+
+    std::vector<std::vector<std::vector<datatype>>> result;
+    dataset.read(result);
+    for (const auto& vec2d: result) {
+        for (const auto& vec1d: vec2d) {
+            REQUIRE(vec1d == (std::vector<datatype>{1, 1, 1}));
+        }
+    }
+}
diff --git a/packages/HighFive/tests/unit/tests_high_five.hpp b/packages/HighFive/tests/unit/tests_high_five.hpp
index 9d259c8d130bad483bae71c282cd9f887cf065d8..25839c69e19cf275c2ed1df6fff6d67a899ec942 100644
--- a/packages/HighFive/tests/unit/tests_high_five.hpp
+++ b/packages/HighFive/tests/unit/tests_high_five.hpp
@@ -42,7 +42,9 @@ using base_test_types = std::tuple<int,
                                    dcomplex,
                                    fcomplex>;
 
-#ifdef H5_USE_HALF_FLOAT
+#ifdef HIGHFIVE_TEST_HALF_FLOAT
+#include <highfive/half_float.hpp>
+
 using float16_t = half_float::half;
 using numerical_test_types =
     decltype(std::tuple_cat(std::declval<base_test_types>(), std::tuple<float16_t>()));
diff --git a/packages/HighFive/tests/unit/tests_high_five_base.cpp b/packages/HighFive/tests/unit/tests_high_five_base.cpp
index fefdcdd5586fa3748a99a729b2103e3232ba5739..bc33d5dad2ff35f77d327d6e2024d4081e06f48f 100644
--- a/packages/HighFive/tests/unit/tests_high_five_base.cpp
+++ b/packages/HighFive/tests/unit/tests_high_five_base.cpp
@@ -6,6 +6,7 @@
  *          http://www.boost.org/LICENSE_1_0.txt)
  *
  */
+#include <H5Ipublic.h>
 #include <algorithm>
 #include <cstdio>
 #include <cstdlib>
@@ -20,7 +21,6 @@
 #include <type_traits>
 #include <vector>
 
-
 #include <catch2/catch_test_macros.hpp>
 #include <catch2/catch_template_test_macros.hpp>
 #include <catch2/matchers/catch_matchers_vector.hpp>
@@ -28,6 +28,15 @@
 #include <highfive/highfive.hpp>
 #include "tests_high_five.hpp"
 
+#ifdef HIGHFIVE_TEST_BOOST
+#include <highfive/boost.hpp>
+#endif
+
+#ifdef HIGHFIVE_TEST_EIGEN
+#include <highfive/eigen.hpp>
+#endif
+
+
 using namespace HighFive;
 using Catch::Matchers::Equals;
 
@@ -313,27 +322,154 @@ TEST_CASE("Test allocation time") {
     CHECK(alloc_size == data.size() * sizeof(decltype(data)::value_type));
 }
 
-/*
- * Test to ensure legacy support: DataSet used to have a default constructor.
- * However, it is not useful to have a DataSet object that does not actually
- * refer to a dataset in a file. Hence, the the default constructor was
- * deprecated.
- * This test is to ensure that the constructor is not accidentally removed and
- * thereby break users' code.
- */
-TEST_CASE("Test default constructors") {
-    const std::string file_name("h5_default_ctors.h5");
-    const std::string dataset_name("dset");
-    File file(file_name, File::Truncate);
-    auto ds = file.createDataSet(dataset_name, std::vector<int>{1, 2, 3, 4, 5});
+template <class T>
+void check_invalid_hid_Object(T& obj) {
+    auto silence = SilenceHDF5();
+
+    CHECK(!obj.isValid());
+    CHECK(obj.getId() == H5I_INVALID_HID);
+
+    CHECK_THROWS(obj.getInfo());
+    CHECK_THROWS(obj.getType());
+}
+
+template <class T, class U>
+void check_invalid_hid_NodeTraits(T& obj, const U& linkable) {
+    auto silence = SilenceHDF5();
+
+    auto data_space = DataSpace{2, 3};
+    auto data_type = HighFive::create_datatype<double>();
+    auto data = std::vector<double>{1.0, 2.0, 3.0};
+    auto gcpl = GroupCreateProps();
+
+    CHECK_THROWS(obj.createDataSet("foo", data_space, data_type));
+    CHECK_THROWS(obj.template createDataSet<double>("foo", data_space));
+    CHECK_THROWS(obj.createDataSet("foo", data));
+
+    CHECK_THROWS(obj.getDataSet("foo"));
+    CHECK_THROWS(obj.createGroup("foo"));
+    CHECK_THROWS(obj.createGroup("foo", gcpl));
+    CHECK_THROWS(obj.getGroup("foo"));
+    CHECK_THROWS(obj.getDataType("foo"));
+    CHECK_THROWS(obj.getNumberObjects());
+    CHECK_THROWS(obj.getObjectName(0));
+    CHECK_THROWS(obj.rename("foo", "bar"));
+    CHECK_THROWS(obj.listObjectNames());
+    CHECK_THROWS(obj.exist("foo"));
+    CHECK_THROWS(obj.unlink("foo"));
+    CHECK_THROWS(obj.getLinkType("foo"));
+    CHECK_THROWS(obj.getObjectType("foo"));
+    CHECK_THROWS(obj.createSoftLink("foo", linkable));
+    CHECK_THROWS(obj.createSoftLink("foo", "bar"));
+    CHECK_THROWS(obj.createExternalLink("foo", "bar", "baz"));
+    CHECK_THROWS(obj.createHardLink("foo", linkable));
+}
+
+template <class T>
+void check_invalid_hid_DataSet(T& obj) {
+    auto silence = SilenceHDF5();
+
+    CHECK_THROWS(obj.getStorageSize());
+    CHECK_THROWS(obj.getOffset());
+    CHECK_THROWS(obj.getMemSpace());
+    CHECK_THROWS(obj.resize({1, 2, 3}));
+    CHECK_THROWS(obj.getDimensions());
+    CHECK_THROWS(obj.getElementCount());
+    CHECK_THROWS(obj.getCreatePropertyList());
+    CHECK_THROWS(obj.getAccessPropertyList());
+}
+
+template <class T>
+void check_invalid_hid_SliceTraits(T& obj) {
+    auto silence = SilenceHDF5();
+
+    auto slab = HighFive::HyperSlab(RegularHyperSlab({0}));
+    auto space = DataSpace{3};
+    auto set = ElementSet{0, 1, 3};
+    auto data = std::vector<double>{1.0, 2.0, 3.0};
+    auto type = create_datatype<double>();
+    auto cols = std::vector<size_t>{0, 2, 3};
+
+    CHECK_THROWS(obj.select(slab));
+    CHECK_THROWS(obj.select(slab, space));
+    CHECK_THROWS(obj.select({0}, {3}));
+    CHECK_THROWS(obj.select(cols));
+    CHECK_THROWS(obj.select(set));
+
+    CHECK_THROWS(obj.template read<double>());
+    CHECK_THROWS(obj.read(data));
+    CHECK_THROWS(obj.read_raw(data.data(), type));
+    CHECK_THROWS(obj.template read_raw<double>(data.data()));
+
+    CHECK_THROWS(obj.write(data));
+    CHECK_THROWS(obj.write_raw(data.data(), type));
+    CHECK_THROWS(obj.template write_raw<double>(data.data()));
+}
+
+template <class T>
+void check_invalid_hid_PathTraits(T& obj) {
+    auto silence = SilenceHDF5();
+
+    CHECK_THROWS(obj.getPath());
+    CHECK_THROWS(obj.getFile());
+}
+
+template <class T>
+void check_invalid_hid_AnnotateTraits(T& obj) {
+    auto silence = SilenceHDF5();
+
+    auto space = DataSpace{3};
+    auto data = std::vector<double>{1.0, 2.0, 3.0};
+    auto type = create_datatype<double>();
+
+    CHECK_THROWS(obj.createAttribute("foo", space, type));
+    CHECK_THROWS(obj.template createAttribute<double>("foo", space));
+    CHECK_THROWS(obj.createAttribute("foo", data));
+
+    CHECK_THROWS(obj.deleteAttribute("foo"));
+    CHECK_THROWS(obj.getAttribute("foo"));
+    CHECK_THROWS(obj.getNumberAttributes());
+    CHECK_THROWS(obj.listAttributeNames());
+    CHECK_THROWS(obj.hasAttribute("foo"));
+}
+
+template <class T>
+void check_invalid_hid_Group(T& obj) {
+    auto silence = SilenceHDF5();
 
-    DataSet d2;  // expect deprecation warning, as it constructs unsafe object
-    // d2.getFile();  // runtime error
-    CHECK(!d2.isValid());
-    d2 = ds;  // copy
-    CHECK(d2.isValid());
+    CHECK_THROWS(obj.getEstimatedLinkInfo());
+    CHECK_THROWS(obj.getCreatePropertyList());
 }
 
+TEST_CASE("Test default DataSet constructor") {
+    DataSet ds;
+    check_invalid_hid_Object(ds);
+    check_invalid_hid_DataSet(ds);
+    check_invalid_hid_SliceTraits(ds);
+    check_invalid_hid_AnnotateTraits(ds);
+    check_invalid_hid_PathTraits(ds);
+
+    File file("h5_default_dset_ctor.h5", File::Truncate);
+    ds = file.createDataSet("dset", std::vector<int>{1, 2, 3, 4, 5});
+    CHECK(ds.isValid());
+}
+
+TEST_CASE("Test default Group constructor") {
+    File file("h5_default_group_ctor.h5", File::Truncate);
+    Group linkable = file.createGroup("bar");
+
+    Group grp;
+    check_invalid_hid_Object(grp);
+    check_invalid_hid_NodeTraits(grp, linkable);
+    check_invalid_hid_AnnotateTraits(grp);
+    check_invalid_hid_PathTraits(grp);
+
+    grp = file.createGroup("grp");
+
+    CHECK(grp.isValid());
+}
+
+
 TEST_CASE("Test groups and datasets") {
     const std::string file_name("h5_group_test.h5");
     const std::string dataset_name("dset");
@@ -778,6 +914,12 @@ TEST_CASE("DataSpace::getElementCount") {
         CHECK(detail::h5s_get_simple_extent_type(space.getId()) == H5S_NULL);
     }
 
+    SECTION("null initializer_list") {
+        auto space = DataSpace{DataSpace::dataspace_null};
+        CHECK(space.getElementCount() == 0);
+        CHECK(detail::h5s_get_simple_extent_type(space.getId()) == H5S_NULL);
+    }
+
     SECTION("null named ctor") {
         auto space = DataSpace::Null();
         CHECK(space.getElementCount() == 0);
@@ -790,6 +932,12 @@ TEST_CASE("DataSpace::getElementCount") {
         CHECK(detail::h5s_get_simple_extent_type(space.getId()) == H5S_SCALAR);
     }
 
+    SECTION("scalar initializer_list") {
+        auto space = DataSpace{DataSpace::dataspace_scalar};
+        CHECK(space.getElementCount() == 1);
+        CHECK(detail::h5s_get_simple_extent_type(space.getId()) == H5S_SCALAR);
+    }
+
     SECTION("scalar named ctor") {
         auto space = DataSpace::Scalar();
         CHECK(space.getElementCount() == 1);
@@ -907,8 +1055,9 @@ TEST_CASE("HighFiveReadWriteShortcut") {
     const std::string dataset_name("dset");
     std::vector<unsigned> vec;
     vec.resize(x_size);
-    for (unsigned i = 0; i < x_size; i++)
+    for (unsigned i = 0; i < x_size; i++) {
         vec[i] = i * 2;
+    }
     std::string at_contents("Contents of string");
     int my_int = 3;
     std::vector<std::vector<int>> my_nested = {{1, 2}, {3, 4}};
@@ -945,7 +1094,7 @@ TEST_CASE("HighFiveReadWriteShortcut") {
     }
 
     // Plain c arrays. 1D
-    {
+    SECTION("int-c-array") {
         int int_c_array[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
         DataSet ds_int2 = file.createDataSet("/TmpCArrayInt", int_c_array);
 
@@ -957,7 +1106,7 @@ TEST_CASE("HighFiveReadWriteShortcut") {
     }
 
     // Plain c arrays. 2D
-    {
+    SECTION("char-c-array") {
         char char_c_2darray[][3] = {"aa", "bb", "cc", "12"};
         DataSet ds_char2 = file.createDataSet("/TmpCArray2dchar", char_c_2darray);
 
@@ -1508,7 +1657,7 @@ struct CreateEmptyVector {
     }
 };
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 template <int n_dim>
 struct CreateEmptyBoostMultiArray {
     using container_type = boost::multi_array<int, static_cast<long unsigned>(n_dim)>;
@@ -1525,7 +1674,7 @@ struct CreateEmptyBoostMultiArray {
 #endif
 
 
-#ifdef H5_USE_EIGEN
+#ifdef HIGHFIVE_TEST_EIGEN
 struct CreateEmptyEigenVector {
     using container_type = Eigen::VectorXi;
 
@@ -1655,7 +1804,7 @@ void check_empty_everything(const std::vector<size_t>& dims) {
     }
 }
 
-#ifdef H5_USE_EIGEN
+#ifdef HIGHFIVE_TEST_EIGEN
 template <int ndim>
 void check_empty_eigen(const std::vector<size_t>&) {}
 
@@ -1682,13 +1831,13 @@ void check_empty(const std::vector<size_t>& dims) {
         check_empty_everything<CreateEmptyVector<ndim>>(dims);
     }
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
     SECTION("boost::multi_array") {
         check_empty_everything<CreateEmptyBoostMultiArray<ndim>>(dims);
     }
 #endif
 
-#ifdef H5_USE_EIGEN
+#ifdef HIGHFIVE_TEST_EIGEN
     check_empty_eigen<ndim>(dims);
 #endif
 }
@@ -2113,7 +2262,7 @@ TEST_CASE("DirectWriteBool") {
     SECTION("WriteReadCycleAttribute") {
         auto attr = file.createAttribute("attr", dataspace, datatype);
         attr.write_raw(expected);
-        attr.read(actual);
+        attr.read_raw(actual);
 
         for (size_t i = 0; i < n; ++i) {
             REQUIRE(expected[i] == actual[i]);
@@ -2123,7 +2272,7 @@ TEST_CASE("DirectWriteBool") {
     SECTION("WriteReadCycleDataSet") {
         auto dset = file.createAttribute("dset", dataspace, datatype);
         dset.write_raw(expected);
-        dset.read(actual);
+        dset.read_raw(actual);
 
         for (size_t i = 0; i < n; ++i) {
             REQUIRE(expected[i] == actual[i]);
@@ -2422,7 +2571,7 @@ TEST_CASE("HighFiveFixedString") {
             // Due to missing non-const overload of `data()` until C++17 we'll
             // read into something else instead (don't forget the '\0').
             auto expected = std::vector<char>(n_chars, '!');
-            ds.read(expected.data(), datatype);
+            ds.read_raw(expected.data(), datatype);
 
             CHECK(expected.size() == value.size() + 1);
             for (size_t i = 0; i < value.size(); ++i) {
@@ -2433,7 +2582,7 @@ TEST_CASE("HighFiveFixedString") {
 #if HIGHFIVE_CXX_STD >= 17
         {
             auto expected = std::string(value.size(), '-');
-            ds.read(expected.data(), datatype);
+            ds.read_raw(expected.data(), datatype);
 
             REQUIRE(expected == value);
         }
@@ -2453,7 +2602,7 @@ TEST_CASE("HighFiveFixedString") {
         ds.write_raw(value.data(), datatype);
 
         auto expected = std::vector<char>(value.size(), '-');
-        ds.read(expected.data(), datatype);
+        ds.read_raw(expected.data(), datatype);
 
         CHECK(expected.size() == value.size());
         for (size_t i = 0; i < value.size(); ++i) {
@@ -2520,29 +2669,6 @@ TEST_CASE("HighFiveReference") {
     }
 }
 
-TEST_CASE("HighFiveReadWriteConsts") {
-    const std::string file_name("3d_dataset_from_flat.h5");
-    const std::string dataset_name("dset");
-    const std::array<std::size_t, 3> DIMS{3, 3, 3};
-    using datatype = int;
-
-    File file(file_name, File::ReadWrite | File::Create | File::Truncate);
-    DataSpace dataspace = DataSpace(DIMS);
-
-    DataSet dataset = file.createDataSet<datatype>(dataset_name, dataspace);
-    std::vector<datatype> const t1(DIMS[0] * DIMS[1] * DIMS[2], 1);
-    auto raw_3d_vec_const = reinterpret_cast<datatype const* const* const*>(t1.data());
-    dataset.write(raw_3d_vec_const);
-
-    std::vector<std::vector<std::vector<datatype>>> result;
-    dataset.read(result);
-    for (const auto& vec2d: result) {
-        for (const auto& vec1d: vec2d) {
-            REQUIRE(vec1d == (std::vector<datatype>{1, 1, 1}));
-        }
-    }
-}
-
 TEST_CASE("HighFiveDataTypeClass") {
     auto Float = DataTypeClass::Float;
     auto String = DataTypeClass::String;
@@ -2561,7 +2687,7 @@ TEST_CASE("HighFiveDataTypeClass") {
     CHECK(((Float | String) & String) == String);
 }
 
-#ifdef H5_USE_EIGEN
+#ifdef HIGHFIVE_TEST_EIGEN
 
 template <typename T>
 void test_eigen_vec(File& file, const std::string& test_flavor, const T& vec_input, T& vec_output) {
@@ -2612,7 +2738,7 @@ TEST_CASE("HighFiveEigen") {
         vec_in << 1, 2, 3, 4, 5, 6, 7, 8, 9;
         Eigen::Matrix<double, 3, 3> vec_out;
 
-        CHECK_THROWS(test_eigen_vec(file, ds_name_flavor, vec_in, vec_out));
+        test_eigen_vec(file, ds_name_flavor, vec_in, vec_out);
     }
 
     // Eigen MatrixXd
@@ -2621,7 +2747,7 @@ TEST_CASE("HighFiveEigen") {
         Eigen::MatrixXd vec_in = 100. * Eigen::MatrixXd::Random(20, 5);
         Eigen::MatrixXd vec_out(20, 5);
 
-        CHECK_THROWS(test_eigen_vec(file, ds_name_flavor, vec_in, vec_out));
+        test_eigen_vec(file, ds_name_flavor, vec_in, vec_out);
     }
 
     // std::vector<of EigenMatrixXd>
@@ -2635,10 +2761,10 @@ TEST_CASE("HighFiveEigen") {
         vec_in.push_back(m2);
         std::vector<Eigen::MatrixXd> vec_out(2, Eigen::MatrixXd::Zero(20, 5));
 
-        CHECK_THROWS(test_eigen_vec(file, ds_name_flavor, vec_in, vec_out));
+        test_eigen_vec(file, ds_name_flavor, vec_in, vec_out);
     }
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
     // boost::multi_array<of EigenVector3f>
     {
         ds_name_flavor = "BMultiEigenVector3f";
@@ -2677,7 +2803,7 @@ TEST_CASE("HighFiveEigen") {
             }
         }
 
-        CHECK_THROWS(test_eigen_vec(file, ds_name_flavor, vec_in, vec_out));
+        test_eigen_vec(file, ds_name_flavor, vec_in, vec_out);
     }
 
 #endif
diff --git a/packages/HighFive/tests/unit/tests_high_five_easy.cpp b/packages/HighFive/tests/unit/tests_high_five_easy.cpp
index e003c323401a9460332883abd618fef10a9a169d..aa30b4e96f938d372c4e364fad745e84b166a291 100644
--- a/packages/HighFive/tests/unit/tests_high_five_easy.cpp
+++ b/packages/HighFive/tests/unit/tests_high_five_easy.cpp
@@ -20,13 +20,22 @@
 
 #include <stdio.h>
 
-#include <highfive/H5Easy.hpp>
 
-#ifdef H5_USE_XTENSOR
+#ifdef HIGHFIVE_TEST_XTENSOR
 #include <xtensor/xrandom.hpp>
 #include <xtensor/xview.hpp>
 #endif
 
+#ifdef HIGHFIVE_TEST_EIGEN
+#include <Eigen/Dense>
+#endif
+
+#ifdef HIGHFIVE_TEST_OPENCV
+#define H5_USE_OPENCV
+#endif
+
+#include <highfive/H5Easy.hpp>
+
 #include <catch2/catch_test_macros.hpp>
 
 TEST_CASE("H5Easy_Compression") {
@@ -179,7 +188,7 @@ TEST_CASE("H5Easy_Attribute_scalar") {
     CHECK(c == c_r);
 }
 
-#ifdef H5_USE_XTENSOR
+#ifdef HIGHFIVE_TEST_XTENSOR
 TEST_CASE("H5Easy_extend1d") {
     H5Easy::File file("h5easy_extend1d.h5", H5Easy::File::Overwrite);
 
@@ -304,7 +313,7 @@ TEST_CASE("H5Easy_Attribute_xtensor") {
 }
 #endif
 
-#ifdef H5_USE_EIGEN
+#ifdef HIGHFIVE_TEST_EIGEN
 TEST_CASE("H5Easy_Eigen_MatrixX") {
     H5Easy::File file("h5easy_eigen_MatrixX.h5", H5Easy::File::Overwrite);
 
@@ -439,7 +448,7 @@ TEST_CASE("H5Easy_Attribute_Eigen_MatrixX") {
 }
 #endif
 
-#ifdef H5_USE_OPENCV
+#ifdef HIGHFIVE_TEST_OPENCV
 TEST_CASE("H5Easy_OpenCV_Mat_") {
     H5Easy::File file("h5easy_opencv_Mat_.h5", H5Easy::File::Overwrite);
 
diff --git a/packages/HighFive/tests/unit/tests_high_five_multi_dims.cpp b/packages/HighFive/tests/unit/tests_high_five_multi_dims.cpp
index 08fbea9cec350a8b4de42393a1a7d5ef830b5d70..60ec66cae05bb1ba6012a397f7afe3ab84b8a0d1 100644
--- a/packages/HighFive/tests/unit/tests_high_five_multi_dims.cpp
+++ b/packages/HighFive/tests/unit/tests_high_five_multi_dims.cpp
@@ -13,8 +13,9 @@
 #include <highfive/highfive.hpp>
 
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 #include <boost/multi_array.hpp>
+#include <highfive/boost.hpp>
 #endif
 
 #include <catch2/catch_test_macros.hpp>
@@ -127,7 +128,7 @@ TEMPLATE_LIST_TEST_CASE("vector of array", "[template]", numerical_test_types) {
 }
 
 
-#ifdef H5_USE_BOOST
+#ifdef HIGHFIVE_TEST_BOOST
 
 template <typename T>
 void MultiArray3DTest() {
diff --git a/src/dev/ParallelChecker.hpp b/src/dev/ParallelChecker.hpp
index 9ff94334e0856dc9cef13e63fd9b9f93671a8d45..08b6de99159ed84019529459b5e21799003f99fc 100644
--- a/src/dev/ParallelChecker.hpp
+++ b/src/dev/ParallelChecker.hpp
@@ -133,7 +133,7 @@ class ParallelChecker
     auto dataset = group.getDataSet(name);
     Array<data_type> array(dataset.getElementCount());
 
-    dataset.read<data_type>(&(array[0]));
+    dataset.read_raw(&(array[0]));
     return array;
   }
 
@@ -146,7 +146,7 @@ class ParallelChecker
     auto dataset = group.getDataSet(name);
     Table<data_type> table(dataset.getDimensions()[0], dataset.getDimensions()[1]);
 
-    dataset.read<data_type>(&(table(0, 0)));
+    dataset.read_raw(&(table(0, 0)));
     return table;
   }
 
diff --git a/src/utils/checkpointing/CheckpointUtils.cpp b/src/utils/checkpointing/CheckpointUtils.cpp
index 519b5a29cf805d4bb701ebb47cbefc892632d1d7..c67514c1002216386b63ac3591709d3b3760213e 100644
--- a/src/utils/checkpointing/CheckpointUtils.cpp
+++ b/src/utils/checkpointing/CheckpointUtils.cpp
@@ -494,13 +494,12 @@ writeDiscreteFunctionVariant(const std::string& symbol_name,
       writeMesh(mesh_v, file, checkpoint_group);
       if constexpr (is_discrete_function_P0_v<DFType>) {
         using data_type = std::decay_t<typename DFType::data_type>;
-        // variable_group.createAttribute("Vh_type", "P0");
         variable_group.createAttribute("data_type", dataTypeName(ast_node_data_type_from<data_type>));
         write(variable_group, "values", discrete_function.cellValues());
       } else if constexpr (is_discrete_function_P0_vector_v<DFType>) {
         using data_type = std::decay_t<typename DFType::data_type>;
-        // variable_group.createAttribute("Vh_type", "P0Vector");
         variable_group.createAttribute("data_type", dataTypeName(ast_node_data_type_from<data_type>));
+        throw NotImplementedError("P0Vector");
         //        write(variable_group, "values", discrete_function.cellArrays());
       }
     },
diff --git a/src/utils/checkpointing/CheckpointUtils.hpp b/src/utils/checkpointing/CheckpointUtils.hpp
index 5a5fe066d9bd457cb603ae8c3f4af9cf800e6dea..6e9af741e9a468e143f1571b672880881b22f2d2 100644
--- a/src/utils/checkpointing/CheckpointUtils.hpp
+++ b/src/utils/checkpointing/CheckpointUtils.hpp
@@ -18,8 +18,10 @@ write(HighFive::Group& group, const std::string& name, const Array<DataType>& ar
   properties.add(HighFive::Deflate(3));
 
   if constexpr (std::is_same_v<CellType, data_type>) {
-    auto dataset = group.createDataSet<short>(name, HighFive::DataSpace{std::vector<size_t>{array.size()}}, properties);
-    dataset.template write_raw<short>(reinterpret_cast<const short*>(&(array[0])));
+    using base_type = std::underlying_type_t<CellType>;
+    auto dataset =
+      group.createDataSet<base_type>(name, HighFive::DataSpace{std::vector<size_t>{array.size()}}, properties);
+    dataset.template write_raw<base_type>(reinterpret_cast<const base_type*>(&(array[0])));
   } else if constexpr ((std::is_same_v<CellId, data_type>) or (std::is_same_v<FaceId, data_type>) or
                        (std::is_same_v<EdgeId, data_type>) or (std::is_same_v<NodeId, data_type>)) {
     using base_type = typename data_type::base_type;
diff --git a/src/utils/checkpointing/ResumeUtils.hpp b/src/utils/checkpointing/ResumeUtils.hpp
index 1ade7973f9c09d3c9bfca4c374958f947a96e2fb..1882d2fc7597a96fd056b360258171d083687bda 100644
--- a/src/utils/checkpointing/ResumeUtils.hpp
+++ b/src/utils/checkpointing/ResumeUtils.hpp
@@ -17,13 +17,14 @@ readArray(const HighFive::Group& group, const std::string& name)
   auto dataset = group.getDataSet(name);
   Array<DataType> array(dataset.getElementCount());
   if constexpr (std::is_same_v<CellType, data_type>) {
-    dataset.template read<short>(reinterpret_cast<short*>(&(array[0])));
+    using base_type = std::underlying_type_t<CellType>;
+    dataset.read_raw(reinterpret_cast<base_type*>(&(array[0])));
   } else if constexpr ((std::is_same_v<CellId, data_type>) or (std::is_same_v<FaceId, data_type>) or
                        (std::is_same_v<EdgeId, data_type>) or (std::is_same_v<NodeId, data_type>)) {
     using base_type = typename data_type::base_type;
-    dataset.template read<base_type>(reinterpret_cast<base_type*>(&(array[0])));
+    dataset.read_raw(reinterpret_cast<base_type*>(&(array[0])));
   } else {
-    dataset.template read<data_type>(&(array[0]));
+    dataset.read_raw(&(array[0]));
   }
 
   return array;
@@ -38,13 +39,14 @@ readTable(const HighFive::Group& group, const std::string& name)
   auto dataset = group.getDataSet(name);
   Table<DataType> table(dataset.getDimensions()[0], dataset.getDimensions()[1]);
   if constexpr (std::is_same_v<CellType, data_type>) {
-    dataset.template read<short>(reinterpret_cast<short*>(&(table(0, 0))));
+    using base_type = std::underlying_type_t<CellType>;
+    dataset.read_raw(reinterpret_cast<base_type*>(&(table(0, 0))));
   } else if constexpr ((std::is_same_v<CellId, data_type>) or (std::is_same_v<FaceId, data_type>) or
                        (std::is_same_v<EdgeId, data_type>) or (std::is_same_v<NodeId, data_type>)) {
     using base_type = typename data_type::base_type;
-    dataset.template read<base_type>(reinterpret_cast<base_type*>(&(table(0, 0))));
+    dataset.read_raw<base_type>(reinterpret_cast<base_type*>(&(table(0, 0))));
   } else {
-    dataset.template read<data_type>(&(table(0, 0)));
+    dataset.read_raw<data_type>(&(table(0, 0)));
   }
 
   return table;