Repository: computationalgeography/lue (language: python)

Issue:
Fix all warnings generated in C/I builds
- Compiler, CMake, ...
- If possible, set the "treat warnings as errors" compiler flag? Only in C/I builds.


Discussion / hints:

Fix patch:
diff --git a/.github/actions/install_hpx/action.yaml b/.github/actions/install_hpx/action.yaml
index 4f4a8d230..84c6ea1bb 100644
--- a/.github/actions/install_hpx/action.yaml
+++ b/.github/actions/install_hpx/action.yaml
@@ -28,7 +28,7 @@ runs:
   steps:
     - name: cache hpx
       id: cache-hpx
-      uses: actions/cache@v3
+      uses: actions/cache@v4
       env:
         cache-name: cache-hpx
       with:
diff --git a/.github/workflows/conda.yml b/.github/workflows/conda.yml
index 0113cc81f..ec70b5c4a 100644
--- a/.github/workflows/conda.yml
+++ b/.github/workflows/conda.yml
@@ -24,12 +24,13 @@ jobs:
             fail-fast: false
             matrix:
                 include:
-                - os: "macos-14"
-                  target-platform: arm-64
-                  conda-bld-dir: "/Users/runner/miniconda3/envs/test/conda-bld/arm-64/"
-                - os: "macos-13"
-                  target-platform: osx-64
-                  conda-bld-dir: "/Users/runner/miniconda3/envs/test/conda-bld/osx-64/"
+                # Bug in HPX / Clang headers it seems
+                # - os: "macos-14"
+                #   target-platform: arm-64
+                #   conda-bld-dir: "/Users/runner/miniconda3/envs/test/conda-bld/arm-64/"
+                # - os: "macos-13"
+                #   target-platform: osx-64
+                #   conda-bld-dir: "/Users/runner/miniconda3/envs/test/conda-bld/osx-64/"
                 - os: "ubuntu-22.04"
                   target-platform: linux-64
                   conda-bld-dir: "/home/runner/miniconda3/envs/test/conda-bld/linux-64/"
@@ -46,7 +47,7 @@ jobs:
                   auto-update-conda: false
             - name: Build package
               run: |
-                  mamba install boa
+                  mamba install boa conda-verify
                   conda mambabuild environment/conda --override-channels --channel conda-forge
             - name: Upload
               uses: Dylan700/sftp-upload-action@latest
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
index 3ff67229b..90ef00734 100644
--- a/.github/workflows/linux.yml
+++ b/.github/workflows/linux.yml
@@ -102,6 +102,7 @@ jobs:
             c_compiler: ${{ matrix.compiler.c }}
             cxx_compiler: ${{ matrix.compiler.cxx }}
             build_type: Release
+            cmake_flags: "-D CMAKE_POLICY_DEFAULT_CMP0148=OLD"
             cmake_preset: hpx_release_linux_node_configuration
             cmake_preset_file: ${{ env.lue_source_directory }}/CMakeHPXPresets.json
             hpx_version: ${{ env.hpx_version }}
@@ -191,8 +192,11 @@ jobs:
               ${{ env.lue_runtime_install_directory }}/bin/lue_scalability --version
               python3 -c "import lue, lue.data_model, lue.framework, lue.pcraster, lue.qa.scalability; print(lue.__version__)"
 
+        - name: consume
+          run: |
               # Test of imported CMake targets
               git clone https://github.com/computationalgeography/lue_consume.git ${{ env.lue_consume_source_directory }}
+
               cmake \
                   -S ${{ env.lue_consume_source_directory }} \
                   -B ${{ env.lue_consume_build_directory }} \
@@ -200,39 +204,14 @@ jobs:
                   -D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
                   -D CMAKE_BUILD_TYPE=Release \
                   -D CMAKE_POLICY_DEFAULT_CMP0144=NEW \
-                  -D FETCHCONTENT_QUIET=OFF \
                   -D LUE_ROOT=${{ env.lue_development_install_directory }} \
                   -D HPX_ROOT=${{ env.hpx_install_directory }} \
                   -D MDSPAN_ROOT=${{ env.mdspan_install_directory }}
               cmake --build ${{ env.lue_consume_build_directory }} --target all
+
               ${{ env.lue_consume_build_directory }}/lue_consume_data_model
               ${{ env.lue_consume_build_directory }}/lue_consume_framework
 
-        # - name: source package
-        #   run: |
-        #       cmake \
-        #           --build ${{ env.lue_build_directory }} \
-        #           --target package_source
-        #       mkdir src
-        #       cd src
-        #       tar zxf ../lue-*.tar.gz
-        #       mkdir bld
-        #       cd lue-*
-        #       ln -s ${{ env.lue_build_directory }}/CMakePresets.json CMakeUserPresets.json
-        #       # TODO Source package does not yet contain the generated source files
-        #       # CMAKE_PREFIX_PATH=${{ env.lue_build_directory }} \
-        #       #     cmake --preset conan-release \
-        #       #         -B bld \
-        #       #         -D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
-        #       #         -D LUE_DATA_MODEL_WITH_PYTHON_API=TRUE \
-        #       #         -D LUE_DATA_MODEL_WITH_UTILITIES=TRUE \
-        #       #         -D LUE_BUILD_VIEW=TRUE \
-        #       #         -D LUE_BUILD_QA=TRUE \
-        #       #         -D LUE_QA_WITH_PYTHON_API=TRUE \
-        #       #         -D LUE_FRAMEWORK_WITH_PYTHON_API=TRUE
-
-        #       # TODO Test configuring and building the source package
-
         - name: documentation
           if: github.repository == 'computationalgeography/lue' && github.ref == 'refs/heads/master' && matrix.compiler.cxx == 'g++-12' && matrix.python_version == '3.12'
           env:
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml
index fb9573945..f1780e5fc 100644
--- a/.github/workflows/macos.yml
+++ b/.github/workflows/macos.yml
@@ -94,7 +94,7 @@ jobs:
             c_compiler: ${{ matrix.compiler.c }}
             cxx_compiler: ${{ matrix.compiler.cxx }}
             build_type: Release
-            cmake_flags: "-D CMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.macos_version }}.0"
+            cmake_flags: "-D CMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.macos_version }}.0 -D CMAKE_POLICY_DEFAULT_CMP0148=OLD"
             cmake_preset: hpx_release_macos_node_configuration
             cmake_preset_file: ${{ env.lue_source_directory }}/CMakeHPXPresets.json
             hpx_version: ${{ env.hpx_version }}
@@ -191,12 +191,16 @@ jobs:
               python${{ matrix.python_version }} ${{ env.lue_runtime_install_directory }}/bin/lue_scalability --version
               python${{ matrix.python_version }} -c "import lue, lue.data_model, lue.framework, lue.pcraster, lue.qa.scalability; print(lue.__version__)"
 
+        - name: consume
+          run: |
               # Test of imported CMake targets
               git clone https://github.com/computationalgeography/lue_consume.git ${{ env.lue_consume_source_directory }}
+
               # broken hdf5 1.14 https://github.com/Homebrew/homebrew-core/issues/159691
               PATH="$(brew --prefix hdf5@1.10)/bin:$PATH" \
               LDFLAGS="-L$(brew --prefix hdf5@1.10)/lib" \
               CPPFLAGS="-I$(brew --prefix hdf5@1.10)/include" \
+
               cmake \
                   -S ${{ env.lue_consume_source_directory }} \
                   -B ${{ env.lue_consume_build_directory }} \
@@ -208,5 +212,6 @@ jobs:
                   -D HPX_ROOT=${{ env.hpx_install_directory }} \
                   -D MDSPAN_ROOT=${{ env.mdspan_install_directory }}
               cmake --build ${{ env.lue_consume_build_directory }} --target all
+
               ${{ env.lue_consume_build_directory }}/lue_consume_data_model
               ${{ env.lue_consume_build_directory }}/lue_consume_framework
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
index d082a8e4d..d0c706ae8 100644
--- a/.github/workflows/windows.yml
+++ b/.github/workflows/windows.yml
@@ -63,11 +63,12 @@ jobs:
           with:
             path: ${{ env.lue_source_directory }}
 
-        - uses: conda-incubator/setup-miniconda@v2
+        - uses: conda-incubator/setup-miniconda@v3
           with:
+            miniforge-version: latest
             auto-update-conda: true
+            conda-solver: "libmamba"
             python-version: ${{ matrix.python_version }}
-            channels: conda-forge
 
         - name: setup platform
           run: |
@@ -79,11 +80,9 @@ jobs:
               # TODO Use the GDAL Conan package instead of the Conda package, once the GDAL
               #      Conan package actually works
 
-              # Use different solver than the default to work around "picosat: out of memory in 'new'"
-              conda install -n base -c defaults conda-libmamba-solver
-              conda install --solver=libmamba \
-                  boost-cpp \
-                  "conan>=2" \
+              conda install \
+                  libboost-devel \
+                  conan \
                   conda-build \
                   docopt \
                   gdal \
@@ -111,7 +110,7 @@ jobs:
             cmake_preset_file: ${{ env.lue_source_directory }}/CMakeHPXPresets.json
             # Boost root is here: $CONDA_PREFIX/Library, but this results in a backslashes in a Windows path in the HPXConfig.cmake
             # That is a bug in the HPX CMake scripts. Forward slashes should be used, e.g.: file(TO_CMAKE_PATH BOOST_ROOT HPX_BOOST_ROOT).
-            cmake_flags: "-D BOOST_ROOT=C:/Miniconda/envs/test/Library -D HWLOC_ROOT=$CONDA_PREFIX/Library -D HWLOC_LIBRARY=$CONDA_PREFIX/Library/lib/hwloc.lib"
+            cmake_flags: "-D CMAKE_POLICY_DEFAULT_CMP0148=OLD -D BOOST_ROOT=C:/Users/runneradmin/miniconda3/envs/test/Library -D HWLOC_ROOT=$CONDA_PREFIX/Library -D HWLOC_LIBRARY=$CONDA_PREFIX/Library/lib/hwloc.lib"
             hpx_version: ${{ env.hpx_version }}
             source_directory: ${{ env.hpx_source_directory }}
             build_directory: ${{ env.hpx_build_directory }}
@@ -163,8 +162,8 @@ jobs:
                       -D LUE_DATA_MODEL_WITH_UTILITIES=TRUE \
                       -D LUE_FRAMEWORK_WITH_IMAGE_LAND=TRUE \
                       -D LUE_FRAMEWORK_WITH_PYTHON_API=TRUE \
-                      -D HPX_ROOT=${{ env.hpx_install_directory }} \
-                      -D MDSPAN_ROOT=${{ env.mdspan_install_directory }}
+                      -D MDSPAN_ROOT=${{ env.mdspan_install_directory }} \
+                      -D HPX_ROOT=${{ env.hpx_install_directory }}
 
         - name: build
           run: |
@@ -188,38 +187,47 @@ jobs:
               # Unit tests
               ctest --test-dir ${{ env.lue_build_directory }} --output-on-failure
 
-              # TODO See gh598
-
-              ### # Tests of runtime targets
-              ### # Add location of dependencies installed with Conan to the runtime environment
-              ### ${{ env.lue_build_directory }}/conanrun.bat
-
-              ### export PATH="${{ env.lue_runtime_install_directory }}/bin:$PATH"
-
-              ### ${{ env.lue_runtime_install_directory }}/bin/lue_translate --version
-              ### ${{ env.lue_runtime_install_directory }}/bin/lue_validate --version
-              ### ${{ env.lue_runtime_install_directory }}/bin/lue_view --version || echo "TODO: Error executing lue_view!"
-
-              ### # Add our package to the set of Conda packages
-              ### conda-develop ${{ env.lue_runtime_install_directory }}/lib/python${{ matrix.python_version }}
-              ### ${{ env.lue_runtime_install_directory }}/bin/lue_calculate --version
-              ### ${{ env.lue_runtime_install_directory }}/bin/lue_scalability --version
-              ### python -c "import lue, lue.data_model, lue.framework, lue.pcraster, lue.qa.scalability; print(lue.__version__)"
-
-              ### dumpbin //imports ${{ env.lue_runtime_install_directory }}/bin/lue_view.exe
-
-              ### # Test of imported CMake targets
-              ### git clone https://github.com/computationalgeography/lue_consume.git ${{ env.lue_consume_source_directory }}
-              ### cmake \
-              ###     -S ${{ env.lue_consume_source_directory }} \
-              ###     -B ${{ env.lue_consume_build_directory }} \
-              ###     -G "Ninja" \
-              ###     -D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
-              ###     -D CMAKE_BUILD_TYPE=Release \
-              ###     -D CMAKE_POLICY_DEFAULT_CMP0144=NEW \
-              ###     -D LUE_ROOT=${{ env.lue_development_install_directory }} \
-              ###     -D HPX_ROOT=${{ env.hpx_install_directory }} \
-              ###     -D MDSPAN_ROOT=${{ env.mdspan_install_directory }}
-              ### cmake --build ${{ env.lue_consume_build_directory }} --target all
-              ### ${{ env.lue_consume_build_directory }}/lue_consume_data_model
-              ### ${{ env.lue_consume_build_directory }}/lue_consume_framework
+              # Tests of runtime targets
+              # Add location of dependencies installed with Conan to the runtime environment
+              # Not needed yet.
+              # ${{ env.lue_build_directory }}/conanrun.bat
+
+              ${{ env.lue_runtime_install_directory }}/bin/lue_translate --version
+              ${{ env.lue_runtime_install_directory }}/bin/lue_validate --version
+              # This doesn't work due to missing Vulkan runtime
+              # ${{ env.lue_runtime_install_directory }}/bin/lue_view --version
+
+              # Add our package to the set of Conda packages
+              conda-develop ${{ env.lue_runtime_install_directory }}/lib/python${{ matrix.python_version }}
+
+              # NOTE: On Windows, locations in PATH are not used anymore by Python to lookup
+              #       dlls. Locations must be added using os.add_dll_directory(path)
+              #       We have added a slight hack to LUE's __init__.py to detect HPX' dll
+              #       directory in PATH. Otherwise HPX won't be found. See comment in that file.
+              #       Only needed on dev machines with custom HPX build, like we have here.
+              export PATH="`pwd`/${{ env.hpx_install_directory }}/bin:$PATH"
+
+              ${{ env.lue_runtime_install_directory }}/bin/lue_calculate --version
+              ${{ env.lue_runtime_install_directory }}/bin/lue_scalability --version
+              python -c "import lue, lue.data_model, lue.framework, lue.pcraster, lue.qa.scalability; print(lue.__version__)"
+
+        - name: consume
+          run: |
+              # Test of imported CMake targets
+              git clone https://github.com/computationalgeography/lue_consume.git ${{ env.lue_consume_source_directory }}
+
+              cmake \
+                  -S ${{ env.lue_consume_source_directory }} \
+                  -B ${{ env.lue_consume_build_directory }} \
+                  -G "Ninja" \
+                  -D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
+                  -D CMAKE_BUILD_TYPE=Release \
+                  -D CMAKE_POLICY_DEFAULT_CMP0144=NEW \
+                  -D LUE_ROOT=${{ env.lue_development_install_directory }} \
+                  -D HPX_ROOT=${{ env.hpx_install_directory }} \
+                  -D MDSPAN_ROOT=${{ env.mdspan_install_directory }}
+              cmake --build ${{ env.lue_consume_build_directory }} --target all
+
+              export PATH="${{ env.lue_development_install_directory }}/bin:${{ env.hpx_install_directory }}/bin:$PATH"
+              ${{ env.lue_consume_build_directory }}/lue_consume_data_model
+              ${{ env.lue_consume_build_directory }}/lue_consume_framework
diff --git a/environment/cmake/Lue.cmake b/environment/cmake/Lue.cmake
index e50c17987..6cb67216f 100644
--- a/environment/cmake/Lue.cmake
+++ b/environment/cmake/Lue.cmake
@@ -1,8 +1,3 @@
-if(UNIX AND (CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
-    set(CMAKE_CXX_VISIBILITY_PRESET hidden)
-    set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE)
-endif()
-
 set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
 set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
 
@@ -17,10 +12,14 @@ set(LUE_CXX_STANDARD 20)
 # Handle configuration and 3rd party libraries and tools, and ...
 include(LueConfiguration)
 
-# ... only now set language settings relevant for (only) our own targets
+# ... only now set settings relevant for (only) our own targets
 set(CMAKE_CXX_STANDARD ${LUE_CXX_STANDARD})
 set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
 set(CMAKE_CXX_EXTENSIONS FALSE)
+if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+    set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE)
+endif()
 
 include(LueMacro)
 
diff --git a/environment/cmake/LueConfiguration.cmake b/environment/cmake/LueConfiguration.cmake
index 3cfb61ef4..bca126533 100644
--- a/environment/cmake/LueConfiguration.cmake
+++ b/environment/cmake/LueConfiguration.cmake
@@ -33,18 +33,16 @@ option(LUE_DATA_MODEL_WITH_UTILITIES
     "Include data model command line utilities"
     FALSE)
 
+option(LUE_BUILD_GDAL
+    "Build LUE GDAL wrapper library"
+    TRUE)
+
 option(LUE_BUILD_FRAMEWORK
     "Build LUE simulation framework"
     TRUE)
-# option(LUE_FRAMEWORK_WITH_OPENCL
-#     "Include support for OpenCL"
-#     FALSE)
 # option(LUE_FRAMEWORK_WITH_MPI
 #     "Include support for MPI"
 #     FALSE)
-# option(LUE_FRAMEWORK_WITH_DASHBOARD
-#     "Include dashboard for simulation framework"
-#     FALSE)
 option(LUE_FRAMEWORK_WITH_PYTHON_API
     "Include Python API for modelling framework"
     FALSE)
@@ -124,9 +122,7 @@ set(LUE_VIEW_USE_VULKAN TRUE)
 # Handle internal dependencies -------------------------------------------------
 if(LUE_BUILD_FRAMEWORK)
     set(LUE_BUILD_DATA_MODEL TRUE)
-    # if(LUE_FRAMEWORK_WITH_DASHBOARD)
-    #     set(LUE_BUILD_IMGUI TRUE)
-    # endif()
+    set(LUE_BUILD_GDAL TRUE)
 endif()
 
 
@@ -140,6 +136,10 @@ if(LUE_BUILD_DATA_MODEL)
     if(LUE_DATA_MODEL_WITH_PYTHON_API)
         set(LUE_SPAN_LITE_REQUIRED TRUE)
     endif()
+
+    if(LUE_DATA_MODEL_WITH_UTILITIES)
+        set(LUE_BUILD_GDAL TRUE)
+    endif()
 endif()
 
 
@@ -212,14 +212,6 @@ if(LUE_BUILD_FRAMEWORK)
     #     set(LUE_PYTHON_REQUIRED TRUE)
     # endif()
 
-    # if(LUE_FRAMEWORK_WITH_OPENCL)
-    #     set(LUE_OPENCL_REQUIRED TRUE)
-    # endif()
-
-    # if(LUE_FRAMEWORK_WITH_DASHBOARD)
-    #     set(LUE_IMGUI_REQUIRED TRUE)
-    # endif()
-
     if(LUE_FRAMEWORK_WITH_PYTHON_API)
         set(LUE_PYBIND11_REQUIRED TRUE)
     endif()
@@ -297,6 +289,10 @@ endif()
 
 # ------------------------------------------------------------------------------
 if(LUE_PYTHON_REQUIRED)
+    # This is the first numpy version supporting Python 3.9
+    set(LUE_MIN_NUMPY_VERSION 1.19)
+    string(REPLACE "." "_" LUE_NPY_NO_DEPRECATED_API "NPY_${LUE_MIN_NUMPY_VERSION}_API_VERSION")
+
     # Order matters: Pybind11 must be searched for after Python has been found.
     find_package(Python 3.9 REQUIRED COMPONENTS Interpreter Development NumPy)
 
@@ -643,10 +639,6 @@ if(LUE_NLOHMANN_JSON_REQUIRED)
     FetchContent_MakeAvailable(nlohmann_json)
 endif()
 
-if(LUE_OPENCL_REQUIRED)
-    find_package(OpenCL REQUIRED)
-endif()
-
 if(LUE_SPAN_LITE_REQUIRED)
     FetchContent_Declare(span-lite
         GIT_REPOSITORY https://github.com/martinmoene/span-lite.git
diff --git a/environment/cmake/LueMacro.cmake b/environment/cmake/LueMacro.cmake
index 929333890..d69c2756b 100644
--- a/environment/cmake/LueMacro.cmake
+++ b/environment/cmake/LueMacro.cmake
@@ -1,132 +1,53 @@
-
-# Also configures the environment to point to the location of shared libs.
-# The idea of this is to keep the dev's shell as clean as possible. Use
-# ctest command to run unit tests.
-#
-# SCOPE: Some prefix. Often the lib name of the lib being tested
-# NAME : Name of test module, with extension
-# UTF_ARGUMENTS_SEPARATOR: String to put between the command and the
-#     UTF arguments.
-#     TODO: This is how it could work:
-#     <command> <runtime_arguments>
-#         <utf_arguments_separator> <utf_arguments>
-#         <command_arguments_separator> <command_arguments>
-#     HPX: utf_arguments_separator == '--'
-#     UTF: command_arguments_separator == '--'
-#         (so this separator doesn't have to be passed in!)
-# LINK_LIBRARIES: Libraries to link against
-# DEPENDENCIES: Targets this test target depends on
-# ENVIRONMENT: Environment variables that should be defined for running
-#     the test
-macro(add_unit_test)
-    set(OPTIONS "")
-    set(ONE_VALUE_ARGUMENTS SCOPE NAME UTF_ARGUMENTS_SEPARATOR)
-    set(MULTI_VALUE_ARGUMENTS
-        SUPPORT_NAMES
-        INCLUDE_DIRS
-        OBJECT_LIBRARIES
-        LINK_LIBRARIES
-        DEPENDENCIES
-        ENVIRONMENT
-    )
-
-    cmake_parse_arguments(ADD_UNIT_TEST "${OPTIONS}" "${ONE_VALUE_ARGUMENTS}"
-        "${MULTI_VALUE_ARGUMENTS}" ${ARGN})
-
-    if(ADD_UNIT_TEST_UNPARSED_ARGUMENTS)
-        message(FATAL_ERROR
-            "Macro called with unrecognized arguments: "
-            "${ADD_UNIT_TEST_UNPARSED_ARGUMENTS}"
-        )
+# Tests can be added conditionally. When the build is configured, the
+# LUE_BUILD_QA and LUE_QA_WITH_TESTS options can be set to TRUE or FALSE. Depending on
+# these settings tests are build or not.
+# DIRECTORY_NAME: Name of subdirectory containing the target.
+function(add_test_conditionally
+        DIRECTORY_NAME)
+    if(LUE_BUILD_QA AND LUE_QA_WITH_TESTS)
+        add_subdirectory(${DIRECTORY_NAME})
     endif()
+endfunction()
 
-    set(TEST_MODULE_NAME ${ADD_UNIT_TEST_NAME})
-    cmake_path(REMOVE_EXTENSION TEST_MODULE_NAME OUTPUT_VARIABLE TEST_MODULE_NAME_STEM)
-    set(TEST_EXE_NAME ${ADD_UNIT_TEST_SCOPE}_${TEST_MODULE_NAME_STEM})
-    string(REPLACE "/" "_" TEST_EXE_NAME ${TEST_EXE_NAME})
 
-    add_executable(${TEST_EXE_NAME} ${TEST_MODULE_NAME}
-        ${ADD_UNIT_TEST_SUPPORT_NAMES}
-        ${ADD_UNIT_TEST_OBJECT_LIBRARIES})
-    target_include_directories(${TEST_EXE_NAME}
-        PRIVATE
-            ${ADD_UNIT_TEST_INCLUDE_DIRS})
-    target_link_libraries(${TEST_EXE_NAME}
-        PRIVATE
-            ${ADD_UNIT_TEST_LINK_LIBRARIES}
-            Boost::unit_test_framework)
-
-    add_test(NAME ${TEST_EXE_NAME}
-        # catch_system_errors: Prevent UTF to detect system errors. This
-        #     messes things up when doing system calls to Python unit tests.
-        #     See also: http://lists.boost.org/boost-users/2009/12/55048.php
-        COMMAND ${TEST_EXE_NAME} ${ADD_UNIT_TEST_UTF_ARGUMENTS_SEPARATOR}
-            --catch_system_errors=no
-    )
+function(add_unit_tests)
+    set(prefix ARG)
+    set(no_values "")
+    set(single_values SCOPE)
+    set(multi_values NAMES LIBRARIES)
 
-    if(ADD_UNIT_TEST_DEPENDENCIES)
-        ADD_DEPENDENCIES(${TEST_EXE_NAME} ${ADD_UNIT_TEST_DEPENDENCIES})
-    endif()
+    cmake_parse_arguments(PARSE_ARGV 0 ${prefix} "${no_values}" "${single_values}" "${multi_values}")
 
-    set_tests_properties(${TEST_EXE_NAME}
-        PROPERTIES
-            ENVIRONMENT
-                "${ADD_UNIT_TEST_ENVIRONMENT}"
-    )
-endmacro()
+    if(${prefix}_UNPARSED_ARGUMENTS)
+        message(FATAL_ERROR
+            "Function called with unrecognized arguments: "
+            "${${prefix}_UNPARSED_ARGUMENTS}")
+    endif()
 
+    foreach(name ${ARG_NAMES})
+        set(module_name ${name}_test)
+        string(REPLACE "/" "_" test_name ${ARG_SCOPE}_${module_name})
 
-function(add_unit_tests)
-    set(OPTIONS "")
-    set(ONE_VALUE_ARGUMENTS SCOPE UTF_ARGUMENTS_SEPARATOR)
-    set(MULTI_VALUE_ARGUMENTS
-        NAMES
-        SUPPORT_NAMES
-        INCLUDE_DIRS
-        OBJECT_LIBRARIES
-        LINK_LIBRARIES
-        DEPENDENCIES
-        ENVIRONMENT
-    )
+        add_executable(${test_name} ${module_name}.cpp)
 
-    cmake_parse_arguments(ADD_UNIT_TESTS "${OPTIONS}" "${ONE_VALUE_ARGUMENTS}"
-        "${MULTI_VALUE_ARGUMENTS}" ${ARGN})
+        target_compile_definitions(${test_name}
+            PRIVATE
+                BOOST_TEST_DYN_LINK
+        )
 
-    if(ADD_UNIT_TESTS_UNPARSED_ARGUMENTS)
-        message(FATAL_ERROR
-            "Macro called with unrecognized arguments: "
-            "${ADD_UNIT_TESTS_UNPARSED_ARGUMENTS}"
+        target_link_libraries(${test_name}
+            PRIVATE
+                ${ARG_LIBRARIES}
+                Boost::unit_test_framework
         )
-    endif()
 
-    foreach(NAME ${ADD_UNIT_TESTS_NAMES})
-        add_unit_test(
-            SCOPE ${ADD_UNIT_TESTS_SCOPE}
-            NAME ${NAME}
-            UTF_ARGUMENTS_SEPARATOR ${ADD_UNIT_TESTS_UTF_ARGUMENTS_SEPARATOR}
-            SUPPORT_NAMES ${ADD_UNIT_TESTS_SUPPORT_NAMES}
-            INCLUDE_DIRS ${ADD_UNIT_TESTS_INCLUDE_DIRS}
-            OBJECT_LIBRARIES ${ADD_UNIT_TESTS_OBJECT_LIBRARIES}
-            LINK_LIBRARIES ${ADD_UNIT_TESTS_LINK_LIBRARIES}
-            DEPENDENCIES ${ADD_UNIT_TESTS_DEPENDENCIES}
-            ENVIRONMENT ${ADD_UNIT_TESTS_ENVIRONMENT}
+        add_test(NAME ${test_name}
+            COMMAND ${test_name}
         )
     endforeach()
 endfunction()
 
 
-# Tests can be added conditionally. When the build is configured, the
-# LUE_BUILD_QA and LUE_QA_WITH_TESTS options can be set to TRUE or FALSE. Depending on
-# these settings tests are build or not.
-# DIRECTORY_NAME: Name of subdirectory containing the target.
-function(add_test_conditionally
-        DIRECTORY_NAME)
-    if(LUE_BUILD_QA AND LUE_QA_WITH_TESTS)
-        add_subdirectory(${DIRECTORY_NAME})
-    endif()
-endfunction()
-
-
 # Copy Python test modules from current source directory to current binary
 # directory. For each module a custom command is created so editing a test
 # module in the source directory will trigger a copy to the binary directory.
@@ -291,90 +212,6 @@ function(lue_add_benchmark)
 endfunction()
 
 
-function(add_hpx_unit_test)
-    set(OPTIONS "")
-    set(ONE_VALUE_ARGUMENTS SCOPE NAME)
-    set(MULTI_VALUE_ARGUMENTS
-        LINK_LIBRARIES
-        DEPENDENCIES
-        ENVIRONMENT
-    )
-
-    cmake_parse_arguments(ADD_HPX_UNIT_TEST "${OPTIONS}" "${ONE_VALUE_ARGUMENTS}"
-        "${MULTI_VALUE_ARGUMENTS}" ${ARGN})
-
-    if(ADD_HPX_UNIT_TEST_UNPARSED_ARGUMENTS)
-        message(FATAL_ERROR
-            "Macro called with unrecognized arguments: "
-            "${ADD_HPX_UNIT_TEST_UNPARSED_ARGUMENTS}")
-    endif()
-
-    set(TEST_MODULE_NAME ${ADD_HPX_UNIT_TEST_NAME})
-    cmake_path(REMOVE_EXTENSION TEST_MODULE_NAME OUTPUT_VARIABLE TEST_MODULE_NAME_STEM)
-    set(TEST_EXE_NAME ${ADD_HPX_UNIT_TEST_SCOPE}_${TEST_MODULE_NAME_STEM})
-    string(REPLACE "/" "_" TEST_EXE_NAME ${TEST_EXE_NAME})
-
-    add_executable(${TEST_EXE_NAME} ${TEST_MODULE_NAME})
-
-    target_link_libraries(${TEST_EXE_NAME}
-        PRIVATE
-            ${ADD_HPX_UNIT_TEST_LINK_LIBRARIES}
-            Boost::unit_test_framework)
-
-    add_test(NAME ${TEST_EXE_NAME}
-        COMMAND
-            ${Python_EXECUTABLE} ${HPXRUN}
-                "--runwrapper" ${LUE_QA_TEST_HPX_RUNWRAPPER}
-                "--parcelport" ${LUE_QA_TEST_HPX_PARCELPORT}
-                "--localities" ${LUE_QA_TEST_NR_LOCALITIES_PER_TEST}
-                "--thread" ${LUE_QA_TEST_NR_THREADS_PER_LOCALITY} --
-                    "$<TARGET_FILE:${TEST_EXE_NAME}>")
-
-    if(ADD_HPX_UNIT_TEST_DEPENDENCIES)
-        ADD_DEPENDENCIES(${TEST_EXE_NAME} ${ADD_HPX_UNIT_TEST_DEPENDENCIES})
-    endif()
-
-    set_tests_properties(${TEST_EXE_NAME}
-        PROPERTIES
-            ENVIRONMENT
-                "${ADD_HPX_UNIT_TEST_ENVIRONMENT}"
-    )
-
-    hpx_setup_target(${TEST_EXE_NAME})
-endfunction()
-
-
-function(add_hpx_unit_tests)
-    set(OPTIONS "")
-    set(ONE_VALUE_ARGUMENTS SCOPE)
-    set(MULTI_VALUE_ARGUMENTS
-        NAMES
-        LINK_LIBRARIES
-        DEPENDENCIES
-        ENVIRONMENT
-    )
-
-    cmake_parse_arguments(ADD_HPX_UNIT_TESTS "${OPTIONS}" "${ONE_VALUE_ARGUMENTS}"
-        "${MULTI_VALUE_ARGUMENTS}" ${ARGN})
-
-    if(ADD_HPX_UNIT_TESTS_UNPARSED_ARGUMENTS)
-        message(FATAL_ERROR
-            "Macro called with unrecognized arguments: "
-            "${ADD_HPX_UNIT_TESTS_UNPARSED_ARGUMENTS}")
-    endif()
-
-    foreach(name ${ADD_HPX_UNIT_TESTS_NAMES})
-        add_hpx_unit_test(
-            SCOPE ${ADD_HPX_UNIT_TESTS_SCOPE}
-            NAME ${name}
-            LINK_LIBRARIES ${ADD_HPX_UNIT_TESTS_LINK_LIBRARIES}
-            DEPENDENCIES ${ADD_HPX_UNIT_TESTS_DEPENDENCIES}
-            ENVIRONMENT ${ADD_HPX_UNIT_TESTS_ENVIRONMENT}
-        )
-    endforeach()
-endfunction()
-
-
 function(lue_install_programs)
     set(options
     )
diff --git a/environment/conda/bld.bat b/environment/conda/bld.bat
index 324677a5b..1a21d2f43 100644
--- a/environment/conda/bld.bat
+++ b/environment/conda/bld.bat
@@ -39,6 +39,7 @@ set CMAKE_PREFIX_PATH=build
 cmake --preset conan-release ^
     %CMAKE_ARGS% ^
     -D CMAKE_INSTALL_LIBDIR=lib ^
+    -D CMAKE_POLICY_DEFAULT_CMP0144=NEW ^
     -D LUE_INSTALL_PYTHON_PACKAGE_DIR="%SP_DIR%/lue" ^
     -D LUE_DATA_MODEL_WITH_PYTHON_API=TRUE ^
     -D LUE_DATA_MODEL_WITH_UTILITIES=TRUE ^
diff --git a/environment/conda/build.sh b/environment/conda/build.sh
index 4c3427c6b..27b6add18 100644
--- a/environment/conda/build.sh
+++ b/environment/conda/build.sh
@@ -24,6 +24,7 @@ LUE_CONAN_PACKAGES="imgui" conan install . \
 CMAKE_PREFIX_PATH=build \
     cmake --preset conan-release \
         ${CMAKE_ARGS} \
+        -D CMAKE_POLICY_DEFAULT_CMP0144=NEW \
         -D LUE_INSTALL_PYTHON_PACKAGE_DIR="${SP_DIR}/lue" \
         -D LUE_DATA_MODEL_WITH_PYTHON_API=TRUE \
         -D LUE_DATA_MODEL_WITH_UTILITIES=TRUE \
diff --git a/environment/conda/meta.yaml b/environment/conda/meta.yaml
index ab5200c38..90e0fa4ff 100644
--- a/environment/conda/meta.yaml
+++ b/environment/conda/meta.yaml
@@ -35,7 +35,7 @@ requirements:
     # Dependencies required during build phase needed on the host.
     - python
     - numpy
-    - libboost-headers
+    - libboost-devel
     - hdf5
     - glfw
     - hpx
diff --git a/environment/configuration/requirements-dev.txt b/environment/configuration/requirements-dev.txt
index 955572e92..79652b0fd 100644
--- a/environment/configuration/requirements-dev.txt
+++ b/environment/configuration/requirements-dev.txt
@@ -4,6 +4,7 @@ docopt==0.6.2
 jinja2==3.1.3
 matplotlib==3.8.0
 numpy==1.26.1
+pre-commit==3.7.0
 pybind11==2.11.1
 ruamel.yaml==0.17.39
 sphinx==7.2.6
diff --git a/source/data_model/CMakeLists.txt b/source/data_model/CMakeLists.txt
index cb3561c7e..69125b6c8 100644
--- a/source/data_model/CMakeLists.txt
+++ b/source/data_model/CMakeLists.txt
@@ -58,10 +58,12 @@ if(LUE_DATA_MODEL_WITH_UTILITIES OR LUE_BUILD_VIEW)
     list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/utility)
 endif()
 
-if(LUE_DATA_MODEL_WITH_UTILITIES)
+if(LUE_BUILD_GDAL)
     add_subdirectory(gdal)
     list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/gdal)
+endif()
 
+if(LUE_DATA_MODEL_WITH_UTILITIES)
     add_subdirectory(translate)
     list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/translate)
 
diff --git a/source/data_model/gdal/src/data_type.cpp b/source/data_model/gdal/src/data_type.cpp
index a9b99e83f..382bfe877 100644
--- a/source/data_model/gdal/src/data_type.cpp
+++ b/source/data_model/gdal/src/data_type.cpp
@@ -1,4 +1,5 @@
 #include "lue/gdal/data_type.hpp"
+#include "lue/gdal/configure.hpp"
 #include <cassert>
 
 
diff --git a/source/data_model/python/CMakeLists.txt b/source/data_model/python/CMakeLists.txt
index e2cfda82d..49f779dd5 100644
--- a/source/data_model/python/CMakeLists.txt
+++ b/source/data_model/python/CMakeLists.txt
@@ -91,7 +91,7 @@ add_library(lue::py_data_model ALIAS lue_py_data_model)
 
 target_compile_definitions(lue_py_data_model
     PRIVATE
-        NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION
+        NPY_NO_DEPRECATED_API=${LUE_NPY_NO_DEPRECATED_API}
 )
 
 set_target_properties(lue_py_data_model
diff --git a/source/framework/CMakeLists.txt b/source/framework/CMakeLists.txt
index b982ca986..e895bff76 100644
--- a/source/framework/CMakeLists.txt
+++ b/source/framework/CMakeLists.txt
@@ -29,11 +29,6 @@ endif()
 add_subdirectory(model)
 list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/model)
 
-# if(LUE_FRAMEWORK_WITH_DASHBOARD)
-#     add_subdirectory(dashboard)
-#     list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/dashboard)
-# endif()
-
 # if(LUE_FRAMEWORK_WITH_BENCHMARKS)
 #     add_subdirectory(benchmark)
 #     list(APPEND doxygen_input ${CMAKE_CURRENT_SOURCE_DIR}/benchmark)
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/component/server/array_partition_io.hpp b/source/framework/algorithm/include/lue/framework/algorithm/component/server/array_partition_io.hpp
index 89be602c9..689e1294e 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/component/server/array_partition_io.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/component/server/array_partition_io.hpp
@@ -65,6 +65,15 @@ namespace lue::server {
             }
 
 
+            ~ArrayPartitionIO() = default;
+
+
+            auto operator=(ArrayPartitionIO const&) = delete;
+
+
+            auto operator=(ArrayPartitionIO&&) = delete;
+
+
             bool is_drained() const
             {
                 return _io.is_drained();
@@ -114,15 +123,20 @@ namespace lue::server {
             }
 
 
+        private:
+
+            friend class hpx::serialization::access;
+
+
             template<typename Archive>
             void serialize(Archive& archive, [[maybe_unused]] unsigned version)
             {
-                archive& _io;
+                // clang-format off
+                archive & _io;
+                // clang-format on
             }
 
 
-        private:
-
             Data _io;
 
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/detail/array_partition_io.hpp b/source/framework/algorithm/include/lue/framework/algorithm/detail/array_partition_io.hpp
index ceddfec53..55a895338 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/detail/array_partition_io.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/detail/array_partition_io.hpp
@@ -66,7 +66,10 @@ namespace lue::detail {
                 _partition_shape{},
                 _input_cells_idxs{},
                 _offsets{},
-                _values{}
+                _values{},
+                _input_cells_idxs_mutex{},
+                _offsets_mutex{},
+                _values_mutex{}
 
             {
                 std::fill(_partition_shape.begin(), _partition_shape.end(), 0);
@@ -80,7 +83,10 @@ namespace lue::detail {
                 _partition_shape{partition_shape},
                 _input_cells_idxs{input_cells_idxs},
                 _offsets{},
-                _values{}
+                _values{},
+                _input_cells_idxs_mutex{},
+                _offsets_mutex{},
+                _values_mutex{}
 
             {
                 assert_invariants();
@@ -117,6 +123,8 @@ namespace lue::detail {
             }
 
 
+            ~ArrayPartitionIO() = default;
+
             ArrayPartitionIO& operator=(ArrayPartitionIO const&) = delete;
 
             ArrayPartitionIO& operator=(ArrayPartitionIO&&) = delete;
@@ -413,32 +421,21 @@ namespace lue::detail {
             friend class hpx::serialization::access;
 
 
-            void serialize(
-                hpx::serialization::input_archive& archive, [[maybe_unused]] unsigned int const version)
+            template<typename Archive>
+            void serialize(Archive& archive, [[maybe_unused]] unsigned version)
             {
                 // std::scoped_lock lock{
                 //     _input_cells_idxs_mutex,
                 //     _offsets_mutex,
                 //     _values_mutex};
 
-                archive& _partition_shape& _input_cells_idxs& _offsets& _values;
-
                 assert_invariants();
-            }
 
-
-            void serialize(
-                hpx::serialization::output_archive& archive,
-                [[maybe_unused]] unsigned int const version) const
-            {
-                // std::scoped_lock lock{
-                //     _input_cells_idxs_mutex,
-                //     _offsets_mutex,
-                //     _values_mutex};
+                // clang-format off
+                archive & _partition_shape & _input_cells_idxs & _offsets & _values;
+                // clang-format on
 
                 assert_invariants();
-
-                archive& _partition_shape& _input_cells_idxs& _offsets& _values;
             }
 
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/policy/detect_no_data_by_value.hpp b/source/framework/algorithm/include/lue/framework/algorithm/policy/detect_no_data_by_value.hpp
index 2807722f9..c7d3f333b 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/policy/detect_no_data_by_value.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/policy/detect_no_data_by_value.hpp
@@ -101,7 +101,9 @@ namespace lue::policy {
             template<typename Archive>
             void serialize(Archive& archive, [[maybe_unused]] unsigned int const version)
             {
-                archive& _value;
+                // clang-format off
+                archive & _value;
+                // clang-format on
             }
 
 
diff --git a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
index 5b459c375..125a9cef0 100644
--- a/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
+++ b/source/framework/algorithm/include/lue/framework/algorithm/value_policies/cast.hpp
@@ -114,7 +114,7 @@ namespace lue {
                         // float -> int / unsigned int
                         return argument >= InputElement{std::numeric_limits<OutputElement>::min()} &&
                                argument <=
-                                   static_cast<OutputElement>(std::numeric_limits<OutputElement>::max());
+                                   static_cast<InputElement>(std::numeric_limits<OutputElement>::max());
                     }
 
                     return true;
diff --git a/source/framework/core/include/lue/framework/core/numa_domain.hpp b/source/framework/core/include/lue/framework/core/numa_domain.hpp
index 3d9193469..8b2033054 100644
--- a/source/framework/core/include/lue/framework/core/numa_domain.hpp
+++ b/source/framework/core/include/lue/framework/core/numa_domain.hpp
@@ -1,7 +1,7 @@
 #pragma once
 #include "lue/framework/core/assert.hpp"
 #include "lue/framework/core/define.hpp"
-#include <hpx/include/compute.hpp>
+#include <hpx/compute.hpp>
 
 
 namespace lue {
diff --git a/source/framework/dashboard/CMakeLists.txt b/source/framework/dashboard/CMakeLists.txt
deleted file mode 100644
index 64409e068..000000000
--- a/source/framework/dashboard/CMakeLists.txt
+++ /dev/null
@@ -1,1 +0,0 @@
-# add_subdirectory(imgui)
diff --git a/source/framework/image_land/python/CMakeLists.txt b/source/framework/image_land/python/CMakeLists.txt
index b21aee511..80f382aa4 100644
--- a/source/framework/image_land/python/CMakeLists.txt
+++ b/source/framework/image_land/python/CMakeLists.txt
@@ -21,7 +21,7 @@ add_library(lue::py_image_land ALIAS lue_py_image_land)
 
 target_compile_definitions(lue_py_image_land
     PRIVATE
-        NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION
+        NPY_NO_DEPRECATED_API=${LUE_NPY_NO_DEPRECATED_API}
 )
 
 set_target_properties(lue_py_image_land
diff --git a/source/framework/model/CMakeLists.txt b/source/framework/model/CMakeLists.txt
index eb37d0c29..3d0cea8ea 100644
--- a/source/framework/model/CMakeLists.txt
+++ b/source/framework/model/CMakeLists.txt
@@ -7,12 +7,6 @@ add_library(lue_framework_model
 
 add_library(lue::framework_model ALIAS lue_framework_model)
 
-hpx_setup_target(lue_framework_model
-    TYPE LIBRARY
-    COMPONENT_DEPENDENCIES
-        iostreams
-)
-
 target_include_directories(lue_framework_model
     PUBLIC
         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
diff --git a/source/framework/partitioned_array/include/lue/framework/partitioned_array/array_partition.hpp b/source/framework/partitioned_array/include/lue/framework/partitioned_array/array_partition.hpp
index e1489ffcf..980f1bb6a 100644
--- a/source/framework/partitioned_array/include/lue/framework/partitioned_array/array_partition.hpp
+++ b/source/framework/partitioned_array/include/lue/framework/partitioned_array/array_partition.hpp
@@ -1,5 +1,4 @@
 #pragma once
-#include "lue/framework/partitioned_array/export.hpp"
 #include "lue/framework/partitioned_array/server/array_partition.hpp"
 
 
diff --git a/source/framework/partitioned_array/include/lue/framework/partitioned_array/server/array_partition.hpp b/source/framework/partitioned_array/include/lue/framework/partitioned_array/server/array_partition.hpp
index d2e3bd393..3116d8213 100644
--- a/source/framework/partitioned_array/include/lue/framework/partitioned_array/server/array_partition.hpp
+++ b/source/framework/partitioned_array/include/lue/framework/partitioned_array/server/array_partition.hpp
@@ -1,6 +1,7 @@
 #pragma once
 #include "lue/framework/core/offset.hpp"
 #include "lue/framework/partitioned_array/array_partition_data.hpp"
+#include "lue/framework/partitioned_array/export.hpp"
 #include <hpx/config.hpp>
 #include <hpx/include/components.hpp>
 
@@ -11,8 +12,7 @@ namespace lue::server {
         @brief      Component server class for partioned array partitions
     */
     template<typename Element, Rank rank>
-    class HPX_COMPONENT_EXPORT ArrayPartition:
-        public hpx::components::component_base<ArrayPartition<Element, rank>>
+    class LUE_FPA_EXPORT ArrayPartition: public hpx::components::component_base<ArrayPartition<Element, rank>>
     {
 
         private:
diff --git a/source/framework/partitioned_route/include/lue/framework/partitioned_route/serial_route_fragment.hpp b/source/framework/partitioned_route/include/lue/framework/partitioned_route/serial_route_fragment.hpp
index 9865efb49..b21f8e4c2 100644
--- a/source/framework/partitioned_route/include/lue/framework/partitioned_route/serial_route_fragment.hpp
+++ b/source/framework/partitioned_route/include/lue/framework/partitioned_route/serial_route_fragment.hpp
@@ -1,6 +1,7 @@
 #pragma once
 #include "lue/framework/core/assert.hpp"
 #include "lue/framework/core/indices.hpp"
+#include "lue/framework/partitioned_route/export.hpp"
 #include <hpx/runtime_distributed.hpp>
 #include <algorithm>
 #include <optional>
@@ -21,7 +22,7 @@ namespace lue {
         fragment is a piece of a route whose cell indxs are all located in a single partition.
     */
     template<Rank rank>
-    class SerialRouteFragment
+    class /* LUE_FPR_EXPORT */ SerialRouteFragment
     {
         public:
 
diff --git a/source/framework/partitioned_route/include/lue/framework/partitioned_route/server/serial_route_partition.hpp b/source/framework/partitioned_route/include/lue/framework/partitioned_route/server/serial_route_partition.hpp
index 08a7fe8cc..a02ef80b7 100644
--- a/source/framework/partitioned_route/include/lue/framework/partitioned_route/server/serial_route_partition.hpp
+++ b/source/framework/partitioned_route/include/lue/framework/partitioned_route/server/serial_route_partition.hpp
@@ -1,6 +1,7 @@
 #pragma once
 #include "lue/framework/core/offset.hpp"
 #include "lue/framework/core/shape.hpp"
+#include "lue/framework/partitioned_route/export.hpp"
 #include "lue/framework/partitioned_route/serial_route_fragment.hpp"
 #include "lue/framework/partitioned_route/serialize/serial_route_fragment.hpp"
 #include "lue/framework/route/define.hpp"
@@ -16,16 +17,14 @@ namespace lue::server {
         @brief      Component server class for serial route partitions
     */
     template<typename RouteID, Rank rank>
-    class HPX_COMPONENT_EXPORT SerialRoutePartition:
+    class LUE_FPR_EXPORT SerialRoutePartition:
         public hpx::components::component_base<SerialRoutePartition<RouteID, rank>>
     {
 
-        private:
+        public:
 
             using Base = hpx::components::component_base<SerialRoutePartition<RouteID, rank>>;
 
-        public:
-
             using RouteFragment = SerialRouteFragment<rank>;
 
             using RouteFragments = std::unordered_map<RouteID, std::vector<RouteFragment>>;
@@ -103,7 +102,7 @@ namespace lue::server {
 #define LUE_REGISTER_SERIAL_ROUTE_PARTITION_ACTION_DECLARATIONS(RouteID, rank, unique)                       \
                                                                                                              \
     namespace lue::detail {                                                                                  \
-        using SerialRoutePartitionServer_##unique = lue::server::SerialRoutePartition<RouteID, rank>;        \
+        using SerialRoutePartitionServer_##unique = server::SerialRoutePartition<RouteID, rank>;        \
     }                                                                                                        \
                                                                                                              \
     HPX_REGISTER_ACTION_DECLARATION(                                                                         \
@@ -139,7 +138,7 @@ namespace lue::server {
                                                                                                              \
     namespace lue::detail {                                                                                  \
         using SerialRoutePartitionServerComponent_##unique =                                                 \
-            hpx::components::component<lue::detail::SerialRoutePartitionServer_##unique>;                    \
+            hpx::components::component<SerialRoutePartitionServer_##unique>;                    \
     }                                                                                                        \
                                                                                                              \
     HPX_REGISTER_COMPONENT(                                                                                  \
diff --git a/source/framework/partitioned_route/include/lue/framework/serial_route.hpp b/source/framework/partitioned_route/include/lue/framework/serial_route.hpp
index eeb013be6..19ebfd31c 100644
--- a/source/framework/partitioned_route/include/lue/framework/serial_route.hpp
+++ b/source/framework/partitioned_route/include/lue/framework/serial_route.hpp
@@ -1,5 +1,6 @@
 #pragma once
 #include "lue/framework/core/array.hpp"
+#include "lue/framework/partitioned_route/export.hpp"
 #include "lue/framework/partitioned_route/serial_route_partition.hpp"
 
 
diff --git a/source/framework/python/CMakeLists.txt b/source/framework/python/CMakeLists.txt
index 260dd308f..2d98f386b 100644
--- a/source/framework/python/CMakeLists.txt
+++ b/source/framework/python/CMakeLists.txt
@@ -153,16 +153,11 @@ add_library(lue_py_framework SHARED
     src/submodule.cpp
 )
 
-# if(LUE_FRAMEWORK_WITH_DASHBOARD)
-#     list(APPEND sources
-#        src/dashboard/dashboard.cpp)
-# endif()
-
 add_library(lue::py_framework ALIAS lue_py_framework)
 
 target_compile_definitions(lue_py_framework
     PRIVATE
-        NPY_NO_DEPRECATED_API=NPY_1_7_API_VERSION
+        NPY_NO_DEPRECATED_API=${LUE_NPY_NO_DEPRECATED_API}
 )
 
 set_target_properties(lue_py_framework
diff --git a/source/python/lue.py.in b/source/python/lue.py.in
index 137353f0f..7344121c3 100644
--- a/source/python/lue.py.in
+++ b/source/python/lue.py.in
@@ -20,6 +20,19 @@ if sys.platform == "win32":
             # All seems to be as expected. LUE DLLs should be stored here.
             os.add_dll_directory(bin_directory_pathname)
 
+        # This is somewhat a hack. Since Python 3.8, PATH is not searched anymore for locations
+        # from which to load dlls. Such locations need to be added using os.add_dll_directory.
+        # In one circumstance we want to add a special location before importing LUE. This
+        # is in our development environment, where HPX is built by ourselves and installed in a
+        # non-standard location. Here, we dectect whether this location has been added to the
+        # PATH, and if so, add this location to Python's search path. In 99.9% of the cases
+        # this is not needed.
+        # This tweak can be removed once we have access to a Conda development package of HPX,
+        # besides a runtime package.
+        for path in os.environ["PATH"].split(";"):
+            if "hpx" in path:
+                os.add_dll_directory(path)
+
 
 from .lue_py import *
 from .lue_py import __version__
diff --git a/source/shared/include/lue/configure.hpp.in b/source/shared/include/lue/configure.hpp.in
index 643b8de1e..e205358fb 100644
--- a/source/shared/include/lue/configure.hpp.in
+++ b/source/shared/include/lue/configure.hpp.in
@@ -5,7 +5,6 @@
 #cmakedefine LUE_DATA_MODEL_WITH_PYTHON_API
 
 #cmakedefine LUE_BUILD_FRAMEWORK
-#cmakedefine LUE_FRAMEWORK_WITH_OPENCL
 #cmakedefine LUE_FRAMEWORK_WITH_PYTHON_API
 #cmakedefine LUE_FRAMEWORK_WITH_IMAGE_LAND
 
diff --git a/source/view/view/CMakeLists.txt b/source/view/view/CMakeLists.txt
index fde754ce9..59cb04e98 100644
--- a/source/view/view/CMakeLists.txt
+++ b/source/view/view/CMakeLists.txt
@@ -28,7 +28,6 @@ target_link_libraries(lue_view
     PRIVATE
         lue::imgui
         lue::utility
-        lue::shared
 )
 
 lue_install_executables(


Test patch:
diff --git a/source/data_model/cxx/test/CMakeLists.txt b/source/data_model/cxx/test/CMakeLists.txt
index 6548c7cbc..fab032b3c 100644
--- a/source/data_model/cxx/test/CMakeLists.txt
+++ b/source/data_model/cxx/test/CMakeLists.txt
@@ -1,54 +1,55 @@
+set(names
+    core/time/clock
+    core/time/duration
+    core/time/tick_period
+    core/time/time_point
+
+    array/same_shape/value
+    array/same_shape/constant_shape/value
+    array/same_shape/variable_shape/value
+
+    array/different_shape/value
+    array/different_shape/constant_shape/value
+    array/different_shape/variable_shape/value
+
+    info/identity/object_id
+    info/identity/active_object_id
+    info/identity/active_set_index
+    info/identity/active_object_index
+
+    info/time/time_box
+    info/time/time_cell
+    info/time/time_point
+
+    info/space/mobile_space_point
+    info/space/stationary_space_point
+    info/space/mobile_space_box
+    info/space/stationary_space_box
+
+    info/property/same_shape/property
+    info/property/same_shape/constant_shape/property
+    info/property/same_shape/variable_shape/property
+
+    info/property/different_shape/property
+    info/property/different_shape/constant_shape/property
+    info/property/different_shape/variable_shape/property
+
+    object/dataset
+    object/presence_in_time
+    object/property/properties
+    object/property/property_set
+    object/space_domain
+    object/time_domain
+
+    scalar
+    raster
+    time_series_1
+    time_series_2
+)
+
 add_unit_tests(
     SCOPE lue_cxx
-    NAMES
-
-        core/time/clock_test.cpp
-        core/time/duration_test.cpp
-        core/time/tick_period_test.cpp
-        core/time/time_point_test.cpp
-
-        array/same_shape/value_test.cpp
-        array/same_shape/constant_shape/value_test.cpp
-        array/same_shape/variable_shape/value_test.cpp
-
-        array/different_shape/value_test.cpp
-        array/different_shape/constant_shape/value_test.cpp
-        array/different_shape/variable_shape/value_test.cpp
-
-        info/identity/object_id_test.cpp
-        info/identity/active_object_id_test.cpp
-        info/identity/active_set_index_test.cpp
-        info/identity/active_object_index_test.cpp
-
-        info/time/time_box_test.cpp
-        info/time/time_cell_test.cpp
-        info/time/time_point_test.cpp
-
-        info/space/mobile_space_point_test.cpp
-        info/space/stationary_space_point_test.cpp
-        info/space/mobile_space_box_test.cpp
-        info/space/stationary_space_box_test.cpp
-
-        info/property/same_shape/property_test.cpp
-        info/property/same_shape/constant_shape/property_test.cpp
-        info/property/same_shape/variable_shape/property_test.cpp
-
-        info/property/different_shape/property_test.cpp
-        info/property/different_shape/constant_shape/property_test.cpp
-        info/property/different_shape/variable_shape/property_test.cpp
-
-        object/dataset_test.cpp
-        object/presence_in_time_test.cpp
-        object/property/properties_test.cpp
-        object/property/property_set_test.cpp
-        object/space_domain_test.cpp
-        object/time_domain_test.cpp
-
-        scalar_test.cpp
-        raster_test.cpp
-        time_series_test-1.cpp
-        time_series_test-2.cpp
-
-    LINK_LIBRARIES
+    NAMES ${names}
+    LIBRARIES
         lue::data_model_test
 )
diff --git a/source/data_model/cxx/test/time_series_test-1.cpp b/source/data_model/cxx/test/time_series_1_test.cpp
similarity index 100%
rename from source/data_model/cxx/test/time_series_test-1.cpp
rename to source/data_model/cxx/test/time_series_1_test.cpp
diff --git a/source/data_model/cxx/test/time_series_test-2.cpp b/source/data_model/cxx/test/time_series_2_test.cpp
similarity index 100%
rename from source/data_model/cxx/test/time_series_test-2.cpp
rename to source/data_model/cxx/test/time_series_2_test.cpp
diff --git a/source/data_model/gdal/test/CMakeLists.txt b/source/data_model/gdal/test/CMakeLists.txt
index 0c3091c87..408dbe177 100644
--- a/source/data_model/gdal/test/CMakeLists.txt
+++ b/source/data_model/gdal/test/CMakeLists.txt
@@ -1,29 +1,16 @@
-set(scope lue_gdal)
-
 set(names
-    blocks_test
-    dataset_test
-    driver_test
-    raster_test
-    raster_band_test
-    type_traits_test
-    version_test
+    blocks
+    dataset
+    driver
+    raster
+    raster_band
+    type_traits
+    version
+)
+add_unit_tests(
+    SCOPE lue_gdal
+    NAMES ${names}
+    LIBRARIES
+        lue::gdal
+        lue::shared
 )
-
-foreach(name ${names})
-
-    set(test_name ${scope}_${name})
-
-    add_executable(${test_name} ${name}.cpp)
-
-    target_link_libraries(${test_name}
-        PRIVATE
-            lue::gdal
-            lue::shared
-            Boost::unit_test_framework
-    )
-
-    add_test(NAME ${test_name}
-        COMMAND ${test_name}
-    )
-endforeach()
diff --git a/source/data_model/gdal/test/dataset_test.cpp b/source/data_model/gdal/test/dataset_test.cpp
index 332959c12..51c3b36fe 100644
--- a/source/data_model/gdal/test/dataset_test.cpp
+++ b/source/data_model/gdal/test/dataset_test.cpp
@@ -79,28 +79,28 @@ BOOST_AUTO_TEST_CASE(open_dataset)
     BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly), std::runtime_error);
 
 
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
 
     lgd::create_dataset(driver_name, dataset_name, raster_shape, nr_bands, data_type);
 
     // File exists but is not readable and not writable
     std::filesystem::permissions(dataset_name, std::filesystem::perms::none);
 #ifndef _WIN32  // TODO
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly), std::runtime_error);
 #endif
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
 
     // File exists but is write-only: not readable
     std::filesystem::permissions(dataset_name, std::filesystem::perms::owner_write);
 #ifndef _WIN32  // TODO
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly), std::runtime_error);
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
 #endif
 
     // File exists and is read-only: not writable
     std::filesystem::permissions(dataset_name, std::filesystem::perms::owner_read);
     BOOST_CHECK_NO_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_ReadOnly));
-    BOOST_CHECK_THROW(!lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
+    BOOST_CHECK_THROW(lgd::open_dataset(dataset_name, GDALAccess::GA_Update), std::runtime_error);
 
     // File exists and is readable and writable
     std::filesystem::permissions(
diff --git a/source/data_model/hdf5/test/CMakeLists.txt b/source/data_model/hdf5/test/CMakeLists.txt
index 1b609a428..251169f89 100644
--- a/source/data_model/hdf5/test/CMakeLists.txt
+++ b/source/data_model/hdf5/test/CMakeLists.txt
@@ -1,15 +1,18 @@
+set(names
+    attribute
+    chunk
+    dataset
+    datatype
+    file
+    group
+    hyperslab
+    identifier
+    shape
+)
+
 add_unit_tests(
     SCOPE lue_hdf5
-    NAMES
-        attribute_test.cpp
-        chunk_test.cpp
-        dataset_test.cpp
-        datatype_test.cpp
-        file_test.cpp
-        group_test.cpp
-        hyperslab_test.cpp
-        identifier_test.cpp
-        shape_test.cpp
-    LINK_LIBRARIES
+    NAMES ${names}
+    LIBRARIES
         lue::hdf5
 )
diff --git a/source/data_model/hl/test/CMakeLists.txt b/source/data_model/hl/test/CMakeLists.txt
index 7eb8d7f7c..1d36fa79b 100644
--- a/source/data_model/hl/test/CMakeLists.txt
+++ b/source/data_model/hl/test/CMakeLists.txt
@@ -1,8 +1,11 @@
+set(names
+    raster_view
+)
+
 add_unit_tests(
     SCOPE lue_data_model_hl
-    NAMES
-        raster_view_test.cpp
-    LINK_LIBRARIES
+    NAMES ${names}
+    LIBRARIES
         lue::data_model_hl
         lue::data_model_test
 )
diff --git a/source/data_model/translate/test/CMakeLists.txt b/source/data_model/translate/test/CMakeLists.txt
index 0dfd87795..1c1802284 100644
--- a/source/data_model/translate/test/CMakeLists.txt
+++ b/source/data_model/translate/test/CMakeLists.txt
@@ -1,9 +1,12 @@
+set(names
+    import
+    stack_name
+)
+
 add_unit_tests(
     SCOPE lue_translate
-    NAMES
-        import_test.cpp
-        stack_name_test.cpp
-    LINK_LIBRARIES
+    NAMES ${names}
+    LIBRARIES
         lue::translate
         lue::data_model_test
 )
diff --git a/source/data_model/utility/test/CMakeLists.txt b/source/data_model/utility/test/CMakeLists.txt
index 88cc3f6eb..95787c18b 100644
--- a/source/data_model/utility/test/CMakeLists.txt
+++ b/source/data_model/utility/test/CMakeLists.txt
@@ -1,7 +1,11 @@
+set(scope lue_utility)
+set(names
+    environment
+)
+
 add_unit_tests(
     SCOPE lue_utility
-    NAMES
-        environment_test.cpp
-    LINK_LIBRARIES
+    NAMES ${names}
+    LIBRARIES
         lue::utility
 )
diff --git a/source/framework/algorithm/test/CMakeLists.txt b/source/framework/algorithm/test/CMakeLists.txt
index f510e20dc..8410d3c82 100644
--- a/source/framework/algorithm/test/CMakeLists.txt
+++ b/source/framework/algorithm/test/CMakeLists.txt
@@ -9,7 +9,6 @@ target_link_libraries(lue_framework_algorithm_test
 )
 
 set(scope lue_framework_algorithm)
-
 set(focal_operation_names
     aspect
     focal_diversity
@@ -124,12 +123,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue_framework_algorithm_test
@@ -207,12 +210,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue_framework_algorithm_test
diff --git a/source/framework/algorithm/test/cast_test.cpp b/source/framework/algorithm/test/cast_test.cpp
index ff66f5186..f50508a4b 100644
--- a/source/framework/algorithm/test/cast_test.cpp
+++ b/source/framework/algorithm/test/cast_test.cpp
@@ -767,9 +767,9 @@ BOOST_AUTO_TEST_CASE(signed_integer_to_floating_point)
                 // clang-format on
             }});
 
-        OutputElement const output_min(input_min);
-        OutputElement const output_max(input_max);
-        OutputElement const output_lowest(input_lowest);
+        OutputElement const output_min{static_cast<OutputElement>(input_min)};
+        OutputElement const output_max{static_cast<OutputElement>(input_max)};
+        OutputElement const output_lowest{static_cast<OutputElement>(input_lowest)};
         OutputElement const output_no_data{lue::policy::no_data_value<OutputElement>};
 
         auto const array_we_want =
@@ -821,7 +821,7 @@ BOOST_AUTO_TEST_CASE(unsigned_integer_to_floating_point)
                 // clang-format on
             }});
 
-        OutputElement const output_max(input_max);
+        OutputElement const output_max{static_cast<OutputElement>(input_max)};
         OutputElement const output_no_data{lue::policy::no_data_value<OutputElement>};
 
         auto const array_we_want =
diff --git a/source/framework/core/test/CMakeLists.txt b/source/framework/core/test/CMakeLists.txt
index 6dabb696e..96ae8c39d 100644
--- a/source/framework/core/test/CMakeLists.txt
+++ b/source/framework/core/test/CMakeLists.txt
@@ -1,26 +1,30 @@
 set(scope lue_framework_core)
 set(names
-    array_test
-    array_visitor_test
-    configuration_entry_test
-    domain_decomposition_test
-    hilbert_curve_test
-    index_util_test
-    linear_curve_test
-    math_test
-    shape_test
-    span_test
+    array
+    array_visitor
+    configuration_entry
+    domain_decomposition
+    hilbert_curve
+    index_util
+    linear_curve
+    math
+    shape
+    span
 )
 
 foreach(name ${names})
+    set(module_name ${name}_test)
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
-    set(test_name ${scope}_${name})
+    add_executable(${test_name} ${module_name}.cpp)
 
-    add_executable(${test_name} ${name}.cpp)
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
 
     target_link_libraries(${test_name}
         PRIVATE
-            lue::framework_core
             lue::framework_test
             Boost::unit_test_framework
     )
diff --git a/source/framework/image_land/test/CMakeLists.txt b/source/framework/image_land/test/CMakeLists.txt
index e8a3f5313..2a36b1d6f 100644
--- a/source/framework/image_land/test/CMakeLists.txt
+++ b/source/framework/image_land/test/CMakeLists.txt
@@ -6,12 +6,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::image_land
diff --git a/source/framework/io/test/CMakeLists.txt b/source/framework/io/test/CMakeLists.txt
index d38f46285..e889ab1ed 100644
--- a/source/framework/io/test/CMakeLists.txt
+++ b/source/framework/io/test/CMakeLists.txt
@@ -1,17 +1,20 @@
 set(scope lue_framework_io)
-
 set(names
     raster
     write
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_io
diff --git a/source/framework/model/test/CMakeLists.txt b/source/framework/model/test/CMakeLists.txt
index bd8fe4711..5163c69a7 100644
--- a/source/framework/model/test/CMakeLists.txt
+++ b/source/framework/model/test/CMakeLists.txt
@@ -4,12 +4,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_model
@@ -38,12 +42,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_model
diff --git a/source/framework/partitioned_array/test/CMakeLists.txt b/source/framework/partitioned_array/test/CMakeLists.txt
index 8c19b6afc..32229a2f6 100644
--- a/source/framework/partitioned_array/test/CMakeLists.txt
+++ b/source/framework/partitioned_array/test/CMakeLists.txt
@@ -5,15 +5,18 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
-            lue::framework_core
             lue::framework_test
             Boost::unit_test_framework
     )
@@ -41,12 +44,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_partitioned_array
diff --git a/source/framework/partitioned_route/test/CMakeLists.txt b/source/framework/partitioned_route/test/CMakeLists.txt
index 03a201e03..b9ab2a496 100644
--- a/source/framework/partitioned_route/test/CMakeLists.txt
+++ b/source/framework/partitioned_route/test/CMakeLists.txt
@@ -1,16 +1,19 @@
 set(scope lue_framework_partitioned_route)
-
 set(names
     serial_route_fragment
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_partitioned_route
@@ -41,12 +44,16 @@ set(names
 )
 
 foreach(name ${names})
-
     set(module_name ${name}_test)
-    set(test_name ${scope}_${module_name})
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
 
     add_executable(${test_name} ${module_name}.cpp)
 
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
     target_link_libraries(${test_name}
         PRIVATE
             lue::framework_partitioned_route
diff --git a/source/framework/partitioned_route/test/serial_route_partition_test.cpp b/source/framework/partitioned_route/test/serial_route_partition_test.cpp
index edad79d44..19a2c5286 100644
--- a/source/framework/partitioned_route/test/serial_route_partition_test.cpp
+++ b/source/framework/partitioned_route/test/serial_route_partition_test.cpp
@@ -1,7 +1,7 @@
 #define BOOST_TEST_MODULE lue framework partitioned_route serial_route_partition
-#include "stream.hpp"
 #include "lue/framework/partitioned_route/serial_route_partition.hpp"
 #include "lue/framework/test/hpx_unit_test.hpp"
+#include "stream.hpp"
 
 
 BOOST_AUTO_TEST_CASE(default_construct_client)
diff --git a/source/framework/partitioned_route/test/serial_route_test.cpp b/source/framework/partitioned_route/test/serial_route_test.cpp
index 2d043089b..2e4807d7e 100644
--- a/source/framework/partitioned_route/test/serial_route_test.cpp
+++ b/source/framework/partitioned_route/test/serial_route_test.cpp
@@ -1,4 +1,4 @@
-#define BOOST_TEST_MODULE lue framework partitioned_route partitioned_serial_route
+#define BOOST_TEST_MODULE lue framework partitioned_route serial_route
 #include "lue/framework/serial_route.hpp"
 #include "lue/framework/test/hpx_unit_test.hpp"
 #include "lue/stream.hpp"
diff --git a/source/shared/test/CMakeLists.txt b/source/shared/test/CMakeLists.txt
index 7aac6b280..c0747cd54 100644
--- a/source/shared/test/CMakeLists.txt
+++ b/source/shared/test/CMakeLists.txt
@@ -1,10 +1,26 @@
+set(scope lue_shared)
 set(names
-    no_data_test.cpp
+    no_data
 )
 
-add_unit_tests(
-    SCOPE lue_shared
-    NAMES ${names}
-    LINK_LIBRARIES
-        lue::shared
-)
+foreach(name ${names})
+    set(module_name ${name}_test)
+    string(REPLACE "/" "_" test_name ${scope}_${module_name})
+
+    add_executable(${test_name} ${module_name}.cpp)
+
+    target_compile_definitions(${test_name}
+        PRIVATE
+            BOOST_TEST_DYN_LINK
+    )
+
+    target_link_libraries(${test_name}
+        PRIVATE
+            lue::shared
+            Boost::unit_test_framework
+    )
+
+    add_test(NAME ${test_name}
+        COMMAND ${test_name}
+    )
+endforeach()