diff --git a/.github/workflows/cmake-build.yml b/.github/workflows/cmake-build.yml new file mode 100644 index 0000000000..cab24a5701 --- /dev/null +++ b/.github/workflows/cmake-build.yml @@ -0,0 +1,253 @@ +name: cmake-build +on: + push: + branches: + - master + pull_request: + branches: + - master + workflow_dispatch: + +defaults: + run: + shell: bash + +jobs: + linux-build: + strategy: + matrix: + image: [ + "conanio/gcc11-ubuntu16.04", + "conanio/clang13-ubuntu16.04" + ] + libcxx: [libstdc++11, libc++] + shared: [shared, static] + boost: [boost, stdfs] + mpi: [mpi, serial] + exclude: + - image: conanio/gcc11-ubuntu16.04 + libcxx: libc++ + include: + - image: conanio/gcc11-ubuntu16.04 + profile: gcc11 + - image: conanio/clang13-ubuntu16.04 + libcxx: libstdc++11 + profile: clang13-libstdc++ + - image: conanio/clang13-ubuntu16.04 + libcxx: libc++ + profile: clang13-libc++ + runs-on: ubuntu-20.04 + container: + image: ${{ matrix.image }} + options: '--user=root' + steps: + - uses: actions/checkout@v2 + - name: Set environment variables + run: | + bash .github/workflows/set_env_vars.sh \ + ${{ matrix.shared }} \ + ${{ matrix.boost }} \ + ${{ matrix.mpi }} + - name: Install MPI prerequisites + if: ${{ matrix.mpi == 'mpi' }} + run: | + apt-get update + apt-get install -y --no-install-recommends ssh + - name: Install and configure conan + run: | + CONAN_ARGS="--profile .github/workflows/conan/profiles/${{ matrix.profile }} \ + -o with_boost=${H5CPP_WITH_BOOST} \ + -o with_mpi=${H5CPP_WITH_MPI} \ + -o shared=${H5CPP_SHARED} \ + -o hdf5:shared=${H5CPP_SHARED}" + conan lock create conanfile.py ${CONAN_ARGS} --base --lockfile-out base.lock + conan lock create conanfile.py ${CONAN_ARGS} --build missing + - name: cache conan dependencies + uses: actions/cache@v2 + with: + path: /home/conan/.conan/data + key: conan-${{ matrix.profile }}-${{ hashfiles('base.lock') }}-${{ hashFiles('conan.lock') }} + restore-keys: | + conan-${{ matrix.profile }}-${{ hashfiles('base.lock') }} + conan-${{ matrix.profile }} + - name: install conan dependencies + run: | + conan install . \ + --install-folder build \ + --lockfile conan.lock \ + --build missing \ + --update + - name: build with cmake + run: | + conan build . \ + --build-folder build + - name: run tests + run: | + cd build + ctest --extra-verbose --no-tests=error + windows-build: + strategy: + matrix: + shared: ["shared", "static"] + boost: ["boost", "stdfs"] + runs-on: windows-2019 + steps: + - uses: actions/checkout@v2 + - name: Add MSVC to PATH + uses: ilammy/msvc-dev-cmd@v1 + - name: Set environment variables + run: | + bash .github/workflows/set_env_vars.sh \ + ${{ matrix.shared }} \ + ${{ matrix.boost }} + - name: Install and configure conan + run: | + python -m pip install --upgrade pip + pip install --upgrade conan + CONAN_ARGS="--profile .github/workflows/conan/profiles/vs2019 \ + -o with_boost=${H5CPP_WITH_BOOST} \ + -o shared=${H5CPP_SHARED} \ + -o hdf5:shared=${H5CPP_SHARED}" + conan lock create conanfile.py ${CONAN_ARGS} --base --lockfile-out base.lock + conan lock create conanfile.py ${CONAN_ARGS} --build missing + - name: cache conan dependencies + uses: actions/cache@v2 + with: + path: ~/.conan/data + key: conan-vs2019-${{ hashfiles('base.lock') }}-${{ hashFiles('conan.lock') }} + restore-keys: | + conan-vs-2019-${{ hashfiles('base.lock') }} + conan-vs-2019 + - name: install conan dependencies + run: | + conan install . \ + --install-folder build \ + --lockfile conan.lock \ + --build missing \ + --update \ + --generator virtualrunenv + - name: build with cmake + run: | + conan build . --build-folder build + - name: run tests + run: | + cd build + .\activate_run.ps1 + ctest --extra-verbose --no-tests=error + shell: pwsh + mac-build: + strategy: + matrix: + shared: ["shared", "static"] + boost: ["boost", "stdfs"] + mpi: ["serial", "mpi"] + runs-on: macos-10.15 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: '3.x' + - name: Set environment variables + run: | + bash .github/workflows/set_env_vars.sh \ + ${{ matrix.shared }} \ + ${{ matrix.boost }} \ + ${{ matrix.mpi }} + - name: Install OpenMPI and prerequisites + if: ${{ matrix.mpi == 'mpi' }} + run: brew install open-mpi + - name: Install and configure conan + run: | + python -m pip install --upgrade pip + pip install --upgrade conan + # there's currently an issue running the MPI tests on OSX with HDF5 compiled + # as a dynamic library. Use static HDF5 for now + HDF5_SHARED=${H5CPP_SHARED} + if [ "${H5CPP_WITH_MPI}" = "True" ]; then + HDF5_SHARED=False + fi + CONAN_ARGS="--profile .github/workflows/conan/profiles/apple-clang12 \ + -o with_boost=${H5CPP_WITH_BOOST} \ + -o with_mpi=${H5CPP_WITH_MPI} \ + -o shared=${H5CPP_SHARED} \ + -o hdf5:shared=${HDF5_SHARED}" + conan lock create conanfile.py ${CONAN_ARGS} --base --lockfile-out base.lock + conan lock create conanfile.py ${CONAN_ARGS} --build missing + - name: cache conan dependencies + uses: actions/cache@v2 + with: + path: ~/.conan/data + key: conan-apple-clang12-${{ hashfiles('base.lock') }}-${{ hashFiles('conan.lock') }} + restore-keys: | + conan-apple-clang12-${{ hashfiles('base.lock') }} + conan-apple-clang12 + - name: install conan dependencies + run: | + conan install . \ + --install-folder build \ + --lockfile conan.lock \ + --build missing \ + --update \ + --generator virtualenv + - name: build with cmake + run: | + conan build . --build-folder build + - name: run tests + run: | + cd build + source activate.sh + ctest --extra-verbose --no-tests=error + debian-10: + strategy: + matrix: + shared: [shared, static] + boost: [boost, stdfs] + runs-on: ubuntu-20.04 + container: + image: debian:buster + steps: + - uses: actions/checkout@v2 + - name: Set environment variables + run: | + bash .github/workflows/set_env_vars.sh \ + ${{ matrix.shared }} \ + ${{ matrix.boost }} + - name: install prerequisites + run: | + apt-get update + apt-get -y install \ + cmake \ + g++ \ + gpg \ + libhdf5-dev \ + libboost-filesystem-dev \ + wget + - name: download and install Catch2 + run: | + wget https://github.com/catchorg/Catch2/archive/refs/tags/v2.13.7.tar.gz + tar -xf v2.13.7.tar.gz + mkdir -p Catch2-2.13.7/build + cmake \ + -S Catch2-2.13.7 \ + -B Catch2-2.13.7/build/ \ + -DCATCH_BUILD_TESTING=OFF \ + -DCATCH_INSTALL_DOCS=OFF + cmake --build Catch2-2.13.7/build --target install + working-directory: /tmp + - name: build with cmake + run: | + HDF5_STATIC=ON + [ "${H5CPP_SHARED}" = "True" ] && HDF5_STATIC=OFF + mkdir build + cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DH5CPP_CONAN=DISABLE \ + -DHDF5_USE_STATIC_LIBRARIES=${HDF5_STATIC} \ + -DH5CPP_BUILD_SHARED=${H5CPP_SHARED} \ + -DH5CPP_WITH_BOOST=${H5CPP_WITH_BOOST} + cmake --build . -- -j 2 + - name: run tests + run: | + cd build + ctest --extra-verbose --no-tests=error diff --git a/.github/workflows/conan/profiles/apple-clang12 b/.github/workflows/conan/profiles/apple-clang12 new file mode 100644 index 0000000000..1c81d9406d --- /dev/null +++ b/.github/workflows/conan/profiles/apple-clang12 @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +arch_build=x86_64 +build_type=Release +compiler=apple-clang +compiler.libcxx=libc++ +compiler.version=12.0 +os=Macos +os_build=Macos diff --git a/.github/workflows/conan/profiles/clang13-libc++ b/.github/workflows/conan/profiles/clang13-libc++ new file mode 100644 index 0000000000..980ca777f9 --- /dev/null +++ b/.github/workflows/conan/profiles/clang13-libc++ @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +arch_build=x86_64 +build_type=Release +compiler=clang +compiler.libcxx=libc++ +compiler.version=13 +os=Linux +os_build=Linux diff --git a/.github/workflows/conan/profiles/clang13-libstdc++ b/.github/workflows/conan/profiles/clang13-libstdc++ new file mode 100644 index 0000000000..57d56c7abb --- /dev/null +++ b/.github/workflows/conan/profiles/clang13-libstdc++ @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +arch_build=x86_64 +build_type=Release +compiler=clang +compiler.libcxx=libstdc++11 +compiler.version=13 +os=Linux +os_build=Linux diff --git a/.github/workflows/conan/profiles/gcc11 b/.github/workflows/conan/profiles/gcc11 new file mode 100644 index 0000000000..fd7203d449 --- /dev/null +++ b/.github/workflows/conan/profiles/gcc11 @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +arch_build=x86_64 +build_type=Release +compiler=gcc +compiler.libcxx=libstdc++11 +compiler.version=11 +os=Linux +os_build=Linux diff --git a/.github/workflows/conan/profiles/vs2019 b/.github/workflows/conan/profiles/vs2019 new file mode 100644 index 0000000000..c1f9e6e406 --- /dev/null +++ b/.github/workflows/conan/profiles/vs2019 @@ -0,0 +1,9 @@ +[settings] +arch=x86_64 +arch_build=x86_64 +build_type=Release +compiler=Visual Studio +compiler.runtime=MD +compiler.version=16 +os=Windows +os_build=Windows diff --git a/.github/workflows/set_env_vars.sh b/.github/workflows/set_env_vars.sh new file mode 100644 index 0000000000..f239d47c93 --- /dev/null +++ b/.github/workflows/set_env_vars.sh @@ -0,0 +1,16 @@ +#!/bin/bash +if [ "$1" = "shared" ]; then + echo "H5CPP_SHARED=True" >> $GITHUB_ENV +else + echo "H5CPP_SHARED=False" >> $GITHUB_ENV +fi +if [ "$2" = "boost" ]; then + echo "H5CPP_WITH_BOOST=True" >> $GITHUB_ENV +else + echo "H5CPP_WITH_BOOST=False" >> $GITHUB_ENV +fi +if [ "$3" = "mpi" ]; then + echo "H5CPP_WITH_MPI=True" >> $GITHUB_ENV +else + echo "H5CPP_WITH_MPI=False" >> $GITHUB_ENV +fi diff --git a/CMakeLists.txt b/CMakeLists.txt index 994611ef35..567e0f8b84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.0.0) +cmake_minimum_required(VERSION 3.10) project(h5cpp LANGUAGES CXX C # VERSION 0.4.1 @@ -12,31 +12,49 @@ project(h5cpp #============================================================================= set(EXTRA_MODULES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake) list(APPEND CMAKE_MODULE_PATH ${EXTRA_MODULES_DIR}) -list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/subprojects/catch2/cmake) + +if (NOT DEFINED BUILD_SHARED_LIBS) + set(BUILD_SHARED_LIBS ON) +endif() +option(H5CPP_BUILD_SHARED "Build h5cpp as a shared library" ${BUILD_SHARED_LIBS}) +if (NOT H5CPP_BUILD_SHARED) + set(BUILD_SHARED_LIBS OFF) +endif() +option(H5CPP_LOCAL_MODULES "Build h5cpp using cmake local modules first") #============================================================================= # Conan #============================================================================= -# SET(CONAN_DISABLE_CHECK_COMPILER TRUE) -set(CONAN_PROFILE "default" CACHE STRING "Name of conan profile to use, uses default by default") -set(CONAN "AUTO" CACHE STRING "conan options AUTO (conan must be in path), MANUAL (expects conanbuildinfo.cmake in build directory) or DISABLE") -set(CONAN_FILE "conanfile_ess.txt" CACHE STRING "The conanfile to use for the build") -if(${CONAN} MATCHES "AUTO") +set(H5CPP_CONAN "AUTO" CACHE STRING "conan options AUTO (conan must be in path), MANUAL (expects conanbuildinfo.cmake in build directory) or DISABLE") +set(H5CPP_CONAN_PROFILE "default" CACHE STRING "Name of conan profile to use, uses default by default") +set(H5CPP_CONAN_FILE "conanfile_ess.txt" CACHE STRING "The conanfile to use for the build") + +if(${H5CPP_CONAN} MATCHES "AUTO") include(${EXTRA_MODULES_DIR}/ConanSetup.cmake) - conan_cmake_run(CONANFILE ${CONAN_FILE} - PROFILE ${CONAN_PROFILE} + conan_cmake_run(CONANFILE ${H5CPP_CONAN_FILE} + PROFILE ${H5CPP_CONAN_PROFILE} BASIC_SETUP NO_OUTPUT_DIRS KEEP_RPATHS BUILD_TYPE "None" BUILD outdated) -elseif(${CONAN} MATCHES "MANUAL") + if(H5CPP_LOCAL_MODULES) + list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) + else() + list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_BINARY_DIR}) + endif() +elseif(${H5CPP_CONAN} MATCHES "MANUAL") if(EXISTS "${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") include("${CMAKE_BINARY_DIR}/conanbuildinfo.cmake") conan_basic_setup(NO_OUTPUT_DIRS KEEP_RPATHS) + if(H5CPP_LOCAL_MODULES) + list(APPEND CMAKE_MODULE_PATH ${CMAKE_BINARY_DIR}) + else() + list(INSERT CMAKE_MODULE_PATH 0 ${CMAKE_BINARY_DIR}) + endif() else() - message(FATAL_ERROR "CONAN set to MANUAL but no file named conanbuildinfo.cmake found in build directory") + message(FATAL_ERROR "H5CPP_CONAN set to MANUAL but no file named conanbuildinfo.cmake found in build directory") endif() -elseif(NOT ${CONAN} MATCHES "DISABLE") - message(FATAL_ERROR "Unrecognised option for CONAN (${CONAN}), use AUTO, MANUAL or DISABLE") +elseif(NOT ${H5CPP_CONAN} MATCHES "DISABLE") + message(FATAL_ERROR "Unrecognised option for H5CPP_CONAN (${H5CPP_CONAN}), use AUTO, MANUAL or DISABLE") endif() #============================================================================= @@ -63,24 +81,40 @@ include(DoxygenUtilities) #============================================================================= # compiler and library configuration #============================================================================= -set(WITH_BOOST ON CACHE BOOL "enable Boost filesystem support") -if(WITH_BOOST) - message(STATUS "Using Boost library for filesystem") - include(${EXTRA_MODULES_DIR}/BoostLibraryConfig.cmake) -else() +option(H5CPP_WITH_BOOST "enable Boost filesystem support" ON) +if(H5CPP_WITH_BOOST) + find_package(Boost 1.41 COMPONENTS filesystem system REQUIRED) +else() # if we do not use Boost we have to ensure a C++ standard of at least 2017 # since we require the std::filesystem API set(CMAKE_CXX_STANDARD 17) - message(STATUS "Using std library for filesystem") endif() include(${EXTRA_MODULES_DIR}/CompilerConfig.cmake) include(${EXTRA_MODULES_DIR}/MPIConfig.cmake) include(${EXTRA_MODULES_DIR}/HDF5LibraryConfig.cmake) +if(H5CPP_BUILD_SHARED) + h5cpp_message(STATUS "Building shared library") +else() + h5cpp_message(STATUS "Building static library") +endif() +if (H5CPP_WITH_MPI) + h5cpp_message(STATUS "Building with MPI support") +endif() +if(H5CPP_WITH_BOOST) + h5cpp_message(STATUS "Using Boost library for filesystem") +else() + h5cpp_message(STATUS "Using std library for filesystem") +endif() + +find_package(Threads REQUIRED) +find_package(SZIP) +find_package(ZLIB REQUIRED) + add_subdirectory(src) -set( BUILD_DOCS ON CACHE BOOL "Build documentation") -if(BUILD_DOCS) +option(H5CPP_BUILD_DOCS "Build documentation" ON) +if(H5CPP_BUILD_DOCS) add_subdirectory(doc) endif() @@ -93,21 +127,22 @@ install(DIRECTORY examples #============================================================================= # unit tests if GTest if present #============================================================================= -set(DISABLE_TESTS False CACHE BOOL "Disable building unit tests") -if(NOT DISABLE_TESTS) - enable_testing() - include(Catch) +option(H5CPP_DISABLE_TESTS "Disable building unit tests" OFF) +if(NOT H5CPP_DISABLE_TESTS) + find_package(Catch2 REQUIRED) + enable_testing() + include(Catch) add_subdirectory(test) endif() #============================================================================= # create package file #============================================================================= -set(WITH_SWMR OFF CACHE BOOL "enable SWMR support") -set(WITH_VDS OFF CACHE BOOL "enable VDS support") +option(H5CPP_WITH_SWMR "enable SWMR support" OFF) +option(H5CPP_WITH_VDS "enable VDS support" OFF) if(HDF5_VERSION VERSION_GREATER 1.10.0 OR HDF5_VERSION VERSION_EQUAL 1.10.0) - set(WITH_SWMR ON) - set(WITH_VDS ON) + set(H5CPP_WITH_SWMR ON) + set(H5CPP_WITH_VDS ON) endif() # diff --git a/CMakeSettings.json b/CMakeSettings.json index 3d9aab7272..a92f27fdeb 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -6,11 +6,11 @@ "configurationType": "Debug", "variables": [ { - "name": "CONAN_FILE", + "name": "H5CPP_CONAN_FILE", "value": "conanfile_eugen.txt" }, { - "name": "CONAN_PROFILE", + "name": "H5CPP_CONAN_PROFILE", "value": "h5cpp-windows10-debug" }, { @@ -34,7 +34,7 @@ "configurationType": "Release", "variables": [ { - "name": "CONAN_FILE", + "name": "H5CPP_CONAN_FILE", "value": "conanfile_eugen.txt" }, { diff --git a/Jenkinsfile b/Jenkinsfile index 124bae502d..3de2b1141d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -76,43 +76,43 @@ builders = pipeline_builder.createBuilders { container -> def cmake_prefix switch (container.key) { case 'centos7': - cmake_options = '-DWITH_MPI=1 -DCONAN_FILE=conanfile_ess_mpi.txt -DCMAKE_BUILD_TYPE=Debug -DWITH_BOOST=OFF' + cmake_options = '-DH5CPP_WITH_MPI=1 -DH5CPP_CONAN_FILE=conanfile_ess_mpi.txt -DCMAKE_BUILD_TYPE=Debug -DH5CPP_WITH_BOOST=OFF -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = 'CC=/usr/lib64/mpich-3.2/bin/mpicc CXX=/usr/lib64/mpich-3.2/bin/mpicxx' break case 'centos7-release': - cmake_options = '-DWITH_MPI=1 -DCONAN_FILE=conanfile_ess_mpi.txt -DCMAKE_BUILD_TYPE=Release' + cmake_options = '-DH5CPP_WITH_MPI=1 -DH5CPP_CONAN_FILE=conanfile_ess_mpi.txt -DCMAKE_BUILD_TYPE=Release -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = 'CC=/usr/lib64/mpich-3.2/bin/mpicc CXX=/usr/lib64/mpich-3.2/bin/mpicxx' break case 'debian10': - cmake_options = '-DCMAKE_BUILD_TYPE=Debug' + cmake_options = '-DCMAKE_BUILD_TYPE=Debug -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'debian10-release': - cmake_options = '-DCMAKE_BUILD_TYPE=Release' + cmake_options = '-DCMAKE_BUILD_TYPE=Release -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'debian10-release-hdf5-1.12': - cmake_options = '-DCMAKE_BUILD_TYPE=Release -DCONAN_FILE=conanfile_1.12.0.txt' + cmake_options = '-DCMAKE_BUILD_TYPE=Release -DH5CPP_CONAN_FILE=conanfile_1.12.0.txt -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'ubuntu1804': - cmake_options = '-DCMAKE_BUILD_TYPE=Debug' + cmake_options = '-DCMAKE_BUILD_TYPE=Debug -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'ubuntu1804-release': - cmake_options = '-DCMAKE_BUILD_TYPE=Release' + cmake_options = '-DCMAKE_BUILD_TYPE=Release -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'ubuntu2004': - cmake_options = '-DCMAKE_BUILD_TYPE=Debug' + cmake_options = '-DCMAKE_BUILD_TYPE=Debug -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break case 'ubuntu2004-release': - cmake_options = '-DCMAKE_BUILD_TYPE=Release' + cmake_options = '-DCMAKE_BUILD_TYPE=Release -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break default: - cmake_options = '-DCMAKE_BUILD_TYPE=Debug' + cmake_options = '-DCMAKE_BUILD_TYPE=Debug -DH5CPP_LOCAL_MODULES=ON' cmake_prefix = '' break } @@ -301,7 +301,7 @@ def get_macos_pipeline(build_type) dir("${project}/build") { try { - sh "cmake -DCMAKE_BUILD_TYPE=${build_type} -DCONAN_FILE=conanfile_macos.txt ../code" + sh "cmake -DCMAKE_BUILD_TYPE=${build_type} -DH5CPP_CONAN_FILE=conanfile_macos.txt ../code" } catch (e) { failure_function(e, 'MacOSX / CMake failed') } @@ -360,7 +360,7 @@ def get_win10_pipeline() dir("_build") { try { bat 'conan remote list' - bat 'cmake -DCMAKE_BUILD_TYPE=Release -DCONAN_FILE=conanfile_windows_ess.txt -DWITH_BOOST=OFF -G "Visual Studio 15 2017 Win64" ..' + bat 'cmake -DCMAKE_BUILD_TYPE=Release -DH5CPP_CONAN_FILE=conanfile_windows_ess.txt -DH5CPP_WITH_BOOST=OFF -G "Visual Studio 15 2017 Win64" ..' } catch (e) { failure_function(e, 'Windows10 / CMake failed') } diff --git a/README.md b/README.md index 37c437e85a..9ca0a38399 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ The minimum requirements for building the library are: * a C++ compiler, gcc>=4.8.1 should do well * the HDF5 C library (>=1.8.13 would do but >=1.10.0 is prefered) * cmake >= 3.0 -* _either_ the boost libraries _or_ a compiler with std::filesystem or std::experimental::filesystem (and specify WITH_BOOST=OFF to CMake) +* _either_ the boost libraries _or_ a compiler with std::filesystem or std::experimental::filesystem (and specify H5CPP_WITH_BOOST=OFF to CMake) The external library dependencies can be acquired and built using [Conan](https://conan.io/). Conan can be installed with PyPI: ``` @@ -74,7 +74,7 @@ conan remote add bincrafters https://bincrafters.jfrog.io/artifactory/api/conan/ ``` and that's it, CMake will handle the rest! -Alternatively you can manually install the dependencies to typical system locations. In this case please disable Conan by using the `-DCONAN=DISABLE` option when you run CMake. +Alternatively you can manually install the dependencies to typical system locations. In this case please disable Conan by using the `-DH5CPP_CONAN=DISABLE` option when you run CMake. Building the library is standard cmake & make fare, out of source. For example, in linux shell, you would do the following: diff --git a/cmake/BoostLibraryConfig.cmake b/cmake/BoostLibraryConfig.cmake deleted file mode 100644 index 4a296c16ce..0000000000 --- a/cmake/BoostLibraryConfig.cmake +++ /dev/null @@ -1,10 +0,0 @@ - -set(Boost_USE_STATIC_LIBS OFF) -set(Boost_USE_MULTITHREADED ON) -set(Boost_USE_STATIC_RUNTIME OFF) - -find_package(Boost 1.41 COMPONENTS filesystem system REQUIRED) - -if (CMAKE_CXX_COMPILER_ID MATCHES MSVC) - add_definitions(-DBOOST_ALL_DYN_LINK) -endif () diff --git a/cmake/FindHDF5.cmake b/cmake/FindHDF5.cmake new file mode 100644 index 0000000000..1507ad8f49 --- /dev/null +++ b/cmake/FindHDF5.cmake @@ -0,0 +1,1226 @@ +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#[=======================================================================[.rst: +FindHDF5 +-------- + +Find Hierarchical Data Format (HDF5), a library for reading and writing +self describing array data. + + +This module invokes the ``HDF5`` wrapper compiler that should be installed +alongside ``HDF5``. Depending upon the ``HDF5`` Configuration, the wrapper +compiler is called either ``h5cc`` or ``h5pcc``. If this succeeds, the module +will then call the compiler with the show argument to see what flags +are used when compiling an ``HDF5`` client application. + +The module will optionally accept the ``COMPONENTS`` argument. If no +``COMPONENTS`` are specified, then the find module will default to finding +only the ``HDF5`` C library. If one or more ``COMPONENTS`` are specified, the +module will attempt to find the language bindings for the specified +components. The valid components are ``C``, ``CXX``, ``Fortran``, ``HL``. +``HL`` refers to the "high-level" HDF5 functions for C and Fortran. +If the ``COMPONENTS`` argument is not given, the module will +attempt to find only the C bindings. +For example, to use Fortran HDF5 and HDF5-HL functions, do: +``find_package(HDF5 COMPONENTS Fortran HL)``. + +This module will read the variable +``HDF5_USE_STATIC_LIBRARIES`` to determine whether or not to prefer a +static link to a dynamic link for ``HDF5`` and all of it's dependencies. +To use this feature, make sure that the ``HDF5_USE_STATIC_LIBRARIES`` +variable is set before the call to find_package. + +.. versionadded:: 3.10 + Support for ``HDF5_USE_STATIC_LIBRARIES`` on Windows. + +Both the serial and parallel ``HDF5`` wrappers are considered and the first +directory to contain either one will be used. In the event that both appear +in the same directory the serial version is preferentially selected. This +behavior can be reversed by setting the variable ``HDF5_PREFER_PARALLEL`` to +``TRUE``. + +In addition to finding the includes and libraries required to compile +an ``HDF5`` client application, this module also makes an effort to find +tools that come with the ``HDF5`` distribution that may be useful for +regression testing. + +Result Variables +^^^^^^^^^^^^^^^^ + +This module will set the following variables in your project: + +``HDF5_FOUND`` + HDF5 was found on the system +``HDF5_VERSION`` + .. versionadded:: 3.3 + HDF5 library version +``HDF5_INCLUDE_DIRS`` + Location of the HDF5 header files +``HDF5_DEFINITIONS`` + Required compiler definitions for HDF5 +``HDF5_LIBRARIES`` + Required libraries for all requested bindings +``HDF5_HL_LIBRARIES`` + Required libraries for the HDF5 high level API for all bindings, + if the ``HL`` component is enabled + +Available components are: ``C`` ``CXX`` ``Fortran`` and ``HL``. +For each enabled language binding, a corresponding ``HDF5_${LANG}_LIBRARIES`` +variable, and potentially ``HDF5_${LANG}_DEFINITIONS``, will be defined. +If the ``HL`` component is enabled, then an ``HDF5_${LANG}_HL_LIBRARIES`` will +also be defined. With all components enabled, the following variables will be defined: + +``HDF5_C_DEFINITIONS`` + Required compiler definitions for HDF5 C bindings +``HDF5_CXX_DEFINITIONS`` + Required compiler definitions for HDF5 C++ bindings +``HDF5_Fortran_DEFINITIONS`` + Required compiler definitions for HDF5 Fortran bindings +``HDF5_C_INCLUDE_DIRS`` + Required include directories for HDF5 C bindings +``HDF5_CXX_INCLUDE_DIRS`` + Required include directories for HDF5 C++ bindings +``HDF5_Fortran_INCLUDE_DIRS`` + Required include directories for HDF5 Fortran bindings +``HDF5_C_LIBRARIES`` + Required libraries for the HDF5 C bindings +``HDF5_CXX_LIBRARIES`` + Required libraries for the HDF5 C++ bindings +``HDF5_Fortran_LIBRARIES`` + Required libraries for the HDF5 Fortran bindings +``HDF5_C_HL_LIBRARIES`` + Required libraries for the high level C bindings +``HDF5_CXX_HL_LIBRARIES`` + Required libraries for the high level C++ bindings +``HDF5_Fortran_HL_LIBRARIES`` + Required libraries for the high level Fortran bindings. + +``HDF5_IS_PARALLEL`` + HDF5 library has parallel IO support +``HDF5_C_COMPILER_EXECUTABLE`` + path to the HDF5 C wrapper compiler +``HDF5_CXX_COMPILER_EXECUTABLE`` + path to the HDF5 C++ wrapper compiler +``HDF5_Fortran_COMPILER_EXECUTABLE`` + path to the HDF5 Fortran wrapper compiler +``HDF5_C_COMPILER_EXECUTABLE_NO_INTERROGATE`` + path to the primary C compiler which is also the HDF5 wrapper +``HDF5_CXX_COMPILER_EXECUTABLE_NO_INTERROGATE`` + path to the primary C++ compiler which is also the HDF5 wrapper +``HDF5_Fortran_COMPILER_EXECUTABLE_NO_INTERROGATE`` + path to the primary Fortran compiler which is also the HDF5 wrapper +``HDF5_DIFF_EXECUTABLE`` + path to the HDF5 dataset comparison tool + +With all components enabled, the following targets will be defined: + +``HDF5::HDF5`` + All detected ``HDF5_LIBRARIES``. +``hdf5::hdf5`` + C library. +``hdf5::hdf5_cpp`` + C++ library. +``hdf5::hdf5_fortran`` + Fortran library. +``hdf5::hdf5_hl`` + High-level C library. +``hdf5::hdf5_hl_cpp`` + High-level C++ library. +``hdf5::hdf5_hl_fortran`` + High-level Fortran library. +``hdf5::h5diff`` + ``h5diff`` executable. + +Hints +^^^^^ + +The following variables can be set to guide the search for HDF5 libraries and includes: + +``HDF5_PREFER_PARALLEL`` + .. versionadded:: 3.4 + + set ``true`` to prefer parallel HDF5 (by default, serial is preferred) + +``HDF5_FIND_DEBUG`` + .. versionadded:: 3.9 + + Set ``true`` to get extra debugging output. + +``HDF5_NO_FIND_PACKAGE_CONFIG_FILE`` + .. versionadded:: 3.8 + + Set ``true`` to skip trying to find ``hdf5-config.cmake``. +#]=======================================================================] + +include(SelectLibraryConfigurations) +include(FindPackageHandleStandardArgs) + +# We haven't found HDF5 yet. Clear its state in case it is set in the parent +# scope somewhere else. We can't rely on it because different components may +# have been requested for this call. +set(HDF5_FOUND OFF) + +# List of the valid HDF5 components +set(HDF5_VALID_LANGUAGE_BINDINGS C CXX Fortran) + +# Validate the list of find components. +if(NOT HDF5_FIND_COMPONENTS) + set(HDF5_LANGUAGE_BINDINGS "C") +else() + set(HDF5_LANGUAGE_BINDINGS) + # add the extra specified components, ensuring that they are valid. + set(HDF5_FIND_HL OFF) + foreach(_component IN LISTS HDF5_FIND_COMPONENTS) + list(FIND HDF5_VALID_LANGUAGE_BINDINGS ${_component} _component_location) + if(NOT _component_location EQUAL -1) + list(APPEND HDF5_LANGUAGE_BINDINGS ${_component}) + elseif(_component STREQUAL "HL") + set(HDF5_FIND_HL ON) + elseif(_component STREQUAL "Fortran_HL") # only for compatibility + list(APPEND HDF5_LANGUAGE_BINDINGS Fortran) + set(HDF5_FIND_HL ON) + set(HDF5_FIND_REQUIRED_Fortran_HL FALSE) + set(HDF5_FIND_REQUIRED_Fortran TRUE) + set(HDF5_FIND_REQUIRED_HL TRUE) + else() + message(FATAL_ERROR "${_component} is not a valid HDF5 component.") + endif() + endforeach() + unset(_component) + unset(_component_location) + if(NOT HDF5_LANGUAGE_BINDINGS) + get_property(_langs GLOBAL PROPERTY ENABLED_LANGUAGES) + foreach(_lang IN LISTS _langs) + if(_lang MATCHES "^(C|CXX|Fortran)$") + list(APPEND HDF5_LANGUAGE_BINDINGS ${_lang}) + endif() + endforeach() + endif() + list(REMOVE_ITEM HDF5_FIND_COMPONENTS Fortran_HL) # replaced by Fortran and HL + list(REMOVE_DUPLICATES HDF5_LANGUAGE_BINDINGS) +endif() + +# Determine whether to search for serial or parallel executable first +if(HDF5_PREFER_PARALLEL) + set(HDF5_C_COMPILER_NAMES h5pcc h5cc) + set(HDF5_CXX_COMPILER_NAMES h5pc++ h5c++) + set(HDF5_Fortran_COMPILER_NAMES h5pfc h5fc) +else() + set(HDF5_C_COMPILER_NAMES h5cc h5pcc) + set(HDF5_CXX_COMPILER_NAMES h5c++ h5pc++) + set(HDF5_Fortran_COMPILER_NAMES h5fc h5pfc) +endif() + +# Test first if the current compilers automatically wrap HDF5 +function(_HDF5_test_regular_compiler_C success version is_parallel) + set(scratch_directory + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if(NOT ${success} OR + NOT EXISTS ${scratch_directory}/compiler_has_h5_c) + set(test_file ${scratch_directory}/cmake_hdf5_test.c) + file(WRITE ${test_file} + "#include \n" + "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n" + "#ifdef H5_HAVE_PARALLEL\n" + "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n" + "#endif\n" + "int main(int argc, char **argv) {\n" + " int require = 0;\n" + " require += info_ver[argc];\n" + "#ifdef H5_HAVE_PARALLEL\n" + " require += info_parallel[argc];\n" + "#endif\n" + " hid_t fid;\n" + " fid = H5Fcreate(\"foo.h5\",H5F_ACC_TRUNC,H5P_DEFAULT,H5P_DEFAULT);\n" + " return 0;\n" + "}") + try_compile(${success} ${scratch_directory} ${test_file} + COPY_FILE ${scratch_directory}/compiler_has_h5_c + ) + endif() + if(${success}) + file(STRINGS ${scratch_directory}/compiler_has_h5_c INFO_STRINGS + REGEX "^INFO:" + ) + string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?" + INFO_VER "${INFO_STRINGS}" + ) + set(${version} ${CMAKE_MATCH_1}) + if(CMAKE_MATCH_3) + set(${version} ${HDF5_C_VERSION}.${CMAKE_MATCH_3}) + endif() + set(${version} ${${version}} PARENT_SCOPE) + + if(INFO_STRINGS MATCHES "INFO:PARALLEL") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() +endfunction() + +function(_HDF5_test_regular_compiler_CXX success version is_parallel) + set(scratch_directory ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if(NOT ${success} OR + NOT EXISTS ${scratch_directory}/compiler_has_h5_cxx) + set(test_file ${scratch_directory}/cmake_hdf5_test.cxx) + file(WRITE ${test_file} + "#include \n" + "#ifndef H5_NO_NAMESPACE\n" + "using namespace H5;\n" + "#endif\n" + "const char* info_ver = \"INFO\" \":\" H5_VERSION;\n" + "#ifdef H5_HAVE_PARALLEL\n" + "const char* info_parallel = \"INFO\" \":\" \"PARALLEL\";\n" + "#endif\n" + "int main(int argc, char **argv) {\n" + " int require = 0;\n" + " require += info_ver[argc];\n" + "#ifdef H5_HAVE_PARALLEL\n" + " require += info_parallel[argc];\n" + "#endif\n" + " H5File file(\"foo.h5\", H5F_ACC_TRUNC);\n" + " return 0;\n" + "}") + try_compile(${success} ${scratch_directory} ${test_file} + COPY_FILE ${scratch_directory}/compiler_has_h5_cxx + ) + endif() + if(${success}) + file(STRINGS ${scratch_directory}/compiler_has_h5_cxx INFO_STRINGS + REGEX "^INFO:" + ) + string(REGEX MATCH "^INFO:([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?" + INFO_VER "${INFO_STRINGS}" + ) + set(${version} ${CMAKE_MATCH_1}) + if(CMAKE_MATCH_3) + set(${version} ${HDF5_CXX_VERSION}.${CMAKE_MATCH_3}) + endif() + set(${version} ${${version}} PARENT_SCOPE) + + if(INFO_STRINGS MATCHES "INFO:PARALLEL") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() +endfunction() + +function(_HDF5_test_regular_compiler_Fortran success is_parallel) + if(NOT ${success}) + set(scratch_directory + ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + set(test_file ${scratch_directory}/cmake_hdf5_test.f90) + file(WRITE ${test_file} + "program hdf5_hello\n" + " use hdf5\n" + " use h5lt\n" + " use h5ds\n" + " integer error\n" + " call h5open_f(error)\n" + " call h5close_f(error)\n" + "end\n") + try_compile(${success} ${scratch_directory} ${test_file}) + if(${success}) + execute_process(COMMAND ${CMAKE_Fortran_COMPILER} -showconfig + OUTPUT_VARIABLE config_output + ERROR_VARIABLE config_error + RESULT_VARIABLE config_result + ) + if(config_output MATCHES "Parallel HDF5: yes") + set(${is_parallel} TRUE PARENT_SCOPE) + else() + set(${is_parallel} FALSE PARENT_SCOPE) + endif() + endif() + endif() +endfunction() + +# Invoke the HDF5 wrapper compiler. The compiler return value is stored to the +# return_value argument, the text output is stored to the output variable. +function( _HDF5_invoke_compiler language output_var return_value_var version_var is_parallel_var) + set(is_parallel FALSE) + if(HDF5_USE_STATIC_LIBRARIES) + set(lib_type_args -noshlib) + else() + set(lib_type_args -shlib) + endif() + set(scratch_dir ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/hdf5) + if("${language}" STREQUAL "C") + set(test_file ${scratch_dir}/cmake_hdf5_test.c) + elseif("${language}" STREQUAL "CXX") + set(test_file ${scratch_dir}/cmake_hdf5_test.cxx) + elseif("${language}" STREQUAL "Fortran") + set(test_file ${scratch_dir}/cmake_hdf5_test.f90) + endif() + # Verify that the compiler wrapper can actually compile: sometimes the compiler + # wrapper exists, but not the compiler. E.g. Miniconda / Anaconda Python + execute_process( + COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} ${test_file} + WORKING_DIRECTORY ${scratch_dir} + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE return_value + ) + if(return_value AND NOT HDF5_FIND_QUIETLY) + message(STATUS + "HDF5 ${language} compiler wrapper is unable to compile a minimal HDF5 program.") + else() + execute_process( + COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -show ${lib_type_args} ${test_file} + WORKING_DIRECTORY ${scratch_dir} + OUTPUT_VARIABLE output + ERROR_VARIABLE output + RESULT_VARIABLE return_value + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(return_value AND NOT HDF5_FIND_QUIETLY) + message(STATUS + "Unable to determine HDF5 ${language} flags from HDF5 wrapper.") + endif() + execute_process( + COMMAND ${HDF5_${language}_COMPILER_EXECUTABLE} -showconfig + OUTPUT_VARIABLE config_output + ERROR_VARIABLE config_output + RESULT_VARIABLE return_value + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + if(return_value AND NOT HDF5_FIND_QUIETLY) + message(STATUS + "Unable to determine HDF5 ${language} version_var from HDF5 wrapper.") + endif() + string(REGEX MATCH "HDF5 Version: ([a-zA-Z0-9\\.\\-]*)" version "${config_output}") + if(version) + string(REPLACE "HDF5 Version: " "" version "${version}") + string(REPLACE "-patch" "." version "${version}") + endif() + if(config_output MATCHES "Parallel HDF5: yes") + set(is_parallel TRUE) + endif() + endif() + foreach(var output return_value version is_parallel) + set(${${var}_var} ${${var}} PARENT_SCOPE) + endforeach() +endfunction() + +# Parse a compile line for definitions, includes, library paths, and libraries. +function(_HDF5_parse_compile_line compile_line_var include_paths definitions + library_paths libraries libraries_hl) + + separate_arguments(_compile_args NATIVE_COMMAND "${${compile_line_var}}") + + foreach(_arg IN LISTS _compile_args) + if("${_arg}" MATCHES "^-I(.*)$") + # include directory + list(APPEND include_paths "${CMAKE_MATCH_1}") + elseif("${_arg}" MATCHES "^-D(.*)$") + # compile definition + list(APPEND definitions "-D${CMAKE_MATCH_1}") + elseif("${_arg}" MATCHES "^-L(.*)$") + # library search path + list(APPEND library_paths "${CMAKE_MATCH_1}") + elseif("${_arg}" MATCHES "^-l(hdf5.*hl.*)$") + # library name (hl) + list(APPEND libraries_hl "${CMAKE_MATCH_1}") + elseif("${_arg}" MATCHES "^-l(.*)$") + # library name + list(APPEND libraries "${CMAKE_MATCH_1}") + elseif("${_arg}" MATCHES "^(.:)?[/\\].*\\.(a|so|dylib|sl|lib)$") + # library file + if(NOT EXISTS "${_arg}") + continue() + endif() + get_filename_component(_lpath "${_arg}" DIRECTORY) + get_filename_component(_lname "${_arg}" NAME_WE) + string(REGEX REPLACE "^lib" "" _lname "${_lname}") + list(APPEND library_paths "${_lpath}") + if(_lname MATCHES "hdf5.*hl") + list(APPEND libraries_hl "${_lname}") + else() + list(APPEND libraries "${_lname}") + endif() + endif() + endforeach() + foreach(var include_paths definitions library_paths libraries libraries_hl) + set(${${var}_var} ${${var}} PARENT_SCOPE) + endforeach() +endfunction() + +# Select a preferred imported configuration from a target +function(_HDF5_select_imported_config target imported_conf) + # We will first assign the value to a local variable _imported_conf, then assign + # it to the function argument at the end. + get_target_property(_imported_conf ${target} MAP_IMPORTED_CONFIG_${CMAKE_BUILD_TYPE}) + if (NOT _imported_conf) + # Get available imported configurations by examining target properties + get_target_property(_imported_conf ${target} IMPORTED_CONFIGURATIONS) + if(HDF5_FIND_DEBUG) + message(STATUS "Found imported configurations: ${_imported_conf}") + endif() + # Find the imported configuration that we prefer. + # We do this by making list of configurations in order of preference, + # starting with ${CMAKE_BUILD_TYPE} and ending with the first imported_conf + set(_preferred_confs ${CMAKE_BUILD_TYPE}) + list(GET _imported_conf 0 _fallback_conf) + list(APPEND _preferred_confs RELWITHDEBINFO RELEASE DEBUG ${_fallback_conf}) + if(HDF5_FIND_DEBUG) + message(STATUS "Start search through imported configurations in the following order: ${_preferred_confs}") + endif() + # Now find the first of these that is present in imported_conf + cmake_policy(PUSH) + cmake_policy(SET CMP0057 NEW) # support IN_LISTS + foreach (_conf IN LISTS _preferred_confs) + if (${_conf} IN_LIST _imported_conf) + set(_imported_conf ${_conf}) + break() + endif() + endforeach() + cmake_policy(POP) + endif() + if(HDF5_FIND_DEBUG) + message(STATUS "Selected imported configuration: ${_imported_conf}") + endif() + # assign value to function argument + set(${imported_conf} ${_imported_conf} PARENT_SCOPE) +endfunction() + + +if(NOT HDF5_ROOT) + set(HDF5_ROOT $ENV{HDF5_ROOT}) +endif() +if(HDF5_ROOT) + set(_HDF5_SEARCH_OPTS NO_DEFAULT_PATH) +else() + set(_HDF5_SEARCH_OPTS) +endif() + +# Try to find HDF5 using an installed hdf5-config.cmake +if(NOT HDF5_FOUND AND NOT HDF5_NO_FIND_PACKAGE_CONFIG_FILE) + find_package(HDF5 QUIET NO_MODULE + HINTS ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS} + ) + if( HDF5_FOUND) + if(HDF5_FIND_DEBUG) + message(STATUS "Found HDF5 at ${HDF5_DIR} via NO_MODULE. Now trying to extract locations etc.") + endif() + set(HDF5_IS_PARALLEL ${HDF5_ENABLE_PARALLEL}) + set(HDF5_INCLUDE_DIRS ${HDF5_INCLUDE_DIR}) + set(HDF5_LIBRARIES) + if (NOT TARGET hdf5 AND NOT TARGET hdf5-static AND NOT TARGET hdf5-shared) + # Some HDF5 versions (e.g. 1.8.18) used hdf5::hdf5 etc + set(_target_prefix "hdf5::") + endif() + set(HDF5_C_TARGET ${_target_prefix}hdf5) + set(HDF5_C_HL_TARGET ${_target_prefix}hdf5_hl) + set(HDF5_CXX_TARGET ${_target_prefix}hdf5_cpp) + set(HDF5_CXX_HL_TARGET ${_target_prefix}hdf5_hl_cpp) + set(HDF5_Fortran_TARGET ${_target_prefix}hdf5_fortran) + set(HDF5_Fortran_HL_TARGET ${_target_prefix}hdf5_hl_fortran) + set(HDF5_DEFINITIONS "") + if(HDF5_USE_STATIC_LIBRARIES) + set(_suffix "-static") + else() + set(_suffix "-shared") + endif() + foreach(_lang ${HDF5_LANGUAGE_BINDINGS}) + + #Older versions of hdf5 don't have a static/shared suffix so + #if we detect that occurrence clear the suffix + if(_suffix AND NOT TARGET ${HDF5_${_lang}_TARGET}${_suffix}) + if(NOT TARGET ${HDF5_${_lang}_TARGET}) + #can't find this component with or without the suffix + #so bail out, and let the following locate HDF5 + set(HDF5_FOUND FALSE) + break() + endif() + set(_suffix "") + endif() + + if(HDF5_FIND_DEBUG) + message(STATUS "Trying to get properties of target ${HDF5_${_lang}_TARGET}${_suffix}") + endif() + # Find library for this target. Complicated as on Windows with a DLL, we need to search for the import-lib. + _HDF5_select_imported_config(${HDF5_${_lang}_TARGET}${_suffix} _hdf5_imported_conf) + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) + if (NOT _hdf5_lang_location) + # no import lib, just try LOCATION + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf}) + if (NOT _hdf5_lang_location) + get_target_property(_hdf5_lang_location ${HDF5_${_lang}_TARGET}${_suffix} LOCATION) + endif() + endif() + if( _hdf5_lang_location ) + set(HDF5_${_lang}_LIBRARY ${_hdf5_lang_location}) + list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) + set(HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_TARGET}${_suffix}) + set(HDF5_${_lang}_FOUND TRUE) + endif() + if(HDF5_FIND_HL) + get_target_property(_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} IMPORTED_IMPLIB_${_hdf5_imported_conf} ) + if (NOT _hdf5_lang_hl_location) + get_target_property(_hdf5_lang_hl_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION_${_hdf5_imported_conf}) + if (NOT _hdf5_hl_lang_location) + get_target_property(_hdf5_hl_lang_location ${HDF5_${_lang}_HL_TARGET}${_suffix} LOCATION) + endif() + endif() + if( _hdf5_lang_hl_location ) + set(HDF5_${_lang}_HL_LIBRARY ${_hdf5_lang_hl_location}) + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix}) + set(HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_HL_TARGET}${_suffix}) + set(HDF5_HL_FOUND TRUE) + endif() + unset(_hdf5_lang_hl_location) + endif() + unset(_hdf5_imported_conf) + unset(_hdf5_lang_location) + endforeach() + endif() +endif() + +if(NOT HDF5_FOUND) + set(_HDF5_NEED_TO_SEARCH FALSE) + set(HDF5_COMPILER_NO_INTERROGATE TRUE) + # Only search for languages we've enabled + foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + # First check to see if our regular compiler is one of wrappers + if(_lang STREQUAL "C") + _HDF5_test_regular_compiler_C( + HDF5_${_lang}_COMPILER_NO_INTERROGATE + HDF5_${_lang}_VERSION + HDF5_${_lang}_IS_PARALLEL) + elseif(_lang STREQUAL "CXX") + _HDF5_test_regular_compiler_CXX( + HDF5_${_lang}_COMPILER_NO_INTERROGATE + HDF5_${_lang}_VERSION + HDF5_${_lang}_IS_PARALLEL) + elseif(_lang STREQUAL "Fortran") + _HDF5_test_regular_compiler_Fortran( + HDF5_${_lang}_COMPILER_NO_INTERROGATE + HDF5_${_lang}_IS_PARALLEL) + else() + continue() + endif() + if(HDF5_${_lang}_COMPILER_NO_INTERROGATE) + if(HDF5_FIND_DEBUG) + message(STATUS "HDF5: Using hdf5 compiler wrapper for all ${_lang} compiling") + endif() + set(HDF5_${_lang}_FOUND TRUE) + set(HDF5_${_lang}_COMPILER_EXECUTABLE_NO_INTERROGATE + "${CMAKE_${_lang}_COMPILER}" + CACHE FILEPATH "HDF5 ${_lang} compiler wrapper") + set(HDF5_${_lang}_DEFINITIONS) + set(HDF5_${_lang}_INCLUDE_DIRS) + set(HDF5_${_lang}_LIBRARIES) + set(HDF5_${_lang}_HL_LIBRARIES) + + mark_as_advanced(HDF5_${_lang}_COMPILER_EXECUTABLE_NO_INTERROGATE) + + set(HDF5_${_lang}_FOUND TRUE) + set(HDF5_HL_FOUND TRUE) + else() + set(HDF5_COMPILER_NO_INTERROGATE FALSE) + # If this language isn't using the wrapper, then try to seed the + # search options with the wrapper + find_program(HDF5_${_lang}_COMPILER_EXECUTABLE + NAMES ${HDF5_${_lang}_COMPILER_NAMES} NAMES_PER_DIR + HINTS ${HDF5_ROOT} + PATH_SUFFIXES bin Bin + DOC "HDF5 ${_lang} Wrapper compiler. Used only to detect HDF5 compile flags." + ${_HDF5_SEARCH_OPTS} + ) + mark_as_advanced( HDF5_${_lang}_COMPILER_EXECUTABLE ) + unset(HDF5_${_lang}_COMPILER_NAMES) + + if(HDF5_${_lang}_COMPILER_EXECUTABLE) + _HDF5_invoke_compiler(${_lang} HDF5_${_lang}_COMPILE_LINE + HDF5_${_lang}_RETURN_VALUE HDF5_${_lang}_VERSION HDF5_${_lang}_IS_PARALLEL) + if(HDF5_${_lang}_RETURN_VALUE EQUAL 0) + if(HDF5_FIND_DEBUG) + message(STATUS "HDF5: Using hdf5 compiler wrapper to determine ${_lang} configuration") + endif() + _HDF5_parse_compile_line( HDF5_${_lang}_COMPILE_LINE + HDF5_${_lang}_INCLUDE_DIRS + HDF5_${_lang}_DEFINITIONS + HDF5_${_lang}_LIBRARY_DIRS + HDF5_${_lang}_LIBRARY_NAMES + HDF5_${_lang}_HL_LIBRARY_NAMES + ) + set(HDF5_${_lang}_LIBRARIES) + + foreach(_lib IN LISTS HDF5_${_lang}_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) + if("x${_lib}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(HDF5_USE_STATIC_LIBRARIES) + if(WIN32) + set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}) + else() + set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}.a) + endif() + endif() + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() + find_library(HDF5_${_lang}_LIBRARY_${_lib} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${_lib} NAMES_PER_DIR + HINTS ${HDF5_${_lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} + ) + unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) + if(HDF5_${_lang}_LIBRARY_${_lib}) + list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${_lang}_LIBRARY_${_lib}}) + else() + list(APPEND HDF5_${_lang}_LIBRARIES ${_lib}) + endif() + endforeach() + if(HDF5_FIND_HL) + set(HDF5_${_lang}_HL_LIBRARIES) + foreach(_lib IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES) + set(_HDF5_SEARCH_NAMES_LOCAL) + if("x${_lib}" MATCHES "hdf5") + # hdf5 library + set(_HDF5_SEARCH_OPTS_LOCAL ${_HDF5_SEARCH_OPTS}) + if(HDF5_USE_STATIC_LIBRARIES) + if(WIN32) + set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}) + else() + set(_HDF5_SEARCH_NAMES_LOCAL lib${_lib}.a) + endif() + endif() + else() + # external library + set(_HDF5_SEARCH_OPTS_LOCAL) + endif() + find_library(HDF5_${_lang}_LIBRARY_${_lib} + NAMES ${_HDF5_SEARCH_NAMES_LOCAL} ${_lib} NAMES_PER_DIR + HINTS ${HDF5_${_lang}_LIBRARY_DIRS} + ${HDF5_ROOT} + ${_HDF5_SEARCH_OPTS_LOCAL} + ) + unset(_HDF5_SEARCH_OPTS_LOCAL) + unset(_HDF5_SEARCH_NAMES_LOCAL) + if(HDF5_${_lang}_LIBRARY_${_lib}) + list(APPEND HDF5_${_lang}_HL_LIBRARIES ${HDF5_${_lang}_LIBRARY_${_lib}}) + else() + list(APPEND HDF5_${_lang}_HL_LIBRARIES ${_lib}) + endif() + endforeach() + set(HDF5_HL_FOUND TRUE) + endif() + + set(HDF5_${_lang}_FOUND TRUE) + if(HDF5_${_lang}_DEFINITIONS) + list(REMOVE_DUPLICATES HDF5_${_lang}_DEFINITIONS) + endif() + if(HDF5_${_lang}_INCLUDE_DIRS) + list(REMOVE_DUPLICATES HDF5_${_lang}_INCLUDE_DIRS) + + set(_TMP_INC_DIR) + foreach( _dir IN LISTS HDF5_${_lang}_INCLUDE_DIRS ) + if( EXISTS "${_dir}" ) + list(APPEND _TMP_INC_DIR "${_dir}") + endif() + endforeach() + set(HDF5_${_lang}_INCLUDE_DIRS ${_TMP_INC_DIR}) + unset(_dir) + unset(_TMP_INC_DIR) + + endif() + else() + set(_HDF5_NEED_TO_SEARCH TRUE) + endif() + else() + set(_HDF5_NEED_TO_SEARCH TRUE) + endif() + endif() + if(HDF5_${_lang}_VERSION) + if(NOT HDF5_VERSION) + set(HDF5_VERSION ${HDF5_${_lang}_VERSION}) + elseif(NOT HDF5_VERSION VERSION_EQUAL HDF5_${_lang}_VERSION) + message(WARNING "HDF5 Version found for language ${_lang}, ${HDF5_${_lang}_VERSION} is different than previously found version ${HDF5_VERSION}") + endif() + endif() + if(DEFINED HDF5_${_lang}_IS_PARALLEL) + if(NOT DEFINED HDF5_IS_PARALLEL) + set(HDF5_IS_PARALLEL ${HDF5_${_lang}_IS_PARALLEL}) + elseif(NOT HDF5_IS_PARALLEL AND HDF5_${_lang}_IS_PARALLEL) + message(WARNING "HDF5 found for language ${_lang} is parallel but previously found language is not parallel.") + elseif(HDF5_IS_PARALLEL AND NOT HDF5_${_lang}_IS_PARALLEL) + message(WARNING "HDF5 found for language ${_lang} is not parallel but previously found language is parallel.") + endif() + endif() + endforeach() + unset(_lib) +else() + set(_HDF5_NEED_TO_SEARCH TRUE) +endif() + +if(NOT HDF5_FOUND AND HDF5_COMPILER_NO_INTERROGATE) + # No arguments necessary, all languages can use the compiler wrappers + set(HDF5_FOUND TRUE) + set(HDF5_METHOD "Included by compiler wrappers") + set(HDF5_REQUIRED_VARS HDF5_METHOD) +elseif(NOT HDF5_FOUND AND NOT _HDF5_NEED_TO_SEARCH) + # Compiler wrappers aren't being used by the build but were found and used + # to determine necessary include and library flags + set(HDF5_INCLUDE_DIRS) + set(HDF5_LIBRARIES) + set(HDF5_HL_LIBRARIES) + foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + if(HDF5_${_lang}_FOUND) + if(NOT HDF5_${_lang}_COMPILER_NO_INTERROGATE) + list(APPEND HDF5_DEFINITIONS ${HDF5_${_lang}_DEFINITIONS}) + list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIRS}) + list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES}) + if(HDF5_FIND_HL) + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_LIBRARIES}) + endif() + endif() + endif() + endforeach() + if (HDF5_DEFINITIONS) + list(REMOVE_DUPLICATES HDF5_DEFINITIONS) + endif() + if (HDF5_INCLUDE_DIRS) + list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS) + + set(_TMP_INC_DIR) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + if( EXISTS "${_dir}" ) + list(APPEND _TMP_INC_DIR "${_dir}") + endif() + endforeach() + set(HDF5_INCLUDE_DIRS ${_TMP_INC_DIR}) + unset(_TMP_INC_DIR) + unset(_dir) + endif() + set(HDF5_FOUND TRUE) + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES) + if(HDF5_FIND_HL) + list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES) + endif() +endif() + +find_program( HDF5_DIFF_EXECUTABLE + NAMES h5diff + HINTS ${HDF5_ROOT} + PATH_SUFFIXES bin Bin + ${_HDF5_SEARCH_OPTS} + DOC "HDF5 file differencing tool." ) +mark_as_advanced( HDF5_DIFF_EXECUTABLE ) + +if( NOT HDF5_FOUND ) + # seed the initial lists of libraries to find with items we know we need + set(HDF5_C_LIBRARY_NAMES hdf5) + set(HDF5_C_HL_LIBRARY_NAMES hdf5_hl ${HDF5_C_LIBRARY_NAMES} ) + + set(HDF5_CXX_LIBRARY_NAMES hdf5_cpp ${HDF5_C_LIBRARY_NAMES}) + set(HDF5_CXX_HL_LIBRARY_NAMES hdf5_hl_cpp ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_CXX_LIBRARY_NAMES}) + + set(HDF5_Fortran_LIBRARY_NAMES hdf5_fortran ${HDF5_C_LIBRARY_NAMES}) + set(HDF5_Fortran_HL_LIBRARY_NAMES hdf5_hl_fortran hdf5hl_fortran ${HDF5_C_HL_LIBRARY_NAMES} ${HDF5_Fortran_LIBRARY_NAMES}) + + # suffixes as seen on Linux, MSYS2, ... + set(_lib_suffixes hdf5) + if(NOT HDF5_PREFER_PARALLEL) + list(APPEND _lib_suffixes hdf5/serial) + endif() + if(HDF5_USE_STATIC_LIBRARIES) + set(_inc_suffixes include/static) + else() + set(_inc_suffixes include/shared) + endif() + + foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + # The "main" library. + set(_hdf5_main_library "") + + # find the HDF5 libraries + foreach(LIB IN LISTS HDF5_${_lang}_LIBRARY_NAMES) + if(HDF5_USE_STATIC_LIBRARIES) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG + lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug + lib${LIB}d-static.a lib${LIB}_debug-static.a ${LIB}d-static ${LIB}_D-static ${LIB}_debug-static ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a lib${LIB} lib${LIB}-static.a ${LIB}-static) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared) + if(WIN32) + list(APPEND HDF5_DEFINITIONS "-DH5_BUILT_AS_DYNAMIC_LIB") + endif() + endif() + find_library(HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + find_library(HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + + # Set the "main" library if not already set. + if (NOT _hdf5_main_library) + if (HDF5_${LIB}_LIBRARY_RELEASE) + set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_RELEASE}") + elseif (HDF5_${LIB}_LIBRARY_DEBUG) + set(_hdf5_main_library "${HDF5_${LIB}_LIBRARY_DEBUG}") + endif () + endif () + + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${_lang}_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + if(HDF5_${_lang}_LIBRARIES) + set(HDF5_${_lang}_FOUND TRUE) + endif() + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_LIBRARIES ${HDF5_${_lang}_LIBRARIES}) + + # find the HDF5 include directories + set(_hdf5_inc_extra_paths) + set(_hdf5_inc_extra_suffixes) + if("${_lang}" STREQUAL "Fortran") + set(HDF5_INCLUDE_FILENAME hdf5.mod HDF5.mod) + + # Add library-based search paths for Fortran modules. + if (NOT _hdf5_main_library STREQUAL "") + # gfortran module directory + if (CMAKE_Fortran_COMPILER_ID STREQUAL "GNU") + get_filename_component(_hdf5_library_dir "${_hdf5_main_library}" DIRECTORY) + list(APPEND _hdf5_inc_extra_paths "${_hdf5_library_dir}") + unset(_hdf5_library_dir) + list(APPEND _hdf5_inc_extra_suffixes gfortran/modules) + endif () + endif () + elseif("${_lang}" STREQUAL "CXX") + set(HDF5_INCLUDE_FILENAME H5Cpp.h) + else() + set(HDF5_INCLUDE_FILENAME hdf5.h) + endif() + + unset(_hdf5_main_library) + + find_path(HDF5_${_lang}_INCLUDE_DIR ${HDF5_INCLUDE_FILENAME} + HINTS ${HDF5_ROOT} + PATHS $ENV{HOME}/.local/include ${_hdf5_inc_extra_paths} + PATH_SUFFIXES include Include ${_inc_suffixes} ${_lib_suffixes} ${_hdf5_inc_extra_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + mark_as_advanced(HDF5_${_lang}_INCLUDE_DIR) + unset(_hdf5_inc_extra_paths) + unset(_hdf5_inc_extra_suffixes) + # set the _DIRS variable as this is what the user will normally use + set(HDF5_${_lang}_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) + list(APPEND HDF5_INCLUDE_DIRS ${HDF5_${_lang}_INCLUDE_DIR}) + + if(HDF5_FIND_HL) + foreach(LIB IN LISTS HDF5_${_lang}_HL_LIBRARY_NAMES) + if(HDF5_USE_STATIC_LIBRARIES) + # According to bug 1643 on the CMake bug tracker, this is the + # preferred method for searching for a static library. + # See https://gitlab.kitware.com/cmake/cmake/-/issues/1643. We search + # first for the full static library name, but fall back to a + # generic search on the name if the static search fails. + set( THIS_LIBRARY_SEARCH_DEBUG + lib${LIB}d.a lib${LIB}_debug.a lib${LIB}d lib${LIB}_D lib${LIB}_debug + lib${LIB}d-static.a lib${LIB}_debug-static.a lib${LIB}d-static lib${LIB}_D-static lib${LIB}_debug-static ) + set( THIS_LIBRARY_SEARCH_RELEASE lib${LIB}.a lib${LIB} lib${LIB}-static.a lib${LIB}-static) + else() + set( THIS_LIBRARY_SEARCH_DEBUG ${LIB}d ${LIB}_D ${LIB}_debug ${LIB}d-shared ${LIB}_D-shared ${LIB}_debug-shared) + set( THIS_LIBRARY_SEARCH_RELEASE ${LIB} ${LIB}-shared) + endif() + find_library(HDF5_${LIB}_LIBRARY_DEBUG + NAMES ${THIS_LIBRARY_SEARCH_DEBUG} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + find_library(HDF5_${LIB}_LIBRARY_RELEASE + NAMES ${THIS_LIBRARY_SEARCH_RELEASE} + HINTS ${HDF5_ROOT} PATH_SUFFIXES lib Lib ${_lib_suffixes} + ${_HDF5_SEARCH_OPTS} + ) + + select_library_configurations( HDF5_${LIB} ) + list(APPEND HDF5_${_lang}_HL_LIBRARIES ${HDF5_${LIB}_LIBRARY}) + endforeach() + + # Append the libraries for this language binding to the list of all + # required libraries. + list(APPEND HDF5_HL_LIBRARIES ${HDF5_${_lang}_HL_LIBRARIES}) + endif() + endforeach() + if(HDF5_FIND_HL AND HDF5_HL_LIBRARIES) + set(HDF5_HL_FOUND TRUE) + endif() + + if(HDF5_DEFINITIONS) + list(REMOVE_DUPLICATES HDF5_DEFINITIONS) + endif() + if( HDF5_INCLUDE_DIRS) + list(REMOVE_DUPLICATES HDF5_INCLUDE_DIRS) + + set(_TMP_INC_DIR) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + if( EXISTS "${_dir}" ) + list(APPEND _TMP_INC_DIR ${_dir}) + endif() + endforeach() + set(HDF5_INCLUDE_DIRS ${_TMP_INC_DIR}) + unset(_TMP_INC_DIR) + unset(_dir) + endif() + + # If the HDF5 include directory was found, open H5pubconf.h to determine if + # HDF5 was compiled with parallel IO support + set( HDF5_IS_PARALLEL FALSE ) + set( HDF5_VERSION "" ) + foreach( _dir IN LISTS HDF5_INCLUDE_DIRS ) + foreach(_hdr "${_dir}/H5pubconf.h" "${_dir}/H5pubconf-64.h" "${_dir}/H5pubconf-32.h") + if( EXISTS "${_hdr}" ) + file( STRINGS "${_hdr}" + HDF5_HAVE_PARALLEL_DEFINE + REGEX "HAVE_PARALLEL 1" ) + if( HDF5_HAVE_PARALLEL_DEFINE ) + set( HDF5_IS_PARALLEL TRUE ) + endif() + unset(HDF5_HAVE_PARALLEL_DEFINE) + + file( STRINGS "${_hdr}" + HDF5_VERSION_DEFINE + REGEX "^[ \t]*#[ \t]*define[ \t]+H5_VERSION[ \t]+" ) + if( "${HDF5_VERSION_DEFINE}" MATCHES + "H5_VERSION[ \t]+\"([0-9]+\\.[0-9]+\\.[0-9]+)(-patch([0-9]+))?\"" ) + set( HDF5_VERSION "${CMAKE_MATCH_1}" ) + if( CMAKE_MATCH_3 ) + set( HDF5_VERSION ${HDF5_VERSION}.${CMAKE_MATCH_3}) + endif() + endif() + unset(HDF5_VERSION_DEFINE) + endif() + endforeach() + endforeach() + unset(_hdr) + unset(_dir) + set( HDF5_IS_PARALLEL ${HDF5_IS_PARALLEL} CACHE BOOL + "HDF5 library compiled with parallel IO support" ) + mark_as_advanced( HDF5_IS_PARALLEL ) + + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS) + if(HDF5_FIND_HL) + list(APPEND HDF5_REQUIRED_VARS HDF5_HL_LIBRARIES) + endif() +endif() + +# For backwards compatibility we set HDF5_INCLUDE_DIR to the value of +# HDF5_INCLUDE_DIRS +if( HDF5_INCLUDE_DIRS ) + set( HDF5_INCLUDE_DIR "${HDF5_INCLUDE_DIRS}" ) +endif() + +# If HDF5_REQUIRED_VARS is empty at this point, then it's likely that +# something external is trying to explicitly pass already found +# locations +if(NOT HDF5_REQUIRED_VARS) + set(HDF5_REQUIRED_VARS HDF5_LIBRARIES HDF5_INCLUDE_DIRS) +endif() + +find_package_handle_standard_args(HDF5 + REQUIRED_VARS ${HDF5_REQUIRED_VARS} + VERSION_VAR HDF5_VERSION + HANDLE_COMPONENTS +) + +unset(_HDF5_SEARCH_OPTS) + +if( HDF5_FOUND AND NOT HDF5_DIR) + # hide HDF5_DIR for the non-advanced user to avoid confusion with + # HDF5_DIR-NOT_FOUND while HDF5 was found. + mark_as_advanced(HDF5_DIR) +endif() + +if (HDF5_FOUND) + if (NOT TARGET HDF5::HDF5) + add_library(HDF5::HDF5 INTERFACE IMPORTED) + string(REPLACE "-D" "" _hdf5_definitions "${HDF5_DEFINITIONS}") + set_target_properties(HDF5::HDF5 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}" + INTERFACE_LINK_LIBRARIES "${HDF5_LIBRARIES}") + unset(_hdf5_definitions) + endif () + + foreach (hdf5_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + if (hdf5_lang STREQUAL "C") + set(hdf5_target_name "hdf5") + elseif (hdf5_lang STREQUAL "CXX") + set(hdf5_target_name "hdf5_cpp") + elseif (hdf5_lang STREQUAL "Fortran") + set(hdf5_target_name "hdf5_fortran") + else () + continue () + endif () + + if (NOT TARGET "hdf5::${hdf5_target_name}") + if (HDF5_COMPILER_NO_INTERROGATE) + add_library("hdf5::${hdf5_target_name}" INTERFACE IMPORTED) + string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_DEFINITIONS}") + set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + else() + if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY") + set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}") + elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY") + set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY}") + elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}") + set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}") + else () + # Error if we still don't have the location. + message(SEND_ERROR + "HDF5 was found, but a different variable was set which contains " + "the location of the `hdf5::${hdf5_target_name}` library.") + endif () + add_library("hdf5::${hdf5_target_name}" UNKNOWN IMPORTED) + string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_DEFINITIONS}") + if (NOT HDF5_${hdf5_lang}_INCLUDE_DIRS) + set(HDF5_${hdf5_lang}_INCLUDE_DIRS ${HDF5_INCLUDE_DIRS}) + endif () + set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES + IMPORTED_LOCATION "${_hdf5_location}" + IMPORTED_IMPLIB "${_hdf5_location}" + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + if (_hdf5_libtype STREQUAL "SHARED") + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND + PROPERTY + INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_DYNAMIC_LIB) + elseif (_hdf5_libtype STREQUAL "STATIC") + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND + PROPERTY + INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_STATIC_LIB) + endif () + unset(_hdf5_definitions) + unset(_hdf5_libtype) + unset(_hdf5_location) + endif () + endif () + + if (NOT HDF5_FIND_HL) + continue () + endif () + + set(hdf5_alt_target_name "") + if (hdf5_lang STREQUAL "C") + set(hdf5_target_name "hdf5_hl") + elseif (hdf5_lang STREQUAL "CXX") + set(hdf5_target_name "hdf5_hl_cpp") + elseif (hdf5_lang STREQUAL "Fortran") + set(hdf5_target_name "hdf5_hl_fortran") + set(hdf5_alt_target_name "hdf5hl_fortran") + else () + continue () + endif () + + if (NOT TARGET "hdf5::${hdf5_target_name}") + if (HDF5_COMPILER_NO_INTERROGATE) + add_library("hdf5::${hdf5_target_name}" INTERFACE IMPORTED) + string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_HL_DEFINITIONS}") + set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_HL_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + else() + if (DEFINED "HDF5_${hdf5_target_name}_LIBRARY") + set(_hdf5_location "${HDF5_${hdf5_target_name}_LIBRARY}") + elseif (DEFINED "HDF5_${hdf5_lang}_HL_LIBRARY") + set(_hdf5_location "${HDF5_${hdf5_lang}_HL_LIBRARY}") + elseif (DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}") + set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_target_name}}") + elseif (hdf5_alt_target_name AND DEFINED "HDF5_${hdf5_lang}_LIBRARY_${hdf5_alt_target_name}") + set(_hdf5_location "${HDF5_${hdf5_lang}_LIBRARY_${hdf5_alt_target_name}}") + else () + # Error if we still don't have the location. + message(SEND_ERROR + "HDF5 was found, but a different variable was set which contains " + "the location of the `hdf5::${hdf5_target_name}` library.") + endif () + add_library("hdf5::${hdf5_target_name}" UNKNOWN IMPORTED) + string(REPLACE "-D" "" _hdf5_definitions "${HDF5_${hdf5_lang}_HL_DEFINITIONS}") + set_target_properties("hdf5::${hdf5_target_name}" PROPERTIES + IMPORTED_LOCATION "${_hdf5_location}" + IMPORTED_IMPLIB "${_hdf5_location}" + INTERFACE_INCLUDE_DIRECTORIES "${HDF5_${hdf5_lang}_HL_INCLUDE_DIRS}" + INTERFACE_COMPILE_DEFINITIONS "${_hdf5_definitions}") + if (_hdf5_libtype STREQUAL "SHARED") + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND + PROPERTY + INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_DYNAMIC_LIB) + elseif (_hdf5_libtype STREQUAL "STATIC") + set_property(TARGET "hdf5::${hdf5_target_name}" APPEND + PROPERTY + INTERFACE_COMPILE_DEFINITIONS H5_BUILT_AS_STATIC_LIB) + endif () + unset(_hdf5_definitions) + unset(_hdf5_libtype) + unset(_hdf5_location) + endif () + endif () + endforeach () + unset(hdf5_lang) + + if (HDF5_DIFF_EXECUTABLE AND NOT TARGET hdf5::h5diff) + add_executable(hdf5::h5diff IMPORTED) + set_target_properties(hdf5::h5diff PROPERTIES + IMPORTED_LOCATION "${HDF5_DIFF_EXECUTABLE}") + endif () +endif () + +if (HDF5_FIND_DEBUG) + message(STATUS "HDF5_DIR: ${HDF5_DIR}") + message(STATUS "HDF5_DEFINITIONS: ${HDF5_DEFINITIONS}") + message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}") + message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}") + message(STATUS "HDF5_HL_LIBRARIES: ${HDF5_HL_LIBRARIES}") + foreach(_lang IN LISTS HDF5_LANGUAGE_BINDINGS) + message(STATUS "HDF5_${_lang}_DEFINITIONS: ${HDF5_${_lang}_DEFINITIONS}") + message(STATUS "HDF5_${_lang}_INCLUDE_DIR: ${HDF5_${_lang}_INCLUDE_DIR}") + message(STATUS "HDF5_${_lang}_INCLUDE_DIRS: ${HDF5_${_lang}_INCLUDE_DIRS}") + message(STATUS "HDF5_${_lang}_LIBRARY: ${HDF5_${_lang}_LIBRARY}") + message(STATUS "HDF5_${_lang}_LIBRARIES: ${HDF5_${_lang}_LIBRARIES}") + message(STATUS "HDF5_${_lang}_HL_LIBRARY: ${HDF5_${_lang}_HL_LIBRARY}") + message(STATUS "HDF5_${_lang}_HL_LIBRARIES: ${HDF5_${_lang}_HL_LIBRARIES}") + endforeach() + message(STATUS "Defined targets (if any):") + foreach(_lang IN ITEMS "" "_cpp" "_fortran") + foreach(_hl IN ITEMS "" "_hl") + foreach(_prefix IN ITEMS "hdf5::" "") + foreach(_suffix IN ITEMS "-static" "-shared" "") + set (_target ${_prefix}hdf5${_hl}${_lang}${_suffix}) + if (TARGET ${_target}) + message(STATUS "... ${_target}") + else() + #message(STATUS "... ${_target} does not exist") + endif() + endforeach() + endforeach() + endforeach() + endforeach() +endif() +unset(_lang) +unset(_HDF5_NEED_TO_SEARCH) diff --git a/cmake/FindSZIP.cmake b/cmake/FindSZIP.cmake new file mode 100644 index 0000000000..f47f34893a --- /dev/null +++ b/cmake/FindSZIP.cmake @@ -0,0 +1,131 @@ +# Included from https://github.com/HDFGroup/hdf5/blob/10450e0491f97d33f2a07076d9346f6fee1c603c/config/cmake_ext_mod/FindSZIP.cmake + +# +# Copyright by The HDF Group. +# All rights reserved. +# +# This file is part of HDF5. The full HDF5 copyright notice, including +# terms governing use, modification, and redistribution, is contained in +# the COPYING file, which can be found at the root of the source code +# distribution tree, or in https://www.hdfgroup.org/licenses. +# If you do not have access to either file, you may request a copy from +# help@hdfgroup.org. +# +######################################################################### + +# - Derived from the FindTiff.cmake and FindJPEG.cmake that is included with cmake +# FindSZIP + +# Find the native SZIP includes and library + +# Imported targets +################## + +# This module defines the following :prop_tgt:`IMPORTED` targets: +# +# SZIP::SZIP +# The SZIP library, if found. +# +# Result variables +################### + +# This module will set the following variables in your project: + +# SZIP_FOUND, true if the SZIP headers and libraries were found. +# SZIP_INCLUDE_DIR, the directory containing the SZIP headers. +# SZIP_INCLUDE_DIRS, the directory containing the SZIP headers. +# SZIP_LIBRARIES, libraries to link against to use SZIP. + +# Cache variables +################# + +# The following variables may also be set: + +# SZIP_LIBRARY, where to find the SZIP library. +# SZIP_LIBRARY_DEBUG - Debug version of SZIP library +# SZIP_LIBRARY_RELEASE - Release Version of SZIP library + +# message (STATUS "Finding SZIP library and headers..." ) +######################################################################### + + +find_path(SZIP_INCLUDE_DIR szlib.h) + +set(szip_names ${SZIP_NAMES} sz szip szip-static libsz libszip libszip-static) +foreach(name ${szip_names}) + list (APPEND szip_names_debug "${name}d") +endforeach() + +if(NOT SZIP_LIBRARY) + find_library(SZIP_LIBRARY_RELEASE NAMES ${szip_names}) + find_library(SZIP_LIBRARY_DEBUG NAMES ${szip_names_debug}) + include(SelectLibraryConfigurations) + select_library_configurations(SZIP) + mark_as_advanced(SZIP_LIBRARY_RELEASE SZIP_LIBRARY_DEBUG) +endif() +unset(szip_names) +unset(szip_names_debug) + +if(SZIP_INCLUDE_DIR AND EXISTS "${SZIP_INCLUDE_DIR}/SZconfig.h") + file(STRINGS "${SZIP_INCLUDE_DIR}/SZconfig.h" szip_version_str + REGEX "^#define[\t ]+SZIP_PACKAGE_VERSION[\t ]+.*") + + string(REGEX REPLACE "^#define[\t ]+SZIP_PACKAGE_VERSION[\t ]+([0-9]+).*" + "\\1" SZIP_VERSION "${szip_version_str}") + unset(szip_version_str) +endif() + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SZIP + REQUIRED_VARS SZIP_LIBRARY SZIP_INCLUDE_DIR + VERSION_VAR SZIP_VERSION) + +if(SZIP_FOUND) + set(SZIP_LIBRARIES ${SZIP_LIBRARY}) + set(SZIP_INCLUDE_DIRS "${SZIP_INCLUDE_DIR}") + + if(NOT TARGET SZIP::SZIP) + add_library(SZIP::SZIP UNKNOWN IMPORTED) + if(SZIP_INCLUDE_DIRS) + set_target_properties(SZIP::SZIP PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${SZIP_INCLUDE_DIRS}") + endif() + if(EXISTS "${SZIP_LIBRARY}") + set_target_properties(SZIP::SZIP PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES "C" + IMPORTED_LOCATION "${SZIP_LIBRARY}") + endif() + if(EXISTS "${SZIP_LIBRARY_RELEASE}") + set_property(TARGET SZIP::SZIP APPEND PROPERTY + IMPORTED_CONFIGURATIONS RELEASE) + set_target_properties(SZIP::SZIP PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C" + IMPORTED_LOCATION_RELEASE "${SZIP_LIBRARY_RELEASE}") + endif() + if(EXISTS "${SZIP_LIBRARY_DEBUG}") + set_property(TARGET SZIP::SZIP APPEND PROPERTY + IMPORTED_CONFIGURATIONS DEBUG) + set_target_properties(SZIP::SZIP PROPERTIES + IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C" + IMPORTED_LOCATION_DEBUG "${SZIP_LIBRARY_DEBUG}") + endif() + endif() +endif() + +mark_as_advanced(SZIP_LIBRARY SZIP_INCLUDE_DIR) + +# Report the results. +if (NOT SZIP_FOUND) + set (SZIP_DIR_MESSAGE + "SZip was not found. Make sure SZIP_LIBRARY and SZIP_INCLUDE_DIR are set or set the SZIP_INSTALL environment variable." + ) + if (NOT SZIP_FIND_QUIETLY) + if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.15.0") + message (VERBOSE "${SZIP_DIR_MESSAGE}") + endif () + else () + if (SZIP_FIND_REQUIRED) + message (FATAL_ERROR "SZip was NOT found and is Required by this project") + endif () + endif () +endif () diff --git a/cmake/HDF5LibraryConfig.cmake b/cmake/HDF5LibraryConfig.cmake index d02025ca68..c05fe75fa1 100644 --- a/cmake/HDF5LibraryConfig.cmake +++ b/cmake/HDF5LibraryConfig.cmake @@ -1,4 +1,4 @@ -if(WITH_MPI) +if(H5CPP_WITH_MPI) set(HDF5_PREFER_PARALLEL TRUE) endif() @@ -15,11 +15,8 @@ message(STATUS "Found HDF5 HDF5_VERSION = ${HDF5_VERSION}") message(STATUS "Found HDF5 HDF5_IS_PARALLEL = ${HDF5_IS_PARALLEL}") message(STATUS "==============================================================") -if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) - add_definitions(-DH5_BUILT_AS_DYNAMIC_LIB) -endif() -if(WITH_MPI) +if(H5CPP_WITH_MPI) if(NOT HDF5_IS_PARALLEL) message(FATAL_ERROR "The HDF5 version found does not support MPI") endif() diff --git a/cmake/MPIConfig.cmake b/cmake/MPIConfig.cmake index d3bda8a6c4..d5cd0663bf 100644 --- a/cmake/MPIConfig.cmake +++ b/cmake/MPIConfig.cmake @@ -1,12 +1,8 @@ -option(WITH_MPI "Enable MPI support" OFF) +option(H5CPP_WITH_MPI "Enable MPI support" OFF) -if (WITH_MPI) +if (H5CPP_WITH_MPI) if (CMAKE_SYSTEM_NAME MATCHES Windows) - message(FATAL_ERROR "MPI not supported on the Windows platform!") - endif () - - if (CMAKE_SYSTEM_NAME MATCHES Darwin) - message(FATAL_ERROR "MPI not supported for OSX") + h5cpp_message(FATAL_ERROR "MPI not supported on the Windows platform!") endif () if(CMAKE_CXX_COMPILER_ID MATCHES GNU) @@ -14,7 +10,7 @@ if (WITH_MPI) endif() find_package(MPI REQUIRED) - message(STATUS "Found MPI headers in: ${MPI_C_INCLUDE_PATH}") - message(STATUS "Found MPI libraries: ${MPI_C_LIBRARIES}") + h5cpp_message(STATUS "Found MPI headers in: ${MPI_C_INCLUDE_PATH}") + h5cpp_message(STATUS "Found MPI libraries: ${MPI_C_LIBRARIES}") endif () diff --git a/cmake/utilities.cmake b/cmake/utilities.cmake index d53ed05803..f5751ccfb8 100644 --- a/cmake/utilities.cmake +++ b/cmake/utilities.cmake @@ -2,10 +2,13 @@ # some utility functions which make life easier # -function(copy_to_current_build) +function(H5CPP_MESSAGE LEVEL) + message(${LEVEL} "H5CPP: ${ARGN}") +endfunction() +function(copy_to_current_build) foreach(f ${ARGV}) configure_file(${f} ${f} COPYONLY) endforeach() - + endfunction() diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000000..bd29e8417a --- /dev/null +++ b/conanfile.py @@ -0,0 +1,50 @@ +from conans import ConanFile, CMake, tools + + +class H5CppConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "cmake", "cmake_find_package" + options = { + "shared": [True, False], + "fPIC": [True, False], + "with_mpi": [True, False], + "with_boost": [True, False] + } + default_options = { + "shared": False, + "fPIC": True, + "with_mpi": False, + "with_boost": True, + "hdf5:hl": True, + "hdf5:enable_cxx": False + } + + def build_requirements(self): + self.build_requires("catch2/2.13.7") + self.build_requires("ninja/1.10.2") + + def config_options(self): + if self.settings.os == "Windows": + del self.options.with_mpi + + def configure(self): + if self.options.get_safe("with_mpi", False): + self.options["hdf5"].parallel = True + + def requirements(self): + self.requires("hdf5/1.12.0") + if self.options.with_boost: + self.requires("boost/1.77.0") + if self.options.get_safe("with_mpi", False): + self.requires("openmpi/4.1.0") + + def build(self): + cmake = CMake(self) + cmake.definitions.update({ + "H5CPP_CONAN": "MANUAL", + "H5CPP_WITH_MPI": self.options.get_safe("with_mpi", False), + "H5CPP_WITH_BOOST": self.options.with_boost + }) + with tools.run_environment(self): + cmake.configure() + cmake.build() diff --git a/conanfile_1.12.0.txt b/conanfile_1.12.0.txt index fb348cef02..20746cc25a 100644 --- a/conanfile_1.12.0.txt +++ b/conanfile_1.12.0.txt @@ -4,6 +4,7 @@ boost/1.69.0 hdf5/1.12.0 zlib/1.2.11 bzip2/1.0.8 +catch2/2.13.7 [generators] cmake_paths diff --git a/conanfile_ess.txt b/conanfile_ess.txt index 2b2b4442df..af6d320ed1 100644 --- a/conanfile_ess.txt +++ b/conanfile_ess.txt @@ -3,6 +3,7 @@ boost/1.69.0 hdf5/1.10.6 zlib/1.2.11 bzip2/1.0.8 +catch2/2.13.7 [generators] cmake_paths diff --git a/conanfile_ess_mpi.txt b/conanfile_ess_mpi.txt index 924138bb84..b089fd7084 100644 --- a/conanfile_ess_mpi.txt +++ b/conanfile_ess_mpi.txt @@ -1,8 +1,9 @@ [requires] boost/1.69.0 hdf5/1.10.5-dm2@ess-dmsc/stable -zlib/1.2.11 +zlib/1.2.11@conan/stable bzip2/1.0.8 +catch2/2.13.7 [generators] cmake_paths diff --git a/conanfile_macos.txt b/conanfile_macos.txt index 2b2b4442df..af6d320ed1 100644 --- a/conanfile_macos.txt +++ b/conanfile_macos.txt @@ -3,6 +3,7 @@ boost/1.69.0 hdf5/1.10.6 zlib/1.2.11 bzip2/1.0.8 +catch2/2.13.7 [generators] cmake_paths diff --git a/conanfile_windows_ess.txt b/conanfile_windows_ess.txt index 7a8672ca7d..05c20ef110 100644 --- a/conanfile_windows_ess.txt +++ b/conanfile_windows_ess.txt @@ -3,6 +3,7 @@ boost/1.69.0 hdf5/1.10.5-dm2@ess-dmsc/stable zlib/1.2.11 bzip2/1.0.8 +catch2/2.13.7 [generators] cmake_paths diff --git a/doc/source/users_guide/installing.rst b/doc/source/users_guide/installing.rst index c6c3a38839..92de70576e 100644 --- a/doc/source/users_guide/installing.rst +++ b/doc/source/users_guide/installing.rst @@ -71,7 +71,7 @@ which should do the job provided that all dependencies are installed in standard locations. We strongly recommend to set the particular build configuration with the :envvar:`CMAKE_BUILD_TYPE` variable. -To attempt to build without Boost, additionally specify `-DWITH_BOOST=OFF`. +To attempt to build without Boost, additionally specify `-DH5CPP_WITH_BOOST=OFF`. This requires a recent compiler, for example gcc >8, with filesystem in the std or std::experimental namespace. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index d685d5574c..4ebe79ecf6 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -5,35 +5,35 @@ set(CMAKE_CXX_STANDARD 11) find_package(h5cpp REQUIRED) add_executable(basic_files basic_files.cpp) -target_link_libraries(basic_files h5cpp) +target_link_libraries(basic_files PRIVATE h5cpp::h5cpp) add_executable(selecting_datasets selecting_datasets.cpp) -target_link_libraries(selecting_datasets h5cpp) +target_link_libraries(selecting_datasets PRIVATE h5cpp::h5cpp) add_executable(std_vector_io std_vector_io.cpp) -target_link_libraries(std_vector_io h5cpp) +target_link_libraries(std_vector_io PRIVATE h5cpp::h5cpp) add_executable(complex_io complex_io.cpp) -target_link_libraries(complex_io h5cpp) +target_link_libraries(complex_io PRIVATE h5cpp::h5cpp) add_executable(writing_image writing_image.cpp rgbpixel.cpp) -target_link_libraries(writing_image h5cpp) +target_link_libraries(writing_image PRIVATE h5cpp::h5cpp) add_executable(write_single_vector write_single_vector.cpp) -target_link_libraries(write_single_vector h5cpp) +target_link_libraries(write_single_vector PRIVATE h5cpp::h5cpp) add_executable(read_dataset read_dataset.cpp) -target_link_libraries(read_dataset h5cpp) +target_link_libraries(read_dataset PRIVATE h5cpp::h5cpp) add_executable(append_scalar_data append_scalar_data.cpp) -target_link_libraries(append_scalar_data h5cpp) +target_link_libraries(append_scalar_data PRIVATE h5cpp::h5cpp) add_executable(write_vector_list write_vector_list.cpp) -target_link_libraries(write_vector_list h5cpp) +target_link_libraries(write_vector_list PRIVATE h5cpp::h5cpp) add_executable(append_vector_data append_vector_data.cpp) -target_link_libraries(append_vector_data h5cpp) +target_link_libraries(append_vector_data PRIVATE h5cpp::h5cpp) add_custom_target(examples) diff --git a/examples/attributes/CMakeLists.txt b/examples/attributes/CMakeLists.txt index cb7513048f..423f6c97ea 100644 --- a/examples/attributes/CMakeLists.txt +++ b/examples/attributes/CMakeLists.txt @@ -1,8 +1,8 @@ add_executable(attribute_creation attribute_creation.cpp) -target_link_libraries(attribute_creation h5cpp) +target_link_libraries(attribute_creation PRIVATE h5cpp::h5cpp) add_executable(attribute_iteration attribute_iteration.cpp) -target_link_libraries(attribute_iteration h5cpp) +target_link_libraries(attribute_iteration PRIVATE h5cpp::h5cpp) add_executable(attribute_io attribute_io.cpp) -target_link_libraries(attribute_io h5cpp) \ No newline at end of file +target_link_libraries(attribute_io PRIVATE h5cpp::h5cpp) \ No newline at end of file diff --git a/examples/mpi/CMakeLists.txt b/examples/mpi/CMakeLists.txt index 2feb4f9f98..8a79d3b679 100644 --- a/examples/mpi/CMakeLists.txt +++ b/examples/mpi/CMakeLists.txt @@ -1,10 +1,8 @@ - add_executable(writer_simple writer.cpp) -target_link_libraries(writer_simple h5cpp) - +target_link_libraries(writer_simple PRIVATE h5cpp::h5cpp) add_executable(writer_extend writer_extend.cpp) -target_link_libraries(writer_extend h5cpp) +target_link_libraries(writer_extend PRIVATE h5cpp::h5cpp) add_dependencies(examples writer_simple diff --git a/examples/swmr/CMakeLists.txt b/examples/swmr/CMakeLists.txt index 9206432ef6..8c20abac96 100644 --- a/examples/swmr/CMakeLists.txt +++ b/examples/swmr/CMakeLists.txt @@ -1,9 +1,9 @@ set(SWMR_SOURCES swmr_environment.cpp swmr_builder.cpp) add_executable(swmr_write swmr_write.cpp ${SWMR_SOURCES}) -target_link_libraries(swmr_write h5cpp) +target_link_libraries(swmr_write PRIVATE h5cpp::h5cpp) add_executable(swmr_read swmr_reader.cpp ${SWMR_SOURCES}) -target_link_libraries(swmr_read h5cpp) +target_link_libraries(swmr_read PRIVATE h5cpp::h5cpp) add_dependencies(examples swmr_write diff --git a/examples/useage/CMakeLists.txt b/examples/useage/CMakeLists.txt index cb2b1538e0..02df445601 100644 --- a/examples/useage/CMakeLists.txt +++ b/examples/useage/CMakeLists.txt @@ -3,7 +3,7 @@ project("usingh5cpp") find_package(h5cpp REQUIRED) add_library(core SHARED core.cpp) -target_link_libraries(core PUBLIC h5cpp) +target_link_libraries(core PUBLIC h5cpp::h5cpp) add_executable(app app.cpp) target_link_libraries(app PRIVATE core) \ No newline at end of file diff --git a/h5cpp-config.cmake.in b/h5cpp-config.cmake.in index 19053d587e..5fab920064 100644 --- a/h5cpp-config.cmake.in +++ b/h5cpp-config.cmake.in @@ -2,10 +2,10 @@ # add some additional information via cached variables # -set(H5CPP_MPI_ENABLED @WITH_MPI@ CACHE BOOL "h5cpp was built with MPI support") -set(H5CPP_SWMR_ENABLED @WITH_SWMR@ CACHE BOOL "h5cpp was built with SMWR support") -set(H5CPP_VDS_ENABLED @WITH_VDS@ CACHE BOOL "h5cpp was built with VDS support") -set(H5CPP_BOOST_ENABLED @WITH_BOOST@ CACHE BOOL "h5cpp was built against boost") +set(H5CPP_MPI_ENABLED @H5CPP_WITH_MPI@ CACHE BOOL "h5cpp was built with MPI support") +set(H5CPP_SWMR_ENABLED @H5CPP_WITH_SWMR@ CACHE BOOL "h5cpp was built with SMWR support") +set(H5CPP_VDS_ENABLED @H5CPP_WITH_VDS@ CACHE BOOL "h5cpp was built with VDS support") +set(H5CPP_BOOST_ENABLED @H5CPP_WITH_BOOST@ CACHE BOOL "h5cpp was built against boost") # # checking for the Boost library @@ -33,7 +33,7 @@ endif() # # checking for hdf5 # -set(HDF5_PREFER_PARALLEL @WITH_MPI@) +set(HDF5_PREFER_PARALLEL @H5CPP_WITH_MPI@) find_package(HDF5 @HDF5_VERSION@ EXACT REQUIRED COMPONENTS C) # diff --git a/ide/vscode/cmake-variants.yaml b/ide/vscode/cmake-variants.yaml index fba79b5a65..7d028593d4 100644 --- a/ide/vscode/cmake-variants.yaml +++ b/ide/vscode/cmake-variants.yaml @@ -19,12 +19,12 @@ mpi: short: without MPI long: build with the serial version of the HDF5 library settings: - WITH_MPI: OFF + H5CPP_WITH_MPI: OFF withmpi: short: with MPI long: bulid using the installed MPI flavor settings: - WITH_MPI: ON + H5CPP_WITH_MPI: ON filesystem: default: boostfs @@ -34,12 +34,12 @@ filesystem: short: boost::filesystem long: use boos filesystem implementation settings: - WITH_BOOST: ON + H5CPP_WITH_BOOST: ON stdfs: short: std::filesystem long: use the C++ standard library filesystem implementation settings: - WITH_BOOST: OFF + H5CPP_WITH_BOOST: OFF conan: @@ -50,9 +50,9 @@ conan: short: without conan long: all dependencies must be provided by the OS environment settings: - CONAN: DISABLE + H5CPP_CONAN: DISABLE 'auto': short: with conan long: all dependencies will be satisifed by conan settings: - CONAN: AUTO \ No newline at end of file + H5CPP_CONAN: AUTO \ No newline at end of file diff --git a/meson.build b/meson.build index fbd67a7979..d88cabfac3 100644 --- a/meson.build +++ b/meson.build @@ -6,7 +6,7 @@ h5cpp_dependencies = [] # ----------------------------------------------------------------------------- if get_option('with-mpi') h5cpp_dependencies += dependency('mpi-cxx', method: 'pkg-config') - add_project_arguments('-DWITH_MPI', language: 'cpp') + add_project_arguments('-DH5CPP_WITH_MPI', language: 'cpp') endif # ----------------------------------------------------------------------------- @@ -20,7 +20,7 @@ h5cpp_dependencies += dependency('hdf5', language: 'c') boost_modules = ['system'] if get_option('with-boostfilesystem') boost_modules += 'filesystem' - add_project_arguments('-DWITH_BOOST', language: 'cpp') + add_project_arguments('-DH5CPP_WITH_BOOST', language: 'cpp') summary() endif diff --git a/src/h5cpp/CMakeLists.txt b/src/h5cpp/CMakeLists.txt index 7d98ed6339..a0ccf7cde1 100644 --- a/src/h5cpp/CMakeLists.txt +++ b/src/h5cpp/CMakeLists.txt @@ -20,45 +20,34 @@ add_subdirectory(utilities) add_doxygen_source_deps(${h5cpp_headers}) -add_library(h5cpp SHARED +add_library(h5cpp ${h5cpp_sources} ${h5cpp_headers} ) +add_library(h5cpp::h5cpp ALIAS h5cpp) add_doxygen_source_deps(${h5cpp_headers}) -target_compile_definitions(h5cpp PRIVATE DLL_BUILD) +if (H5CPP_BUILD_SHARED) + target_compile_definitions(h5cpp PRIVATE H5CPP_EXPORTS PUBLIC H5CPP_BUILD_SHARED) +endif() + set(H5CPP_LINKS ${MPI_CXX_LIBRARIES}) -if(WITH_BOOST) +if(H5CPP_WITH_BOOST) list(APPEND H5CPP_LINKS Boost::filesystem Boost::system) -elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # Link stdc++fs or c++experimental to get std::experimental::filesystem when necessary - list(APPEND H5CPP_LINKS stdc++fs) -elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0 AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") - list(APPEND H5CPP_LINKS c++fs) +else() + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.1 AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + # Link stdc++fs or c++experimental to get std::experimental::filesystem when necessary + list(APPEND H5CPP_LINKS stdc++fs) + elseif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11 AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + list(APPEND H5CPP_LINKS c++fs) + else() + target_compile_features(h5cpp PUBLIC cxx_std_17) + endif() endif() -# -# remove the absolute path from the library name -# -set(H5CPP_INTERFACE_LIBS) -set(H5CPP_PRIVATE_LIBS ${HDF5_LIBRARIES}) -foreach(HDF5_LIBRARY ${HDF5_LIBRARIES}) - get_filename_component(LIB_NAME ${HDF5_LIBRARY} NAME) - list(APPEND H5CPP_INTERFACE_LIBS ${LIB_NAME}) -endforeach() - -set(H5CPP_HL_PRIVATE_LIBS ${HDF5_HL_LIBRARIES}) -foreach(HDF5_LIBRARY ${HDF5_HL_LIBRARIES}) - get_filename_component(LIB_NAME ${HDF5_LIBRARY} NAME) - list(APPEND H5CPP_INTERFACE_LIBS ${LIB_NAME}) -endforeach() - - target_include_directories(h5cpp PRIVATE ${PROJECT_SOURCE_DIR}/src - PUBLIC ${HDF5_INCLUDE_DIRS} - PUBLIC ${MPI_CXX_INCLUDE_PATH} INTERFACE $ INTERFACE $ ) @@ -66,8 +55,8 @@ target_include_directories(h5cpp # # THIS IS BAD # NEED TO GET RID OF THIS -if (WITH_MPI) - target_compile_definitions(h5cpp PUBLIC WITH_MPI) +if (H5CPP_WITH_MPI) + target_compile_definitions(h5cpp PUBLIC H5CPP_WITH_MPI) endif () set_target_properties(h5cpp @@ -80,9 +69,20 @@ set_target_properties(h5cpp enable_coverage(h5cpp) +set(H5CPP_FILTER_TARGETS ZLIB::ZLIB) +if (TARGET SZIP::SZIP) + list(APPEND H5CPP_FILTER_TARGETS SZIP::SZIP) +endif() + target_link_libraries(h5cpp - PUBLIC ${H5CPP_LINKS} - PRIVATE ${COVERAGE_LIBRARIES} ${H5CPP_PRIVATE_LIBS} ${H5CPP_HL_PRIVATE_LIBS} + PUBLIC + ${H5CPP_LINKS} + PRIVATE ${COVERAGE_LIBRARIES} + hdf5::hdf5_hl + hdf5::hdf5 + Threads::Threads + ${H5CPP_FILTER_TARGETS} + ${CMAKE_DL_LIBS} INTERFACE ${H5CPP_INTERFACE_LIBS}) include(GNUInstallDirs) #Required for CMAKE_INSTALL_XXX @@ -97,6 +97,7 @@ install(TARGETS h5cpp install(EXPORT h5cpp_targets DESTINATION ${CMAKE_INSTALL_PACKAGEDIR} + NAMESPACE h5cpp:: COMPONENT development) # ============================================================================= @@ -138,7 +139,7 @@ function(GET_LIBRARY_NAME LIB) endfunction(GET_LIBRARY_NAME) -if(${CONAN} MATCHES "DISABLE") +if(${H5CPP_CONAN} MATCHES "DISABLE") get_target_property(LIBRARIES h5cpp INTERFACE_LINK_LIBRARIES) get_target_property(DEFINITIONS h5cpp INTERFACE_COMPILE_DEFINITIONS) @@ -183,7 +184,7 @@ if(${CONAN} MATCHES "DISABLE") endforeach() - message("Linke libraries: ${PKG_CONFIG_LIBS}") + message("Link libraries: ${PKG_CONFIG_LIBS}") message("Library paths: ${PKG_CONFIG_LINKFLAGS}") diff --git a/src/h5cpp/core/filesystem.hpp b/src/h5cpp/core/filesystem.hpp index dcd5ee3c49..f0876e6b1a 100644 --- a/src/h5cpp/core/filesystem.hpp +++ b/src/h5cpp/core/filesystem.hpp @@ -2,7 +2,7 @@ #include -#ifdef WITH_BOOST +#ifdef H5CPP_WITH_BOOST #include namespace fs = boost::filesystem; #else diff --git a/src/h5cpp/core/hdf5_capi.hpp b/src/h5cpp/core/hdf5_capi.hpp index d5c3b97248..e18ac1be93 100644 --- a/src/h5cpp/core/hdf5_capi.hpp +++ b/src/h5cpp/core/hdf5_capi.hpp @@ -29,7 +29,7 @@ // // This hack is necessary to get MPI, HDF5 and C++ build together // -#ifdef WITH_MPI +#ifdef H5CPP_WITH_MPI #include #endif diff --git a/src/h5cpp/core/windows.hpp b/src/h5cpp/core/windows.hpp index bfaa7e8349..b1e8b139a4 100644 --- a/src/h5cpp/core/windows.hpp +++ b/src/h5cpp/core/windows.hpp @@ -25,14 +25,18 @@ // #pragma once -#ifdef _MSC_VER - #ifdef DLL_BUILD - #define DLL_EXPORT __declspec(dllexport) - #else - #define DLL_EXPORT __declspec(dllimport) - #endif -#else +#ifndef H5CPP_BUILD_SHARED #define DLL_EXPORT +#else + #ifdef _MSC_VER + #ifdef H5CPP_EXPORTS + #define DLL_EXPORT __declspec(dllexport) + #else + #define DLL_EXPORT __declspec(dllimport) + #endif + #else + #define DLL_EXPORT + #endif #endif #ifdef _MSC_VER diff --git a/src/h5cpp/core/with_boost.hpp.in b/src/h5cpp/core/with_boost.hpp.in index c9ce1e9166..5615c38dd2 100644 --- a/src/h5cpp/core/with_boost.hpp.in +++ b/src/h5cpp/core/with_boost.hpp.in @@ -1,3 +1,3 @@ #pragma once -#cmakedefine WITH_BOOST +#cmakedefine H5CPP_WITH_BOOST diff --git a/src/h5cpp/file/mpi_driver.cpp b/src/h5cpp/file/mpi_driver.cpp index 6fd24f980d..a439f0bd91 100644 --- a/src/h5cpp/file/mpi_driver.cpp +++ b/src/h5cpp/file/mpi_driver.cpp @@ -31,7 +31,7 @@ namespace hdf5 { namespace file { -#ifdef WITH_MPI +#ifdef H5CPP_WITH_MPI MPIDriver::MPIDriver(MPI_Comm comm,MPI_Info info): comm_(comm), diff --git a/src/h5cpp/file/mpi_driver.hpp b/src/h5cpp/file/mpi_driver.hpp index a3040c608a..51590489b1 100644 --- a/src/h5cpp/file/mpi_driver.hpp +++ b/src/h5cpp/file/mpi_driver.hpp @@ -30,7 +30,7 @@ namespace hdf5 { namespace file { -#if ( defined(_DOXYGEN_) || defined(WITH_MPI) ) +#if ( defined(_DOXYGEN_) || defined(H5CPP_WITH_MPI) ) //! //! \brief class for the MPI driver (*for hdf5 with compiled MPI*) diff --git a/src/h5cpp/property/dataset_transfer.cpp b/src/h5cpp/property/dataset_transfer.cpp index 3858726898..9d845b66a0 100644 --- a/src/h5cpp/property/dataset_transfer.cpp +++ b/src/h5cpp/property/dataset_transfer.cpp @@ -48,7 +48,7 @@ DatasetTransferList::DatasetTransferList(ObjectHandle &&handle, bool do_check): } } -#ifdef WITH_MPI +#ifdef H5CPP_WITH_MPI std::ostream &operator<<(std::ostream &stream,const MPITransferMode &mode) { diff --git a/src/h5cpp/property/dataset_transfer.hpp b/src/h5cpp/property/dataset_transfer.hpp index 2a4743cf6c..d09393e39f 100644 --- a/src/h5cpp/property/dataset_transfer.hpp +++ b/src/h5cpp/property/dataset_transfer.hpp @@ -33,7 +33,7 @@ namespace hdf5 { namespace property { -#if (defined(_DOXYGEN_) || defined(WITH_MPI)) +#if (defined(_DOXYGEN_) || defined(H5CPP_WITH_MPI)) enum class MPITransferMode : std::underlying_type::type { Independent = H5FD_MPIO_INDEPENDENT, @@ -90,10 +90,11 @@ class DLL_EXPORT DatasetTransferList : public List { return dtpl_; } -#if (defined(_DOXYGEN_) || defined(WITH_MPI) ) +#if (defined(_DOXYGEN_) || defined(H5CPP_WITH_MPI) ) //! //! \brief set mpi transfer mode (*for hdf5 compiled with MPI*) //! + void mpi_transfer_mode(MPITransferMode mode) const; //! //! \brief get mpi transfer mode (*for hdf5 compiled with MPI*) diff --git a/subprojects/catch2/cmake/Catch.cmake b/subprojects/catch2/cmake/Catch.cmake deleted file mode 100644 index b3f90a79e8..0000000000 --- a/subprojects/catch2/cmake/Catch.cmake +++ /dev/null @@ -1,205 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -Catch ------ - -This module defines a function to help use the Catch test framework. - -The :command:`catch_discover_tests` discovers tests by asking the compiled test -executable to enumerate its tests. This does not require CMake to be re-run -when tests change. However, it may not work in a cross-compiling environment, -and setting test properties is less convenient. - -This command is intended to replace use of :command:`add_test` to register -tests, and will create a separate CTest test for each Catch test case. Note -that this is in some cases less efficient, as common set-up and tear-down logic -cannot be shared by multiple test cases executing in the same instance. -However, it provides more fine-grained pass/fail information to CTest, which is -usually considered as more beneficial. By default, the CTest test name is the -same as the Catch name; see also ``TEST_PREFIX`` and ``TEST_SUFFIX``. - -.. command:: catch_discover_tests - - Automatically add tests with CTest by querying the compiled test executable - for available tests:: - - catch_discover_tests(target - [TEST_SPEC arg1...] - [EXTRA_ARGS arg1...] - [WORKING_DIRECTORY dir] - [TEST_PREFIX prefix] - [TEST_SUFFIX suffix] - [PROPERTIES name1 value1...] - [TEST_LIST var] - [REPORTER reporter] - [OUTPUT_DIR dir] - [OUTPUT_PREFIX prefix} - [OUTPUT_SUFFIX suffix] - ) - - ``catch_discover_tests`` sets up a post-build command on the test executable - that generates the list of tests by parsing the output from running the test - with the ``--list-test-names-only`` argument. This ensures that the full - list of tests is obtained. Since test discovery occurs at build time, it is - not necessary to re-run CMake when the list of tests changes. - However, it requires that :prop_tgt:`CROSSCOMPILING_EMULATOR` is properly set - in order to function in a cross-compiling environment. - - Additionally, setting properties on tests is somewhat less convenient, since - the tests are not available at CMake time. Additional test properties may be - assigned to the set of tests as a whole using the ``PROPERTIES`` option. If - more fine-grained test control is needed, custom content may be provided - through an external CTest script using the :prop_dir:`TEST_INCLUDE_FILES` - directory property. The set of discovered tests is made accessible to such a - script via the ``_TESTS`` variable. - - The options are: - - ``target`` - Specifies the Catch executable, which must be a known CMake executable - target. CMake will substitute the location of the built executable when - running the test. - - ``TEST_SPEC arg1...`` - Specifies test cases, wildcarded test cases, tags and tag expressions to - pass to the Catch executable with the ``--list-test-names-only`` argument. - - ``EXTRA_ARGS arg1...`` - Any extra arguments to pass on the command line to each test case. - - ``WORKING_DIRECTORY dir`` - Specifies the directory in which to run the discovered test cases. If this - option is not provided, the current binary directory is used. - - ``TEST_PREFIX prefix`` - Specifies a ``prefix`` to be prepended to the name of each discovered test - case. This can be useful when the same test executable is being used in - multiple calls to ``catch_discover_tests()`` but with different - ``TEST_SPEC`` or ``EXTRA_ARGS``. - - ``TEST_SUFFIX suffix`` - Similar to ``TEST_PREFIX`` except the ``suffix`` is appended to the name of - every discovered test case. Both ``TEST_PREFIX`` and ``TEST_SUFFIX`` may - be specified. - - ``PROPERTIES name1 value1...`` - Specifies additional properties to be set on all tests discovered by this - invocation of ``catch_discover_tests``. - - ``TEST_LIST var`` - Make the list of tests available in the variable ``var``, rather than the - default ``_TESTS``. This can be useful when the same test - executable is being used in multiple calls to ``catch_discover_tests()``. - Note that this variable is only available in CTest. - - ``REPORTER reporter`` - Use the specified reporter when running the test case. The reporter will - be passed to the Catch executable as ``--reporter reporter``. - - ``OUTPUT_DIR dir`` - If specified, the parameter is passed along as - ``--out dir/`` to Catch executable. The actual file name is the - same as the test name. This should be used instead of - ``EXTRA_ARGS --out foo`` to avoid race conditions writing the result output - when using parallel test execution. - - ``OUTPUT_PREFIX prefix`` - May be used in conjunction with ``OUTPUT_DIR``. - If specified, ``prefix`` is added to each output file name, like so - ``--out dir/prefix``. - - ``OUTPUT_SUFFIX suffix`` - May be used in conjunction with ``OUTPUT_DIR``. - If specified, ``suffix`` is added to each output file name, like so - ``--out dir/suffix``. This can be used to add a file extension to - the output e.g. ".xml". - -#]=======================================================================] - -#------------------------------------------------------------------------------ -function(catch_discover_tests TARGET) - cmake_parse_arguments( - "" - "" - "TEST_PREFIX;TEST_SUFFIX;WORKING_DIRECTORY;TEST_LIST;REPORTER;OUTPUT_DIR;OUTPUT_PREFIX;OUTPUT_SUFFIX" - "TEST_SPEC;EXTRA_ARGS;PROPERTIES" - ${ARGN} - ) - - if(NOT _WORKING_DIRECTORY) - set(_WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") - endif() - if(NOT _TEST_LIST) - set(_TEST_LIST ${TARGET}_TESTS) - endif() - - ## Generate a unique name based on the extra arguments - string(SHA1 args_hash "${_TEST_SPEC} ${_EXTRA_ARGS} ${_REPORTER} ${_OUTPUT_DIR} ${_OUTPUT_PREFIX} ${_OUTPUT_SUFFIX}") - string(SUBSTRING ${args_hash} 0 7 args_hash) - - # Define rule to generate test list for aforementioned test executable - set(ctest_include_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_include-${args_hash}.cmake") - set(ctest_tests_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}_tests-${args_hash}.cmake") - get_property(crosscompiling_emulator - TARGET ${TARGET} - PROPERTY CROSSCOMPILING_EMULATOR - ) - add_custom_command( - TARGET ${TARGET} POST_BUILD - BYPRODUCTS "${ctest_tests_file}" - COMMAND "${CMAKE_COMMAND}" - -D "TEST_TARGET=${TARGET}" - -D "TEST_EXECUTABLE=$" - -D "TEST_EXECUTOR=${crosscompiling_emulator}" - -D "TEST_WORKING_DIR=${_WORKING_DIRECTORY}" - -D "TEST_SPEC=${_TEST_SPEC}" - -D "TEST_EXTRA_ARGS=${_EXTRA_ARGS}" - -D "TEST_PROPERTIES=${_PROPERTIES}" - -D "TEST_PREFIX=${_TEST_PREFIX}" - -D "TEST_SUFFIX=${_TEST_SUFFIX}" - -D "TEST_LIST=${_TEST_LIST}" - -D "TEST_REPORTER=${_REPORTER}" - -D "TEST_OUTPUT_DIR=${_OUTPUT_DIR}" - -D "TEST_OUTPUT_PREFIX=${_OUTPUT_PREFIX}" - -D "TEST_OUTPUT_SUFFIX=${_OUTPUT_SUFFIX}" - -D "CTEST_FILE=${ctest_tests_file}" - -P "${_CATCH_DISCOVER_TESTS_SCRIPT}" - VERBATIM - ) - - file(WRITE "${ctest_include_file}" - "if(EXISTS \"${ctest_tests_file}\")\n" - " include(\"${ctest_tests_file}\")\n" - "else()\n" - " add_test(${TARGET}_NOT_BUILT-${args_hash} ${TARGET}_NOT_BUILT-${args_hash})\n" - "endif()\n" - ) - - if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0") - # Add discovered tests to directory TEST_INCLUDE_FILES - set_property(DIRECTORY - APPEND PROPERTY TEST_INCLUDE_FILES "${ctest_include_file}" - ) - else() - # Add discovered tests as directory TEST_INCLUDE_FILE if possible - get_property(test_include_file_set DIRECTORY PROPERTY TEST_INCLUDE_FILE SET) - if (NOT ${test_include_file_set}) - set_property(DIRECTORY - PROPERTY TEST_INCLUDE_FILE "${ctest_include_file}" - ) - else() - message(FATAL_ERROR - "Cannot set more than one TEST_INCLUDE_FILE" - ) - endif() - endif() - -endfunction() - -############################################################################### - -set(_CATCH_DISCOVER_TESTS_SCRIPT - ${CMAKE_CURRENT_LIST_DIR}/CatchAddTests.cmake -) diff --git a/subprojects/catch2/cmake/CatchAddTests.cmake b/subprojects/catch2/cmake/CatchAddTests.cmake deleted file mode 100644 index 18286b71c7..0000000000 --- a/subprojects/catch2/cmake/CatchAddTests.cmake +++ /dev/null @@ -1,132 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -set(prefix "${TEST_PREFIX}") -set(suffix "${TEST_SUFFIX}") -set(spec ${TEST_SPEC}) -set(extra_args ${TEST_EXTRA_ARGS}) -set(properties ${TEST_PROPERTIES}) -set(reporter ${TEST_REPORTER}) -set(output_dir ${TEST_OUTPUT_DIR}) -set(output_prefix ${TEST_OUTPUT_PREFIX}) -set(output_suffix ${TEST_OUTPUT_SUFFIX}) -set(script) -set(suite) -set(tests) - -function(add_command NAME) - set(_args "") - foreach(_arg ${ARGN}) - if(_arg MATCHES "[^-./:a-zA-Z0-9_]") - set(_args "${_args} [==[${_arg}]==]") # form a bracket_argument - else() - set(_args "${_args} ${_arg}") - endif() - endforeach() - set(script "${script}${NAME}(${_args})\n" PARENT_SCOPE) -endfunction() - -# Run test executable to get list of available tests -if(NOT EXISTS "${TEST_EXECUTABLE}") - message(FATAL_ERROR - "Specified test executable '${TEST_EXECUTABLE}' does not exist" - ) -endif() -execute_process( - COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-test-names-only - OUTPUT_VARIABLE output - RESULT_VARIABLE result - WORKING_DIRECTORY "${TEST_WORKING_DIR}" -) -# Catch --list-test-names-only reports the number of tests, so 0 is... surprising -if(${result} EQUAL 0) - message(WARNING - "Test executable '${TEST_EXECUTABLE}' contains no tests!\n" - ) -elseif(${result} LESS 0) - message(FATAL_ERROR - "Error running test executable '${TEST_EXECUTABLE}':\n" - " Result: ${result}\n" - " Output: ${output}\n" - ) -endif() - -string(REPLACE "\n" ";" output "${output}") - -# Run test executable to get list of available reporters -execute_process( - COMMAND ${TEST_EXECUTOR} "${TEST_EXECUTABLE}" ${spec} --list-reporters - OUTPUT_VARIABLE reporters_output - RESULT_VARIABLE reporters_result - WORKING_DIRECTORY "${TEST_WORKING_DIR}" -) -if(${reporters_result} EQUAL 0) - message(WARNING - "Test executable '${TEST_EXECUTABLE}' contains no reporters!\n" - ) -elseif(${reporters_result} LESS 0) - message(FATAL_ERROR - "Error running test executable '${TEST_EXECUTABLE}':\n" - " Result: ${reporters_result}\n" - " Output: ${reporters_output}\n" - ) -endif() -string(FIND "${reporters_output}" "${reporter}" reporter_is_valid) -if(reporter AND ${reporter_is_valid} EQUAL -1) - message(FATAL_ERROR - "\"${reporter}\" is not a valid reporter!\n" - ) -endif() - -# Prepare reporter -if(reporter) - set(reporter_arg "--reporter ${reporter}") -endif() - -# Prepare output dir -if(output_dir AND NOT IS_ABSOLUTE ${output_dir}) - set(output_dir "${TEST_WORKING_DIR}/${output_dir}") - if(NOT EXISTS ${output_dir}) - file(MAKE_DIRECTORY ${output_dir}) - endif() -endif() - -# Parse output -foreach(line ${output}) - set(test ${line}) - # Escape characters in test case names that would be parsed by Catch2 - set(test_name ${test}) - foreach(char , [ ]) - string(REPLACE ${char} "\\${char}" test_name ${test_name}) - endforeach(char) - # ...add output dir - if(output_dir) - string(REGEX REPLACE "[^A-Za-z0-9_]" "_" test_name_clean ${test_name}) - set(output_dir_arg "--out ${output_dir}/${output_prefix}${test_name_clean}${output_suffix}") - endif() - - # ...and add to script - add_command(add_test - "${prefix}${test}${suffix}" - ${TEST_EXECUTOR} - "${TEST_EXECUTABLE}" - "${test_name}" - ${extra_args} - "${reporter_arg}" - "${output_dir_arg}" - ) - add_command(set_tests_properties - "${prefix}${test}${suffix}" - PROPERTIES - WORKING_DIRECTORY "${TEST_WORKING_DIR}" - ${properties} - ) - list(APPEND tests "${prefix}${test}${suffix}") -endforeach() - -# Create a list of all discovered tests, which users may use to e.g. set -# properties on the tests -add_command(set ${TEST_LIST} ${tests}) - -# Write CTest script -file(WRITE "${CTEST_FILE}" "${script}") diff --git a/subprojects/catch2/cmake/ParseAndAddCatchTests.cmake b/subprojects/catch2/cmake/ParseAndAddCatchTests.cmake deleted file mode 100644 index 3f3da83198..0000000000 --- a/subprojects/catch2/cmake/ParseAndAddCatchTests.cmake +++ /dev/null @@ -1,251 +0,0 @@ -#==================================================================================================# -# supported macros # -# - TEST_CASE, # -# - TEMPLATE_TEST_CASE # -# - SCENARIO, # -# - TEST_CASE_METHOD, # -# - CATCH_TEST_CASE, # -# - CATCH_TEMPLATE_TEST_CASE # -# - CATCH_SCENARIO, # -# - CATCH_TEST_CASE_METHOD. # -# # -# Usage # -# 1. make sure this module is in the path or add this otherwise: # -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # -# 2. make sure that you've enabled testing option for the project by the call: # -# enable_testing() # -# 3. add the lines to the script for testing target (sample CMakeLists.txt): # -# project(testing_target) # -# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") # -# enable_testing() # -# # -# find_path(CATCH_INCLUDE_DIR "catch.hpp") # -# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) # -# # -# file(GLOB SOURCE_FILES "*.cpp") # -# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) # -# # -# include(ParseAndAddCatchTests) # -# ParseAndAddCatchTests(${PROJECT_NAME}) # -# # -# The following variables affect the behavior of the script: # -# # -# PARSE_CATCH_TESTS_VERBOSE (Default OFF) # -# -- enables debug messages # -# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) # -# -- excludes tests marked with [!hide], [.] or [.foo] tags # -# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) # -# -- adds fixture class name to the test name # -# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) # -# -- adds cmake target name to the test name # -# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) # -# -- causes CMake to rerun when file with tests changes so that new tests will be discovered # -# # -# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way # -# a test should be run. For instance to use test MPI, one can write # -# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) # -# just before calling this ParseAndAddCatchTests function # -# # -# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test # -# command. For example, to include successful tests in the output, one can write # -# set(AdditionalCatchParameters --success) # -# # -# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source # -# file in the target is set, and contains the list of the tests extracted from that target, or # -# from that file. This is useful, for example to add further labels or properties to the tests. # -# # -#==================================================================================================# - -if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8) - message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer") -endif() - -option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF) -option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF) -option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON) -option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON) -option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF) - -function(ParseAndAddCatchTests_PrintDebugMessage) - if(PARSE_CATCH_TESTS_VERBOSE) - message(STATUS "ParseAndAddCatchTests: ${ARGV}") - endif() -endfunction() - -# This removes the contents between -# - block comments (i.e. /* ... */) -# - full line comments (i.e. // ... ) -# contents have been read into '${CppCode}'. -# !keep partial line comments -function(ParseAndAddCatchTests_RemoveComments CppCode) - string(ASCII 2 CMakeBeginBlockComment) - string(ASCII 3 CMakeEndBlockComment) - string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}") - string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}") - - set(${CppCode} "${${CppCode}}" PARENT_SCOPE) -endfunction() - -# Worker function -function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget) - # If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file. - if(SourceFile MATCHES "\\\$") - ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.") - return() - endif() - # According to CMake docs EXISTS behavior is well-defined only for full paths. - get_filename_component(SourceFile ${SourceFile} ABSOLUTE) - if(NOT EXISTS ${SourceFile}) - message(WARNING "Cannot find source file: ${SourceFile}") - return() - endif() - ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}") - file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME) - - # Remove block and fullline comments - ParseAndAddCatchTests_RemoveComments(Contents) - - # Find definition of test names - # https://regex101.com/r/JygOND/1 - string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([ \t\n]*\"[^\"]*\"[ \t\n]*(,[ \t\n]*\"[^\"]*\")?(,[ \t\n]*[^\,\)]*)*\\)[ \t\n]*\{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}") - - if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests) - ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property") - set_property( - DIRECTORY - APPEND - PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile} - ) - endif() - - # check CMP0110 policy for new add_test() behavior - if(POLICY CMP0110) - cmake_policy(GET CMP0110 _cmp0110_value) # new add_test() behavior - else() - # just to be thorough explicitly set the variable - set(_cmp0110_value) - endif() - - foreach(TestName ${Tests}) - # Strip newlines - string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}") - - # Get test type and fixture if applicable - string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}") - string(REGEX MATCH "(CATCH_)?(TEMPLATE_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}") - string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}") - - # Get string parts of test definition - string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}") - - # Strip wrapping quotation marks - string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}") - string(REPLACE "\";\"" ";" TestStrings "${TestStrings}") - - # Validate that a test name and tags have been provided - list(LENGTH TestStrings TestStringsLength) - if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1) - message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}") - endif() - - # Assign name and tags - list(GET TestStrings 0 Name) - if("${TestType}" STREQUAL "SCENARIO") - set(Name "Scenario: ${Name}") - endif() - if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND "${TestType}" MATCHES "(CATCH_)?TEST_CASE_METHOD" AND TestFixture ) - set(CTestName "${TestFixture}:${Name}") - else() - set(CTestName "${Name}") - endif() - if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME) - set(CTestName "${TestTarget}:${CTestName}") - endif() - # add target to labels to enable running all tests added from this target - set(Labels ${TestTarget}) - if(TestStringsLength EQUAL 2) - list(GET TestStrings 1 Tags) - string(TOLOWER "${Tags}" Tags) - # remove target from labels if the test is hidden - if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*") - list(REMOVE_ITEM Labels ${TestTarget}) - endif() - string(REPLACE "]" ";" Tags "${Tags}") - string(REPLACE "[" "" Tags "${Tags}") - else() - # unset tags variable from previous loop - unset(Tags) - endif() - - list(APPEND Labels ${Tags}) - - set(HiddenTagFound OFF) - foreach(label ${Labels}) - string(REGEX MATCH "^!hide|^\\." result ${label}) - if(result) - set(HiddenTagFound ON) - break() - endif(result) - endforeach(label) - if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9") - ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label") - else() - ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"") - if(Labels) - ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}") - endif() - - # Escape commas in the test spec - string(REPLACE "," "\\," Name ${Name}) - - # Work around CMake 3.18.0 change in `add_test()`, before the escaped quotes were neccessary, - # only with CMake 3.18.0 the escaped double quotes confuse the call. This change is reverted in 3.18.1 - # And properly introduced in 3.19 with the CMP0110 policy - if(_cmp0110_value STREQUAL "NEW" OR ${CMAKE_VERSION} VERSION_EQUAL "3.18") - ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to NEW, no need for add_test(\"\") workaround") - else() - ParseAndAddCatchTests_PrintDebugMessage("CMP0110 set to OLD adding \"\" for add_test() workaround") - set(CTestName "\"${CTestName}\"") - endif() - - # Handle template test cases - if("${TestTypeAndFixture}" MATCHES ".*TEMPLATE_.*") - set(Name "${Name} - *") - endif() - - # Add the test and set its properties - add_test(NAME "${CTestName}" COMMAND ${OptionalCatchTestLauncher} $ ${Name} ${AdditionalCatchParameters}) - # Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead - if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8") - ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property") - set_tests_properties("${CTestName}" PROPERTIES DISABLED ON) - else() - set_tests_properties("${CTestName}" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran" - LABELS "${Labels}") - endif() - set_property( - TARGET ${TestTarget} - APPEND - PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") - set_property( - SOURCE ${SourceFile} - APPEND - PROPERTY ParseAndAddCatchTests_TESTS "${CTestName}") - endif() - - - endforeach() -endfunction() - -# entry point -function(ParseAndAddCatchTests TestTarget) - ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}") - get_target_property(SourceFiles ${TestTarget} SOURCES) - ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}") - foreach(SourceFile ${SourceFiles}) - ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget}) - endforeach() - ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}") -endfunction() diff --git a/subprojects/catch2/include/catch2/catch.hpp b/subprojects/catch2/include/catch2/catch.hpp deleted file mode 100644 index cf1fae15aa..0000000000 --- a/subprojects/catch2/include/catch2/catch.hpp +++ /dev/null @@ -1,17799 +0,0 @@ -/* - * Catch v2.13.0 - * Generated: 2020-07-12 20:07:49.015950 - * ---------------------------------------------------------- - * This file has been merged from multiple headers. Please don't edit it directly - * Copyright (c) 2020 Two Blue Cubes Ltd. All rights reserved. - * - * 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) - */ -#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED -// start catch.hpp - - -#define CATCH_VERSION_MAJOR 2 -#define CATCH_VERSION_MINOR 13 -#define CATCH_VERSION_PATCH 0 - -#ifdef __clang__ -# pragma clang system_header -#elif defined __GNUC__ -# pragma GCC system_header -#endif - -// start catch_suppress_warnings.h - -#ifdef __clang__ -# ifdef __ICC // icpc defines the __clang__ macro -# pragma warning(push) -# pragma warning(disable: 161 1682) -# else // __ICC -# pragma clang diagnostic push -# pragma clang diagnostic ignored "-Wpadded" -# pragma clang diagnostic ignored "-Wswitch-enum" -# pragma clang diagnostic ignored "-Wcovered-switch-default" -# endif -#elif defined __GNUC__ - // Because REQUIREs trigger GCC's -Wparentheses, and because still - // supported version of g++ have only buggy support for _Pragmas, - // Wparentheses have to be suppressed globally. -# pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details - -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -# pragma GCC diagnostic ignored "-Wpadded" -#endif -// end catch_suppress_warnings.h -#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) -# define CATCH_IMPL -# define CATCH_CONFIG_ALL_PARTS -#endif - -// In the impl file, we want to have access to all parts of the headers -// Can also be used to sanely support PCHs -#if defined(CATCH_CONFIG_ALL_PARTS) -# define CATCH_CONFIG_EXTERNAL_INTERFACES -# if defined(CATCH_CONFIG_DISABLE_MATCHERS) -# undef CATCH_CONFIG_DISABLE_MATCHERS -# endif -# if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER) -# define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER -# endif -#endif - -#if !defined(CATCH_CONFIG_IMPL_ONLY) -// start catch_platform.h - -#ifdef __APPLE__ -# include -# if TARGET_OS_OSX == 1 -# define CATCH_PLATFORM_MAC -# elif TARGET_OS_IPHONE == 1 -# define CATCH_PLATFORM_IPHONE -# endif - -#elif defined(linux) || defined(__linux) || defined(__linux__) -# define CATCH_PLATFORM_LINUX - -#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__) -# define CATCH_PLATFORM_WINDOWS -#endif - -// end catch_platform.h - -#ifdef CATCH_IMPL -# ifndef CLARA_CONFIG_MAIN -# define CLARA_CONFIG_MAIN_NOT_DEFINED -# define CLARA_CONFIG_MAIN -# endif -#endif - -// start catch_user_interfaces.h - -namespace Catch { - unsigned int rngSeed(); -} - -// end catch_user_interfaces.h -// start catch_tag_alias_autoregistrar.h - -// start catch_common.h - -// start catch_compiler_capabilities.h - -// Detect a number of compiler features - by compiler -// The following features are defined: -// -// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? -// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? -// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? -// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled? -// **************** -// Note to maintainers: if new toggles are added please document them -// in configuration.md, too -// **************** - -// In general each macro has a _NO_ form -// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature. -// Many features, at point of detection, define an _INTERNAL_ macro, so they -// can be combined, en-mass, with the _NO_ forms later. - -#ifdef __cplusplus - -# if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) -# define CATCH_CPP14_OR_GREATER -# endif - -# if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) -# define CATCH_CPP17_OR_GREATER -# endif - -#endif - -#if defined(__cpp_lib_uncaught_exceptions) -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -// We have to avoid both ICC and Clang, because they try to mask themselves -// as gcc, and we want only GCC in this block -#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic pop" ) - -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) - -#endif - -#if defined(__clang__) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic pop" ) - -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -# if !defined(__ibmxl__) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */ -# endif - -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \ - _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"") - -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" ) - -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" ) - -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \ - _Pragma( "clang diagnostic ignored \"-Wunused-template\"" ) - -#endif // __clang__ - -//////////////////////////////////////////////////////////////////////////////// -// Assume that non-Windows platforms support posix signals by default -#if !defined(CATCH_PLATFORM_WINDOWS) - #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS -#endif - -//////////////////////////////////////////////////////////////////////////////// -// We know some environments not to support full POSIX signals -#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__) - #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -#endif - -#ifdef __OS400__ -# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS -# define CATCH_CONFIG_COLOUR_NONE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Android somehow still does not support std::to_string -#if defined(__ANDROID__) -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING -# define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Not all Windows environments support SEH properly -#if defined(__MINGW32__) -# define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH -#endif - -//////////////////////////////////////////////////////////////////////////////// -// PS4 -#if defined(__ORBIS__) -# define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE -#endif - -//////////////////////////////////////////////////////////////////////////////// -// Cygwin -#ifdef __CYGWIN__ - -// Required for some versions of Cygwin to declare gettimeofday -// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin -# define _BSD_SOURCE -// some versions of cygwin (most) do not support std::to_string. Use the libstd check. -// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813 -# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \ - && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF)) - -# define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING - -# endif -#endif // __CYGWIN__ - -//////////////////////////////////////////////////////////////////////////////// -// Visual C++ -#if defined(_MSC_VER) - -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) ) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION __pragma( warning(pop) ) - -# if _MSC_VER >= 1900 // Visual Studio 2015 or newer -# define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -# endif - -// Universal Windows platform does not support SEH -// Or console colours (or console at all...) -# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP) -# define CATCH_CONFIG_COLOUR_NONE -# else -# define CATCH_INTERNAL_CONFIG_WINDOWS_SEH -# endif - -// MSVC traditional preprocessor needs some workaround for __VA_ARGS__ -// _MSVC_TRADITIONAL == 0 means new conformant preprocessor -// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor -# if !defined(__clang__) // Handle Clang masquerading for msvc -# if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL) -# define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -# endif // MSVC_TRADITIONAL -# endif // __clang__ - -#endif // _MSC_VER - -#if defined(_REENTRANT) || defined(_MSC_VER) -// Enable async processing, as -pthread is specified or no additional linking is required -# define CATCH_INTERNAL_CONFIG_USE_ASYNC -#endif // _MSC_VER - -//////////////////////////////////////////////////////////////////////////////// -// Check if we are compiled with -fno-exceptions or equivalent -#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND) -# define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED -#endif - -//////////////////////////////////////////////////////////////////////////////// -// DJGPP -#ifdef __DJGPP__ -# define CATCH_INTERNAL_CONFIG_NO_WCHAR -#endif // __DJGPP__ - -//////////////////////////////////////////////////////////////////////////////// -// Embarcadero C++Build -#if defined(__BORLANDC__) - #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// Use of __COUNTER__ is suppressed during code analysis in -// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly -// handled by it. -// Otherwise all supported compilers support COUNTER macro, -// but user still might want to turn it off -#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L ) - #define CATCH_INTERNAL_CONFIG_COUNTER -#endif - -//////////////////////////////////////////////////////////////////////////////// - -// RTX is a special version of Windows that is real time. -// This means that it is detected as Windows, but does not provide -// the same set of capabilities as real Windows does. -#if defined(UNDER_RTSS) || defined(RTX64_BUILD) - #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH - #define CATCH_INTERNAL_CONFIG_NO_ASYNC - #define CATCH_CONFIG_COLOUR_NONE -#endif - -#if !defined(_GLIBCXX_USE_C99_MATH_TR1) -#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Various stdlib support checks that require __has_include -#if defined(__has_include) - // Check if string_view is available and usable - #if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW - #endif - - // Check if optional is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if byte is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # define CATCH_INTERNAL_CONFIG_CPP17_BYTE - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) - - // Check if variant is available and usable - # if __has_include() && defined(CATCH_CPP17_OR_GREATER) - # if defined(__clang__) && (__clang_major__ < 8) - // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852 - // fix should be in clang 8, workaround in libstdc++ 8.2 - # include - # if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # define CATCH_CONFIG_NO_CPP17_VARIANT - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9) - # else - # define CATCH_INTERNAL_CONFIG_CPP17_VARIANT - # endif // defined(__clang__) && (__clang_major__ < 8) - # endif // __has_include() && defined(CATCH_CPP17_OR_GREATER) -#endif // defined(__has_include) - -#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) -# define CATCH_CONFIG_COUNTER -#endif -#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH) -# define CATCH_CONFIG_WINDOWS_SEH -#endif -// This is set by default, because we assume that unix compilers are posix-signal-compatible by default. -#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) -# define CATCH_CONFIG_POSIX_SIGNALS -#endif -// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions. -#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR) -# define CATCH_CONFIG_WCHAR -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING) -# define CATCH_CONFIG_CPP11_TO_STRING -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL) -# define CATCH_CONFIG_CPP17_OPTIONAL -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) -# define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW) -# define CATCH_CONFIG_CPP17_STRING_VIEW -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT) -# define CATCH_CONFIG_CPP17_VARIANT -#endif - -#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE) -# define CATCH_CONFIG_CPP17_BYTE -#endif - -#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT) -# define CATCH_INTERNAL_CONFIG_NEW_CAPTURE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE) -# define CATCH_CONFIG_NEW_CAPTURE -#endif - -#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -# define CATCH_CONFIG_DISABLE_EXCEPTIONS -#endif - -#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN) -# define CATCH_CONFIG_POLYFILL_ISNAN -#endif - -#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC) && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC) -# define CATCH_CONFIG_USE_ASYNC -#endif - -#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE) -# define CATCH_CONFIG_ANDROID_LOGWRITE -#endif - -#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER) -# define CATCH_CONFIG_GLOBAL_NEXTAFTER -#endif - -// Even if we do not think the compiler has that warning, we still have -// to provide a macro that can be used by the code. -#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION) -# define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS -#endif -#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS -#endif - -// The goal of this macro is to avoid evaluation of the arguments, but -// still have the compiler warn on problems inside... -#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN) -# define CATCH_INTERNAL_IGNORE_BUT_WARN(...) -#endif - -#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#elif defined(__clang__) && (__clang_major__ < 5) -# undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS) -# define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS -#endif - -#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) -#define CATCH_TRY if ((true)) -#define CATCH_CATCH_ALL if ((false)) -#define CATCH_CATCH_ANON(type) if ((false)) -#else -#define CATCH_TRY try -#define CATCH_CATCH_ALL catch (...) -#define CATCH_CATCH_ANON(type) catch (type) -#endif - -#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) -#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#endif - -// end catch_compiler_capabilities.h -#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line -#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) -#ifdef CATCH_CONFIG_COUNTER -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) -#else -# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) -#endif - -#include -#include -#include - -// We need a dummy global operator<< so we can bring it into Catch namespace later -struct Catch_global_namespace_dummy {}; -std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy); - -namespace Catch { - - struct CaseSensitive { enum Choice { - Yes, - No - }; }; - - class NonCopyable { - NonCopyable( NonCopyable const& ) = delete; - NonCopyable( NonCopyable && ) = delete; - NonCopyable& operator = ( NonCopyable const& ) = delete; - NonCopyable& operator = ( NonCopyable && ) = delete; - - protected: - NonCopyable(); - virtual ~NonCopyable(); - }; - - struct SourceLineInfo { - - SourceLineInfo() = delete; - SourceLineInfo( char const* _file, std::size_t _line ) noexcept - : file( _file ), - line( _line ) - {} - - SourceLineInfo( SourceLineInfo const& other ) = default; - SourceLineInfo& operator = ( SourceLineInfo const& ) = default; - SourceLineInfo( SourceLineInfo&& ) noexcept = default; - SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default; - - bool empty() const noexcept { return file[0] == '\0'; } - bool operator == ( SourceLineInfo const& other ) const noexcept; - bool operator < ( SourceLineInfo const& other ) const noexcept; - - char const* file; - std::size_t line; - }; - - std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); - - // Bring in operator<< from global namespace into Catch namespace - // This is necessary because the overload of operator<< above makes - // lookup stop at namespace Catch - using ::operator<<; - - // Use this in variadic streaming macros to allow - // >> +StreamEndStop - // as well as - // >> stuff +StreamEndStop - struct StreamEndStop { - std::string operator+() const; - }; - template - T const& operator + ( T const& value, StreamEndStop ) { - return value; - } -} - -#define CATCH_INTERNAL_LINEINFO \ - ::Catch::SourceLineInfo( __FILE__, static_cast( __LINE__ ) ) - -// end catch_common.h -namespace Catch { - - struct RegistrarForTagAliases { - RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); - }; - -} // end namespace Catch - -#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \ - CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ - CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \ - namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \ - CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION - -// end catch_tag_alias_autoregistrar.h -// start catch_test_registry.h - -// start catch_interfaces_testcase.h - -#include - -namespace Catch { - - class TestSpec; - - struct ITestInvoker { - virtual void invoke () const = 0; - virtual ~ITestInvoker(); - }; - - class TestCase; - struct IConfig; - - struct ITestCaseRegistry { - virtual ~ITestCaseRegistry(); - virtual std::vector const& getAllTests() const = 0; - virtual std::vector const& getAllTestsSorted( IConfig const& config ) const = 0; - }; - - bool isThrowSafe( TestCase const& testCase, IConfig const& config ); - bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); - std::vector filterTests( std::vector const& testCases, TestSpec const& testSpec, IConfig const& config ); - std::vector const& getAllTestCasesSorted( IConfig const& config ); - -} - -// end catch_interfaces_testcase.h -// start catch_stringref.h - -#include -#include -#include -#include - -namespace Catch { - - /// A non-owning string class (similar to the forthcoming std::string_view) - /// Note that, because a StringRef may be a substring of another string, - /// it may not be null terminated. - class StringRef { - public: - using size_type = std::size_t; - using const_iterator = const char*; - - private: - static constexpr char const* const s_empty = ""; - - char const* m_start = s_empty; - size_type m_size = 0; - - public: // construction - constexpr StringRef() noexcept = default; - - StringRef( char const* rawChars ) noexcept; - - constexpr StringRef( char const* rawChars, size_type size ) noexcept - : m_start( rawChars ), - m_size( size ) - {} - - StringRef( std::string const& stdString ) noexcept - : m_start( stdString.c_str() ), - m_size( stdString.size() ) - {} - - explicit operator std::string() const { - return std::string(m_start, m_size); - } - - public: // operators - auto operator == ( StringRef const& other ) const noexcept -> bool; - auto operator != (StringRef const& other) const noexcept -> bool { - return !(*this == other); - } - - auto operator[] ( size_type index ) const noexcept -> char { - assert(index < m_size); - return m_start[index]; - } - - public: // named queries - constexpr auto empty() const noexcept -> bool { - return m_size == 0; - } - constexpr auto size() const noexcept -> size_type { - return m_size; - } - - // Returns the current start pointer. If the StringRef is not - // null-terminated, throws std::domain_exception - auto c_str() const -> char const*; - - public: // substrings and searches - // Returns a substring of [start, start + length). - // If start + length > size(), then the substring is [start, size()). - // If start > size(), then the substring is empty. - auto substr( size_type start, size_type length ) const noexcept -> StringRef; - - // Returns the current start pointer. May not be null-terminated. - auto data() const noexcept -> char const*; - - constexpr auto isNullTerminated() const noexcept -> bool { - return m_start[m_size] == '\0'; - } - - public: // iterators - constexpr const_iterator begin() const { return m_start; } - constexpr const_iterator end() const { return m_start + m_size; } - }; - - auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&; - auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&; - - constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef { - return StringRef( rawChars, size ); - } -} // namespace Catch - -constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef { - return Catch::StringRef( rawChars, size ); -} - -// end catch_stringref.h -// start catch_preprocessor.hpp - - -#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__ -#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__))) -#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__))) - -#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__ -// MSVC needs more evaluations -#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__))) -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__)) -#else -#define CATCH_RECURSE(...) CATCH_RECURSION_LEVEL5(__VA_ARGS__) -#endif - -#define CATCH_REC_END(...) -#define CATCH_REC_OUT - -#define CATCH_EMPTY() -#define CATCH_DEFER(id) id CATCH_EMPTY() - -#define CATCH_REC_GET_END2() 0, CATCH_REC_END -#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2 -#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1 -#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT -#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0) -#define CATCH_REC_NEXT(test, next) CATCH_REC_NEXT1(CATCH_REC_GET_END test, next) - -#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2(f, x, peek, ...) f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ ) - -#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ ) -#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...) f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ ) - -// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results, -// and passes userdata as the first parameter to each invocation, -// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c) -#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0)) - -#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param) -#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__ -#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__ -#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__) -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) -#else -// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF -#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__) -#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__ -#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1) -#endif - -#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__ -#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name) - -#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__) - -#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper()) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)) -#else -#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper())) -#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))) -#endif - -#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\ - CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__) - -#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0) -#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1) -#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2) -#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3) -#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4) -#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5) -#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6) -#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7) -#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8) -#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9) -#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) - -#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N - -#define INTERNAL_CATCH_TYPE_GEN\ - template struct TypeList {};\ - template\ - constexpr auto get_wrapper() noexcept -> TypeList { return {}; }\ - template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper() noexcept -> TemplateTypeList { return {}; }\ - template\ - struct append;\ - template\ - struct rewrap;\ - template class, typename...>\ - struct create;\ - template class, typename>\ - struct convert;\ - \ - template \ - struct append { using type = T; };\ - template< template class L1, typename...E1, template class L2, typename...E2, typename...Rest>\ - struct append, L2, Rest...> { using type = typename append, Rest...>::type; };\ - template< template class L1, typename...E1, typename...Rest>\ - struct append, TypeList, Rest...> { using type = L1; };\ - \ - template< template class Container, template class List, typename...elems>\ - struct rewrap, List> { using type = TypeList>; };\ - template< template class Container, template class List, class...Elems, typename...Elements>\ - struct rewrap, List, Elements...> { using type = typename append>, typename rewrap, Elements...>::type>::type; };\ - \ - template