cmake_minimum_required(VERSION 3.15)

# CMP0091 makes the MSVC runtime a target property.  This is required when a
# single build contains both a static and a shared CoolProp library, because
# the two variants historically use different runtimes.
cmake_policy(SET CMP0091 NEW)

set(project_name "CoolProp")
set(app_name ${project_name})

# REVISION is concatenated onto the patch and PEP 440-normalized by the version
# tooling (dev/extract_version.py, dev/coolprop_version_provider.py): "b1" ->
# 8.0.0b1 (a beta pre-release), "dev" -> 8.0.0.dev0, "" -> 8.0.0 (final).
# Keep a numeric version for CMake's project/package version machinery.
set(COOLPROP_VERSION_MAJOR 8)
set(COOLPROP_VERSION_MINOR 0)
set(COOLPROP_VERSION_PATCH 1)
set(COOLPROP_VERSION_REVISION dev)
set(COOLPROP_VERSION_NUMERIC
    "${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}"
)
set(COOLPROP_VERSION "${COOLPROP_VERSION_NUMERIC}${COOLPROP_VERSION_REVISION}")

# CMAKE_OSX_DEPLOYMENT_TARGET and Xcode toolchain attributes must be selected
# before the first project()/enable_language() call. A parent may provide this
# legacy CoolProp option from its cache when using add_subdirectory().
if(DEFINED DARWIN_USE_LIBCPP)
  if(DARWIN_USE_LIBCPP)
    set(CMAKE_OSX_DEPLOYMENT_TARGET
        "10.9"
        CACHE STRING "Minimum OS X deployment version")
    set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
  else()
    set(CMAKE_OSX_DEPLOYMENT_TARGET
        "10.5"
        CACHE STRING "Minimum OS X deployment version")
    set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++")
  endif()
endif()

# If an older parent already enabled MSVC languages while CMP0091 used OLD
# behavior, a nested project() can make the directory-local policy state look
# modern even though the compiler flags were initialized in legacy mode.
# Snapshot that condition before CoolProp's project() call.
set(_coolprop_needs_msvc_runtime_fallback OFF)
if(NOT CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR
   AND MSVC
   AND NOT CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
  set(_coolprop_needs_msvc_runtime_fallback ON)
endif()

project(${project_name} VERSION ${COOLPROP_VERSION_NUMERIC} LANGUAGES C CXX)

# Always export compile_commands.json for clang-tidy, IWYU, and editor LSPs
# (CoolProp-2uw.7). Honored by Makefile and Ninja generators; harmless on others.
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

include(CheckIncludeFileCXX)

#######################################
#          COMPILER CACHE             #
#-------------------------------------#

# Route compiles through ccache when it is available.  A fresh git worktree
# otherwise recompiles the entire library from scratch -- measured at 3m47s for
# the Catch runner tree plus 4m02s for the shared-library tree, on sources
# byte-identical to the ones the main checkout already built (bd CoolProp-tl0w).
#
# This MUST sit above the dependencies.cmake include below.  CMAKE_<LANG>_-
# COMPILER_LAUNCHER is consumed when a target is created, and that include adds
# every CPM package -- Catch2 alone is 106 of the Catch runner tree's 205
# objects.  Setting the launcher after that include left those 106 compiling
# uncached, which measured as 99/205 objects covered.
#
# CCACHE_BASEDIR is load-bearing, not a tuning knob.  CoolProp's compile lines
# bake in absolute paths: every -I into the source tree, the CPM _deps includes
# under the build dir, and the input file itself.  Those strings differ per
# worktree, so without base_dir every object in a new worktree misses and ccache
# buys nothing.  Pointing base_dir at the source root makes ccache rewrite
# absolute paths beneath it to CWD-relative form before hashing; since a
# worktree's build dir sits inside the worktree exactly as the main checkout's
# does, the rewritten command lines coincide and the cache is shared.
#
# What base_dir does NOT do is reach inside a -D macro value, and CatchTestRunner
# carries -DCOOLPROP_ALL_FLUIDS_JSON_PATH="<source dir>/dev/all_fluids.json" on
# all 99 of its objects (CMakeLists.txt, target_compile_definitions below).  That
# costs far less than it looks like it should, because ccache's preprocessor mode
# excludes -D from the command-line hash -- a define's effect is already present
# in the preprocessed text -- so only a TU that actually expands the macro fails
# to share.  Measured on a fresh cache populated from an unrelated path:
#
#   cacheable calls  205 / 205      direct hits         106  (Catch2; no -D)
#   hits             204 / 205      preprocessed hits    98  (-D present, unused)
#   misses             1 / 205      the one TU that expands the macro
#
# The other limit is ccache's hash_dir, which defaults true and folds the working
# directory into the hash whenever -g is present.  Debug / RelWithDebInfo /
# sanitizer trees therefore do NOT share across worktrees; the numbers above are
# Release, and only -g-free builds get them.
#
# `cmake -E env` rather than a bare `env` so the launcher stays portable.
#
# Only the Makefile and Ninja generators honour <LANG>_COMPILER_LAUNCHER, so
# Visual Studio and Xcode are excluded -- wiring it there is a silent no-op that
# reads as support.  (CoolProp documents `cmake -G Xcode` for the iOS wrapper,
# and already special-cases Xcode further down, so this is a live path.)
# MSVC itself is NOT excluded.  ccache has supported cl.exe
# since 4.6 under Ninja and Makefiles, though MSVC's default /Zi debug format is
# uncacheable (/Z7 is required); opt out with -DCOOLPROP_USE_CCACHE=OFF.
#
# A launcher the caller already supplied (distcc, sccache, a CI wrapper) is
# honoured rather than overwritten.  Both the -D form and the environment-
# variable form are checked, so a launcher set either way -- including an
# environment variable that is defined but empty, meaning "no launcher" -- is
# honoured.  (project(), just above, also copies an environment launcher into
# the cache variable on CMake 3.17+.)
# Either language being pre-set defers the whole block, so a caller who sets
# only CXX does not end up with a mismatched C launcher.
option(COOLPROP_USE_CCACHE "Route compiles through ccache when available" ON)

if(COOLPROP_USE_CCACHE
   AND NOT CMAKE_GENERATOR MATCHES "Visual Studio|Xcode"
   AND NOT CMAKE_C_COMPILER_LAUNCHER
   AND NOT CMAKE_CXX_COMPILER_LAUNCHER
   AND NOT DEFINED ENV{CMAKE_C_COMPILER_LAUNCHER}
   AND NOT DEFINED ENV{CMAKE_CXX_COMPILER_LAUNCHER})
  find_program(COOLPROP_CCACHE_PROGRAM ccache)
  if(COOLPROP_CCACHE_PROGRAM)
    set(_coolprop_ccache_launcher
        "${CMAKE_COMMAND}" -E env "CCACHE_BASEDIR=${CMAKE_CURRENT_SOURCE_DIR}"
        "${COOLPROP_CCACHE_PROGRAM}")
    set(CMAKE_C_COMPILER_LAUNCHER ${_coolprop_ccache_launcher})
    set(CMAKE_CXX_COMPILER_LAUNCHER ${_coolprop_ccache_launcher})
    message(STATUS "ccache enabled: ${COOLPROP_CCACHE_PROGRAM} (CCACHE_BASEDIR=${CMAKE_CURRENT_SOURCE_DIR})")
  else()
    message(STATUS "ccache not found; compiling without a compiler cache")
  endif()
endif()

if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
  # Preserve the historical in-tree release layout for top-level builds.
  # Apply this default BEFORE validating COOLPROP_INSTALL_PREFIX: a configure
  # that stops on the guard below still writes the cache, and if the platform
  # default were cached at that point (INITIALIZED_TO_DEFAULT is only set on the
  # first run), the recovery the message suggests would silently install to
  # /usr/local instead of install_root.
  if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
    set(CMAKE_INSTALL_PREFIX
        "${CMAKE_CURRENT_SOURCE_DIR}/install_root"
        CACHE PATH "CoolProp install path" FORCE)
  endif()
  if(DEFINED COOLPROP_INSTALL_PREFIX)
    if(COOLPROP_INSTALL_PREFIX STREQUAL "")
      message(FATAL_ERROR
              "COOLPROP_INSTALL_PREFIX must not be empty; omit it to use the default install prefix (after a failed configure, also clear the cached value with cmake -U COOLPROP_INSTALL_PREFIX).")
    endif()
    message(STATUS "COOLPROP_INSTALL_PREFIX=${COOLPROP_INSTALL_PREFIX}")
    set(CMAKE_INSTALL_PREFIX
        "${COOLPROP_INSTALL_PREFIX}"
        CACHE PATH "CoolProp install path" FORCE)
  endif()
  # Install destinations are relative, so an empty prefix installs into the
  # filesystem root.  Master always forced install_root; now that an explicit
  # CMAKE_INSTALL_PREFIX is honoured, refuse an empty one too (for example
  # -DCMAKE_INSTALL_PREFIX="$PREFIX" with PREFIX unset).
  if(CMAKE_INSTALL_PREFIX STREQUAL "")
    message(FATAL_ERROR
            "CMAKE_INSTALL_PREFIX must not be empty; omit it to use the default install prefix (after a failed configure, also clear the cached value with cmake -U CMAKE_INSTALL_PREFIX).")
  endif()
elseif(DEFINED COOLPROP_INSTALL_PREFIX)
  message(
    WARNING
      "Ignoring COOLPROP_INSTALL_PREFIX='${COOLPROP_INSTALL_PREFIX}' in a nested CoolProp build; set CMAKE_INSTALL_PREFIX in the parent project instead."
  )
endif()

# Dependency management via CPM.cmake (replaces git submodules).
# Set CPM_SOURCE_CACHE (e.g. ~/.cache/CPM) to share downloads across worktrees.
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/dependencies.cmake")

#######################################
#           BUILD OPTIONS             #
#-------------------------------------#
# These options are available to be   #
# modified in the build process.      #
# packages may want to modify these   #
# to suit, or just leave as defaults. #
#######################################

option(COOLPROP_STATIC_LIBRARY "Build CoolProp as a static library (.lib, .a)"
       OFF)

option(COOLPROP_SHARED_LIBRARY "Build CoolProp as a shared library (.dll, .so)"
       OFF)

option(COOLPROP_OBJECT_LIBRARY
       "Build CoolProp objects, but do not link them (.obj, .o)" OFF)

option(COOLPROP_FPIC
       "Build CoolProp libraries with position-independent code" OFF)

option(COOLPROP_EES_MODULE "Build the EES module" OFF)

option(COOLPROP_WINDOWS_PACKAGE "Build the Windows installer" OFF)

option(BUILD_TESTING "Enable testing for this given builder" OFF)

option(FORCE_BITNESS_32 "Force a 32bit build regardless of the host" OFF)

option(FORCE_BITNESS_64 "Force a 64bit build regardless of the host" OFF)

option(FORCE_BITNESS_NATIVE
       "Force a native bitness build regardless of the host" OFF)

option(COOLPROP_RELEASE "Optimize the builds with the release specs" OFF)

option(COOLPROP_DEBUG "Make a debug build" OFF)

option(COOLPROP_SMATH_WORK_INPLACE "Build SMath wrapper in source directory"
       OFF)

option(
  COOLPROP_MSVC_STATIC
  "Statically link Microsoft Standard library removes dependency on MSVCRXXX.dll."
  OFF)

option(
  COOLPROP_MSVC_DYNAMIC
  "Dynamically link Microsoft Standard library to integrate with other builds."
  OFF)

option(
  COOLPROP_MSVC_DEBUG
  "Deprecated compatibility option; Debug builds always use the debug MSVC runtime."
  ON)

option(COOLPROP_NO_EXAMPLES
       "Do not generate example code, does only apply to some wrappers." OFF)

option(COOLPROP_SVD_E2E
       "Build the SVD-SBTL end-to-end validation tool at dev/svd_sbtl_e2e.cpp"
       OFF)

option(COOLPROP_BUILD_SVD_TABLES
       "Build the SVDSBTL bulk-table builder at dev/build_svd_tables.cpp"
       OFF)

option(COOLPROP_BUILD_SVDSBTL_BENCH
       "Build the SVDSBTL state-point benchmark at dev/bench_svdsbtl_ph.cpp"
       OFF)

option(COOLPROP_BUILD_SVDSBTL_PROFILE
       "Build the SVDSBTL per-stage profiler at dev/profile_svdsbtl.cpp"
       OFF)

#option (DARWIN_USE_LIBCPP
#        "On Darwin systems, compile and link with -std=libc++ instead of the default -std=libstdc++"
#        ON)

# Force C++11 since lambdas are used in CPStrings.h
# In the future, we may want to force C++14 since std::make_unique is used in DataStructures.cpp
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# CoolProp uses <filesystem> in src/CPfilepaths.cpp, include/CoolProp/detail/
# atomic_write.h and the SBTL sources, and links no separate filesystem library.
# GCC only ships <filesystem> from 8, and only stops needing -lstdc++fs for it
# at 9, so 9 is the real floor.
#
# Say so here rather than letting it surface later.  GCC 7.5, which openSUSE
# Leap 15.x still installs as its default compiler, announces partial C++17
# support and then fails well into the build with
#
#     src/CPfilepaths.cpp:11:10: fatal error: filesystem: No such file or
#     directory
#
# followed by an unrelated-looking overload resolution error in
# SVDEvaluator.h.  Neither names the actual problem.  That was a real OBS
# build failure.
#
# Only GNU is checked.  The floors for MSVC, Clang and AppleClang are easy to
# state wrongly and none of the toolchains CoolProp is built with come close
# to them, so an unverified check there would risk breaking builds that work
# rather than explaining one that does not.
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION
                                            VERSION_LESS 9)
  message(
    FATAL_ERROR
      "CoolProp needs GCC 9 or newer for std::filesystem, and this is GCC "
      "${CMAKE_CXX_COMPILER_VERSION}. On openSUSE Leap 15.x install gcc13-c++ "
      "and configure with -DCMAKE_C_COMPILER=gcc-13 -DCMAKE_CXX_COMPILER=g++-13.")
endif()


# Define -DCOOLPROP_ASAN=ON to enable the option of using address sanitizer of clang
if (COOLPROP_ASAN)

  # https://stackoverflow.com/a/64294837 (CC BY-SA 4.0)
  if(isMultiConfig)
      if(NOT "Asan" IN_LIST CMAKE_CONFIGURATION_TYPES)
          list(APPEND CMAKE_CONFIGURATION_TYPES Asan)
      endif()
  else()
      set(allowedBuildTypes Asan Debug Release RelWithDebInfo MinSizeRel)
      set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowedBuildTypes}")

      if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE IN_LIST allowedBuildTypes)
          message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
      endif()
  endif()

  # Optimize the Asan build: -O2 -g -DNDEBUG (the RelWithDebInfo level, plus
  # ASan).  ASan instrumentation is unaffected by optimization level, so this
  # is the standard way to run ASan; -O is set explicitly rather than inherited
  # from ${CMAKE_*_FLAGS_RELWITHDEBINFO}. (Historically this referenced the
  # mixed-case ${CMAKE_*_FLAGS_RelWithDebInfo}, an undefined -> empty variable,
  # so the Asan build silently compiled at -O0. That made the
  # dense-SVD SVDSBTL surface builds crawl and was the primary reason the ASan
  # CI job took ~45 min; with -O2 the full suite runs ~3 min locally / ~10 min
  # on the 2-vCPU runner.)  Keep these in sync with RelWithDebInfo if it changes.
  set(CMAKE_C_FLAGS_ASAN
      "-O2 -g -DNDEBUG -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
      "Flags used by the C compiler for Asan build type or configuration." FORCE)

  set(CMAKE_CXX_FLAGS_ASAN
      "-O2 -g -DNDEBUG -fsanitize=address -fno-omit-frame-pointer" CACHE STRING
      "Flags used by the C++ compiler for Asan build type or configuration." FORCE)

  set(CMAKE_EXE_LINKER_FLAGS_ASAN
      "-fsanitize=address" CACHE STRING
      "Linker flags to be used to create executables for Asan build type." FORCE)

  set(CMAKE_SHARED_LINKER_FLAGS_ASAN
      "-fsanitize=address" CACHE STRING
      "Linker flags to be used to create shared libraries for Asan build type." FORCE)

endif()

# see
# https://stackoverflow.com/questions/52509602/cant-compile-c-program-on-a-mac-after-upgrade-to-mojave
# https://support.enthought.com/hc/en-us/articles/204469410-OS-X-GCC-Clang-and-Cython-in-10-9-Mavericks
# https://github.com/pandas-dev/pandas/pull/24274/files
# https://github.com/explosion/thinc/pull/84/files
# https://github.com/jlfaucher/builder/commit/d144d3a695949f90c5e2acff4dfd94fdcf8dcdfa
# https://github.com/CoolProp/CoolProp/issues/1778
# https://gitlab.kitware.com/cmake/cmake/issues/18396
if(DEFINED DARWIN_USE_LIBCPP)
  if(DARWIN_USE_LIBCPP)
    set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -stdlib=libc++")
    set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -mmacosx-version-min=10.9")
    #set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -std=c++11")
    set(OSX_LINK_FLAGS "${OSX_LINK_FLAGS} -lc++")
    set(OSX_LINK_FLAGS "${OSX_LINK_FLAGS} -nodefaultlibs")
  else(DARWIN_USE_LIBCPP)
    set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -stdlib=libstdc++")
    set(OSX_COMPILE_FLAGS "${OSX_COMPILE_FLAGS} -mmacosx-version-min=10.5")
    set(OSX_LINK_FLAGS "${OSX_LINK_FLAGS} -lstdc++")
  endif(DARWIN_USE_LIBCPP)
  message(STATUS "DARWIN_USE_LIBCPP was set added some flags:")
  message(STATUS "  OSX_COMPILE_FLAGS: ${OSX_COMPILE_FLAGS}")
  message(STATUS "     OSX_LINK_FLAGS: ${OSX_LINK_FLAGS}")
else(DEFINED DARWIN_USE_LIBCPP)
  if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
    message(STATUS "OSX build detected:")
    message(
      STATUS "  You might want to pass the -DDARWIN_USE_LIBCPP=ON/OFF parameter"
    )
    message(STATUS "  to enable or disable different C++ standard libraries.")
    message(
      STATUS
        "  You can also specify the environment variable MACOSX_DEPLOYMENT_TARGET=10.9 to force clang builds."
    )
  endif("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
endif(DEFINED DARWIN_USE_LIBCPP)

#if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
#  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}${OSX_COMPILE_FLAGS}")
#  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}${OSX_COMPILE_FLAGS}")
#endif()
# Alternatively you could use
# set_target_properties(TARGET_NAME PROPERTIES APPEND_STRING PROPERTY COMPILE_FLAGS "-mmacosx-version-min=10.5")
# set_target_properties(TARGET_NAME PROPERTIES APPEND_STRING PROPERTY LINK_FLAGS "-mmacosx-version-min=10.5")

#######################################
#         PROJECT INFORMATION         #
#-------------------------------------#
# This CMakeLists.txt file is for the #
# CoolProp thermodynamic library      #
# written by Ian Bell. The following  #
# section contains project and        #
# version information.                #
#######################################

# The dev_checks tag gate (dev/ci/check_tag_version.py) requires a v* tag to
# match this version, so bump the variables above before tagging a release.
message(STATUS "CoolProp version: ${COOLPROP_VERSION}")

string(TIMESTAMP COOLPROP_YEAR 2010-%Y)
#set ( COOLPROP_YEAR "2010-2016" )
set(COOLPROP_PUBLISHER "The CoolProp developers")

# Add definitions to silence warnings in MSVC2017 related to shared ptr code.
#if (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919) # OR MSVC_TOOLSET_VERSION EQUAL 141) # This requuires CMake >= 3.7
#  add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
#endif (MSVC_VERSION GREATER_EQUAL 1910 AND MSVC_VERSION LESS_EQUAL 1919)

if(MSVC
   AND NOT (MSVC_VERSION LESS 1910)
   AND NOT (MSVC_VERSION GREATER 1919))
  add_definitions(-D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif()

if(MINGW)
  if (DEFINED ENV{MSYSTEM})
    message(STATUS "MSYS2 $ENV{MSYSTEM} environment detected")
    if ("$ENV{MSYSTEM}" STREQUAL "MINGW64")
      message(STATUS "MINGW64 environment detected. Ming-w64 is being phased out in favor of MSYS2 UCRT64, but it is still supported for now.")
      message(STATUS "To compile with MSYS2 UCRT64, run CMake from within the MSYS2 UCRT64 shell.")
    endif()
    if ("$ENV{MSYSTEM}" STREQUAL "MSYS")
      message(STATUS "MSYS environment detected. The MSYS environment is not recommended for building CoolProp.")
      message(FATAL_ERROR "To compile with MSYS2 UCRT64, run CMake from within the MSYS2 UCRT64 shell.")
    endif()
  else()
      message(STATUS "Original MINGW Detected. MinGW is deprecated in favor of MSYS2 UCRT64.")
      message(FATAL_ERROR "To compile with MSYS2 UCRT64, run CMake from within the MSYS2 UCRT64 shell.")
  endif()
endif()

if(COOLPROP_RELEASE AND COOLPROP_DEBUG)
  message(FATAL_ERROR "You can only make a release OR and debug build.")
endif()
if(COOLPROP_RELEASE)
  set(CMAKE_BUILD_TYPE Release)
elseif(COOLPROP_DEBUG)
  set(CMAKE_BUILD_TYPE Debug)
  #ELSEIF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
  #  IF("${COOLPROP_VERSION_REVISION}" STREQUAL "dev")
  #    SET(CMAKE_BUILD_TYPE Debug)
  #  ELSE ()
  #    SET(CMAKE_BUILD_TYPE Release)
  #  ENDIF()
endif()

# Ensure MSYS2/UCRT outputs are grouped by build type - emmulates MSVC behavior
if(MINGW AND DEFINED ENV{MSYSTEM})
  if("${CMAKE_BUILD_TYPE}" STREQUAL "")
    set(CMAKE_BUILD_TYPE Release)
  endif()
  set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
  set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
  set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}")
endif()

include_directories("${boost_headers_SOURCE_DIR}")

#######################################
#         FIND ALL SOURCES            #
#-------------------------------------#
# The project is organised with       #
# split includes and source folders   #
# this makes it easier for developers #
# to quickly find relevant includes.  #
# This section finds all sources,     #
# headers and corresponding dirs.     #
#######################################

# These backends will be compiled in
set(COOLPROP_ENABLED_BACKENDS
    Cubics
    IF97
    Helmholtz
    REFPROP
    Incompressible
    Tabular
    PCSAFT
    GERG)

# Get everything in the src/ directory (always), but not recursive
file(GLOB APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp")

# Generic SVD / Region components — sources live under src/SVD/ and
# src/Region/, headers under include/CoolProp/{svd,region}/.
# SBTL adapter layer (Phase 2b) sits on top — sources under src/SBTL/,
# headers under include/CoolProp/sbtl/.
file(GLOB SVD_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/SVD/*.cpp")
file(GLOB REGION_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Region/*.cpp")
file(GLOB SBTL_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/SBTL/*.cpp")
file(GLOB SVDSBTL_BACKEND_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Backends/SVDSBTL/*.cpp")
list(APPEND APP_SOURCES ${SVD_SOURCES} ${REGION_SOURCES} ${SBTL_SOURCES} ${SVDSBTL_BACKEND_SOURCES})

# Add the miniz source file
list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/externals/miniz-3.1.1/miniz.c")

# For each enabled backend, grab its files
foreach(backend ${COOLPROP_ENABLED_BACKENDS})
  file(GLOB_RECURSE BACKEND_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Backends/${backend}/*.cpp")
  list(APPEND APP_SOURCES ${BACKEND_SOURCES})
endforeach()

# Expression DSL for runtime-loaded transport correlations
file(GLOB EXPRESSION_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/expression/*.cpp")
list(APPEND APP_SOURCES ${EXPRESSION_SOURCES})

## You can exclude this file, in case you want to run your own tests or use Catch
list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp")
list(REMOVE_ITEM APP_SOURCES
     "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp")

## This file is only needed for the library, normal builds do not need it.
list(REMOVE_ITEM APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp")

set(APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}")
if(COOLPROP_VENDOR_THIRD_PARTY)
  list(APPEND APP_INCLUDE_DIRS ${COOLPROP_EIGEN_INCLUDE_DIRS})
endif()
list(APPEND APP_INCLUDE_DIRS "${msgpack-c_SOURCE_DIR}/include")
list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/miniz-3.1.1")
list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/externals/incbin")
list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/dev")
list(APPEND APP_INCLUDE_DIRS "${boost_headers_SOURCE_DIR}")
if(COOLPROP_VENDOR_THIRD_PARTY)
  list(APPEND APP_INCLUDE_DIRS ${COOLPROP_FMT_INCLUDE_DIRS})
endif()
list(APPEND APP_INCLUDE_DIRS "${nlohmann_json_SOURCE_DIR}/include")
list(APPEND APP_INCLUDE_DIRS "${valijson_SOURCE_DIR}/include")
# Valijson is consumed header-only (DOWNLOAD_ONLY), so its INTERFACE
# VALIJSON_USE_EXCEPTIONS define is not propagated. Set it explicitly so
# Valijson throws catchable exceptions on internal errors instead of abort().
add_compile_definitions(VALIJSON_USE_EXCEPTIONS=1)
list(APPEND APP_INCLUDE_DIRS "${IF97_SOURCE_DIR}")
list(APPEND APP_INCLUDE_DIRS "${REFPROP_headers_SOURCE_DIR}")

if (MSVC)
  # fmtlib requires that the utf-8 support be compiled in
  # TODO: add the fmt target from fmtlib directly which does this 
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj /MP /utf-8 -D_CRT_SECURE_NO_WARNINGS")
endif()
list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/include")
list(APPEND APP_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
# With COOLPROP_VENDOR_THIRD_PARTY=OFF the Eigen and fmt roots are system or
# package-manager prefixes (/opt/homebrew/include, a vcpkg or conda include
# dir, ...) which can also hold other libraries' headers, or an installed
# CoolProp.  Search them last, so they cannot shadow the pinned dependencies
# or CoolProp's own include/ and src/ trees.
if(NOT COOLPROP_VENDOR_THIRD_PARTY)
  list(APPEND APP_INCLUDE_DIRS ${COOLPROP_EIGEN_INCLUDE_DIRS}
       ${COOLPROP_FMT_INCLUDE_DIRS})
endif()

## Set endianess for msgpack on ARM64 with MSVC
#if(MSVC)
#  if("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "ARM64")
#    message(STATUS "Forcing msgpack-c to use little endian configuration")
#	add_compile_definitions(MSGPACK_ENDIAN_LITTLE_BYTE)
#  endif()
#endif()

include_directories(${APP_INCLUDE_DIRS})

set(SWIG_DEPENDENCIES
    ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/DataStructures.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/CoolProp.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/AbstractState.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/Configuration.h
    ${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/fluids/PhaseEnvelope.h)

set(COOLPROP_APP_SOURCES
    ${APP_SOURCES}
    CACHE STRING "List of CPP sources needed for CoolProp")
set(COOLPROP_INCLUDE_DIRECTORIES
    ${APP_INCLUDE_DIRS}
    CACHE STRING "List of include directories needed for CoolProp")

#######################################
#         REQUIRED MODULES            #
#-------------------------------------#
# CoolProp requires some standard OS  #
# features, these include:            #
# DL (CMAKE_DL_LIBS) for REFPROP      #
#######################################
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
                      "${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/Modules/")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
include(CoolPropJSONVisibility)

message(STATUS "Looking for Python")
# The floor is 3.9, matching requires-python in pyproject.toml: the build runs
# dev/generate_headers.py to embed the fluid data, and that script uses builtin
# generics such as list[Path], which are a syntax error before 3.9.
#
# Stating the floor here makes CMake skip an interpreter that is too old and
# keep looking.  Without it, a distribution whose default python3 predates 3.9
# (Leap 15.x still ships 3.6) configures happily and then dies mid-build with
# "TypeError: 'type' object is not subscriptable", which says nothing about the
# real problem.  That was a real OBS build failure.
find_package(Python 3.9 REQUIRED COMPONENTS Interpreter)
set(PYTHON_EXECUTABLE ${Python_EXECUTABLE})

include(FlagFunctions) # Is found since it is in the module path.

#if(MSVC)
#  add_compiler_flag_release("/EHsc")
#  add_compiler_flag_debug("/EHsc")
#endif()

#######################################
#                 BITNESS             #
#-------------------------------------#
#        Calculate if 32 or 64        #
#######################################

## If WIN32 (but NOT MINGW where bitness is determined from SIZEOF_VOID_P)
if(WIN32 AND NOT MINGW)
  if(CMAKE_CL_64)
    set(BITNESS "64")
  else()
    set(BITNESS "32")
  endif()
else()
  if(CMAKE_SIZEOF_VOID_P MATCHES "8")
    set(BITNESS "64")
  else()
    set(BITNESS "32")
  endif()
endif()

if(MSVC AND (FORCE_BITNESS_32 OR FORCE_BITNESS_64))
  message(
    STATUS
      "You cannot force a certain bitness for Visual Studio, use the generator settings for this purpose."
  )
  message(
    STATUS
      "Pass '-G \"Visual Studio 17 2022\" -A x64' to CMake to make a 64bit binary using VS2017 or later."
  )
  message(
    STATUS
      "Pass '-G \"Visual Studio 17 2022\" -A win32' to CMake to make a 32bit binary using VS2017 or later."
  )
  message(
    STATUS
      "Pass '-G \"Visual Studio 10 2010 Win64\"' to CMake to make a 64bit binary using VS2010."
  )
  message(
    STATUS
      "Pass '-G \"Visual Studio 10 2010\"' to CMake to make a 32bit binary using VS2010."
  )
  message(FATAL_ERROR "Fix that and try again...")
endif()

if(FORCE_BITNESS_32)
  set(BITNESS "32")
elseif(FORCE_BITNESS_64)
  set(BITNESS "64")
elseif(FORCE_BITNESS_NATIVE)
  set(BITNESS "NATIVE")
endif()

#######################################
#           BITNESS FLAG              #
#-------------------------------------#
# Decide ONCE whether -m32/-m64 can   #
# be used, and let every target below #
# use the answer.                     #
#######################################

# -m32 and -m64 pick between the two ABIs an x86 toolchain can both emit,
# which is what FORCE_BITNESS_32 is for.  Other architectures have one ABI per
# toolchain and reject the flag outright rather than ignoring it:
#
#     c++: error: unrecognized command-line option '-m64'          (aarch64)
#     c++: error: unrecognized command-line option '-m32'          (armhf)
#
# Both were real OBS build failures.  Rather than guess from the processor
# name, ask the compiler: a name list cannot know about every toolchain, and
# CMAKE_SYSTEM_PROCESSOR is empty when a toolchain file does not set it.
if(MSVC OR BITNESS STREQUAL "NATIVE")
  set(COOLPROP_BITNESS_FLAG "")
else()
  include(CheckCXXCompilerFlag)
  check_cxx_compiler_flag("-m${BITNESS}" COOLPROP_CXX_ACCEPTS_BITNESS_FLAG)
  if(COOLPROP_CXX_ACCEPTS_BITNESS_FLAG)
    set(COOLPROP_BITNESS_FLAG "-m${BITNESS}")
  else()
    set(COOLPROP_BITNESS_FLAG "")
    # BITNESS normally just describes CMAKE_SIZEOF_VOID_P, so dropping the
    # flag changes nothing.  Being asked for a bitness the toolchain cannot
    # produce is different, and is refused rather than silently ignored:
    # ignoring it would hand back a library of the other bitness.
    if(FORCE_BITNESS_32 OR FORCE_BITNESS_64)
      message(
        FATAL_ERROR
          "FORCE_BITNESS_32/64 needs a compiler that accepts -m${BITNESS}, and "
          "this one rejects it. Build for the bitness of the toolchain "
          "instead, or use a toolchain file that targets the other one.")
    endif()
  endif()
endif()

#######################################
#         SHARED POINTER              #
#-------------------------------------#
# In this section we define the       #
# flags needed to use shared_ptr      #
# reliably                            #
#######################################

include("${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/Modules/FindSharedPtr.cmake")
find_shared_ptr()
if(NOT SHARED_PTR_FOUND)
  message(FATAL_ERROR "Must be able to find shared_ptr")
else()
  if(SHARED_PTR_TR1_MEMORY_HEADER)
    add_definitions("-DSHARED_PTR_TR1_MEMORY_HEADER")
  endif()
  if(SHARED_PTR_TR1_NAMESPACE)
    add_definitions("-DSHARED_PTR_TR1_NAMESPACE")
  endif()
endif()

#######################################
#         MAKE ARTEFACTS              #
#-------------------------------------#
# In this section we define the       #
# artefacts (exes, libs) that will be #
# made for CoolProp, these include    #
# customisation from earlier options. #
#######################################

###     FLUIDS, MIXTURES JSON       ###
add_custom_target(
  generate_headers
  COMMAND "${PYTHON_EXECUTABLE}"
          "${CMAKE_CURRENT_SOURCE_DIR}/dev/generate_headers.py")

if(NOT COOLPROP_NO_EXAMPLES)
  add_custom_target(
    generate_examples
    COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Python
            "${CMAKE_CURRENT_BINARY_DIR}/Example.py"
    COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Octave
            "${CMAKE_CURRENT_BINARY_DIR}/Example.m"
    COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R
            "${CMAKE_CURRENT_BINARY_DIR}/Example.R"
    #COMMAND "${PYTHON_EXECUTABLE}" example_generator.py MATLAB "${CMAKE_CURRENT_BINARY_DIR}/Example.m"
    COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Java
            "${CMAKE_CURRENT_BINARY_DIR}/Example.java"
    COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Csharp
            "${CMAKE_CURRENT_BINARY_DIR}/Example.cs"
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples")
else()
  add_custom_target(
    generate_examples
    COMMAND
      echo
      "Example generation has been disabled with the COOLPROP_NO_EXAMPLES option."
  )
endif()

###      Library options            ###
# We already know the bitness from the earlier
# settings. Let us rely on that and only handle
# calling conventions and shared/static issues.

include(CoolPropLibrary)
coolprop_add_library_targets()

if(COOLPROP_IOS_TARGET)
  # Set the Base SDK (only change the SDKVER value, if for instance, you are building for iOS 5.0):
  set(SDKVER "9.2")
  set(DEVROOT
      "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer"
  )
  set(SDKROOT "${DEVROOT}/SDKs/iPhoneOS${SDKVER}.sdk")
  if(EXISTS ${SDKROOT})
    set(CMAKE_OSX_SYSROOT "${SDKROOT}")
  else()
    message("Warning, iOS Base SDK path not found: " ${SDKROOT})
  endif()

  # Will resolve to "Standard (armv6 armv7)" on Xcode 4.0.2 and to "Standard (armv7)" on Xcode 4.2:
  set(CMAKE_OSX_ARCHITECTURES "$(ARCHS_STANDARD_32_BIT)")

  # seamless toggle between device and simulator
  set(CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos;-iphonesimulator")

  include_directories(${CMAKE_CURRENT_SOURCE_DIR})
endif()

if(COOLPROP_VXWORKS_MAKEFILE)

  set(INCLUDE_DIRECTORIES)
  foreach(_srcFile ${APP_INCLUDE_DIRS})
    string(CONCAT _el "-I\"" ${_srcFile} "\"")
    string(REPLACE "${CMAKE_CURRENT_SOURCE_DIR}" "$(COOLPROP_ROOT)" _el
                   "${_el}")
    list(APPEND INCLUDE_DIRECTORIES ${_el})
  endforeach()
  string(REPLACE ";" " " INCLUDE_DIRECTORIES "${INCLUDE_DIRECTORIES}")
  set(OLD_ROOT /home/ian/.wine/drive_c/)
  set(NEW_ROOT c:/)
  string(REPLACE ${OLD_ROOT} ${NEW_ROOT} INCLUDE_DIRECTORIES
                 "${INCLUDE_DIRECTORIES}")
  set(SRC "${CMAKE_CURRENT_SOURCE_DIR}/src")
  string(REPLACE ${OLD_ROOT} ${NEW_ROOT} SRC "${SRC}")
  file(RELATIVE_PATH COOLPROP_ROOT "${CMAKE_CURRENT_BINARY_DIR}"
       "${CMAKE_CURRENT_SOURCE_DIR}")

  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Labview/vxWorks/Makefile.in"
    "vxWorksMakefile")
endif()

if(COOLPROP_VXWORKS_LIBRARY_MODULE OR COOLPROP_VXWORKS_LIBRARY)
  list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp")
  add_executable(${app_name} ${APP_SOURCES})
  set_target_properties(
    ${app_name} PROPERTIES SUFFIX ".out" COMPILE_FLAGS
                                         "${COMPILE_FLAGS} -DEXTERNC")
  add_dependencies(${app_name} generate_headers)
  install(TARGETS ${app_name}
          DESTINATION "shared_library/VxWorks")
endif()

if(COOLPROP_PRIME_MODULE)
  if(NOT WIN32)
    message(
      FATAL_ERROR "COOLPROP_PRIME_MODULE can only be used on windows host")
  endif()
  if("${COOLPROP_PRIME_ROOT}" STREQUAL "")
    message(
      FATAL_ERROR
        "You must provide the path to Mathcad Prime Root directory using something like -DCOOLPROP_PRIME_ROOT=\"C:/Program Files/PTC/Mathcad Prime 3.1\""
    )
  else()
    message(STATUS "COOLPROP_PRIME_ROOT: ${COOLPROP_PRIME_ROOT}")
  endif()
  list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/MathcadStateGuard.cpp")
  # Embed Windows VERSIONINFO so CoolPropPrimeWrapper.dll's Properties dialog shows
  # FileVersion/ProductVersion fields (#2391). The .rc is configured from
  # COOLPROP_VERSION_{MAJOR,MINOR,PATCH} above and added to the source list.
  # NOTE: Only here if WIN32, where rc.exe (or MSYS2 windres) is available.
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolProp.rc.in"
    "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.rc"
    @ONLY)
  list(APPEND APP_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.rc")
  # Source list complete, add all to library
  add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES})
  coolprop_hide_json_symbols(CoolPropMathcadWrapper)
  include_directories("${COOLPROP_PRIME_ROOT}/Custom Functions")
  target_link_libraries(CoolPropMathcadWrapper
                        "${COOLPROP_PRIME_ROOT}/Custom Functions/mcaduser.lib")
  set_target_properties(CoolPropMathcadWrapper
                        PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"")
  add_dependencies(CoolPropMathcadWrapper generate_headers)
  set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX
                                                                        "")
  install(TARGETS CoolPropMathcadWrapper
          DESTINATION MathcadPrime)
  install(
    FILES
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/Prime/CoolPropFluidProperties.mcdx"
    DESTINATION MathcadPrime)
  install(
    FILES
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/Prime/README.md"
    DESTINATION MathcadPrime)
endif()

if(COOLPROP_MATHCAD15_MODULE)
  if(NOT WIN32)
    message(
      FATAL_ERROR "COOLPROP_MATHCAD15_MODULE can only be used on windows host")
  endif()
  if("${COOLPROP_MATHCAD15_ROOT}" STREQUAL "")
    message(
      FATAL_ERROR
        "You must provide the path to MathCAD 15 Root directory using something like -DCOOLPROP_MATHCAD15_ROOT=\"C:/Program Files (x86)/Mathcad/Mathcad 15\""
    )
  else()
    message(STATUS "COOLPROP_MATHCAD15_ROOT: ${COOLPROP_MATHCAD15_ROOT}")
  endif()
  list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropMathcad.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/MathcadStateGuard.cpp")
  add_library(CoolPropMathcadWrapper SHARED ${APP_SOURCES})
  coolprop_hide_json_symbols(CoolPropMathcadWrapper)
  include_directories("${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/include")
  target_link_libraries(
    CoolPropMathcadWrapper
    "${COOLPROP_MATHCAD15_ROOT}/userefi/microsft/lib/mcaduser.lib")
  set_target_properties(CoolPropMathcadWrapper
                        PROPERTIES LINK_FLAGS "/ENTRY:\"DllEntryPoint\"")
  add_dependencies(CoolPropMathcadWrapper generate_headers)
  set_target_properties(CoolPropMathcadWrapper PROPERTIES SUFFIX ".dll" PREFIX
                                                                        "")
  install(TARGETS CoolPropMathcadWrapper
          DESTINATION MathCAD15)
  install(
    FILES
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolPropFluidProperties.xmcdz"
    DESTINATION MathCAD15)
  install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/MathCAD/CoolProp_EN.xml"
          DESTINATION MathCAD15)
endif()

# EES is compiled once per bitness: a ".dlf" that the 32-bit program loads from
# its USERLIB folder and a ".dlf64" that EES64.exe loads from USERLIB64.  EES
# refuses a library of the wrong bitness; see wrappers/EES/DEVELOPER.md.
if(COOLPROP_EES_MODULE)
  if(NOT WIN32)
    message(
      FATAL_ERROR
        "The EES wrapper is a Windows library, it cannot be built for ${CMAKE_SYSTEM_NAME}."
    )
  endif()
  if("${BITNESS}" STREQUAL "32")
    set(COOLPROP_EES_SUFFIX ".dlf")
    set(COOLPROP_EES_LIBRARY_NAME "CoolProp.LIB")
    # 32-bit Windows has several calling conventions, EES expects the C one
    set(COOLPROP_EES_CONVENTION "__cdecl")
  elseif("${BITNESS}" STREQUAL "64")
    set(COOLPROP_EES_SUFFIX ".dlf64")
    set(COOLPROP_EES_LIBRARY_NAME "CoolProp.LIB64")
    # x64 has a single calling convention, so no keyword is needed.  Leaving
    # CONVENTION undefined lets CoolPropLib.h fall back to __stdcall, which the
    # x64 compilers accept and ignore, the same as for the 64-bit CoolProp.dll.
    set(COOLPROP_EES_CONVENTION "")
  else()
    message(
      FATAL_ERROR
        "The EES wrapper needs a 32-bit or 64-bit build, BITNESS is '${BITNESS}'."
    )
  endif()
  # Prepare the sources
  include_directories(${APP_INCLUDE_DIRS})
  list(APPEND APP_SOURCES "wrappers/EES/main.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}")
  add_library(COOLPROP_EES SHARED ${APP_SOURCES})
  coolprop_hide_json_symbols(COOLPROP_EES)
  # Modify the target and add dependencies
  add_dependencies(COOLPROP_EES generate_headers)
  set_target_properties(COOLPROP_EES PROPERTIES COMPILE_FLAGS
                                                "${COMPILE_FLAGS} -DCOOLPROP_LIB")
  if(NOT "${COOLPROP_EES_CONVENTION}" STREQUAL "")
    set_property(
      TARGET COOLPROP_EES APPEND_STRING
      PROPERTY COMPILE_FLAGS " -DCONVENTION=${COOLPROP_EES_CONVENTION}")
  endif()
  set_target_properties(COOLPROP_EES PROPERTIES SUFFIX
                                                "${COOLPROP_EES_SUFFIX}" PREFIX "")
  # Creates "COOLPROP_EES.dlf" or "COOLPROP_EES.dlf64"
  if(NOT MSVC)
    # Only the 32-bit build needs -m32, and it is appended so that it does not
    # drop the defines set above.
    if("${BITNESS}" STREQUAL "32")
      set_property(
        TARGET COOLPROP_EES
        APPEND_STRING
        PROPERTY COMPILE_FLAGS " -m32")
      set_property(
        TARGET COOLPROP_EES
        APPEND_STRING
        PROPERTY LINK_FLAGS " -m32")
    endif()
  elseif(MSVC)
    set_target_properties(COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY
                                                  ${CMAKE_CURRENT_BINARY_DIR})
    set_target_properties(COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG
                                                  ${CMAKE_CURRENT_BINARY_DIR})
    set_target_properties(
      COOLPROP_EES PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE
                              ${CMAKE_CURRENT_BINARY_DIR})
    # etc for the other available configuration types (MinSizeRel, RelWithDebInfo)
  endif()
  # copy required files
  add_custom_command(
    TARGET COOLPROP_EES
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm"
      "${CMAKE_CURRENT_BINARY_DIR}/."
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB"
      "${CMAKE_CURRENT_BINARY_DIR}/${COOLPROP_EES_LIBRARY_NAME}"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES"
      "${CMAKE_CURRENT_BINARY_DIR}/."
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Copying the EES files to the build directory"
    VERBATIM)
  # install the generated library and the other files, one folder per bitness
  # so that a 32-bit and a 64-bit build do not overwrite each other.  The
  # destination stays relative: CMake resolves it against the install prefix,
  # and an absolute one would ignore "cmake --install --prefix" and DESTDIR.
  set(COOLPROP_EES_INSTALL_DIR "EES/${CMAKE_SYSTEM_NAME}/${BITNESS}bit")
  install(TARGETS COOLPROP_EES DESTINATION "${COOLPROP_EES_INSTALL_DIR}")
  install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.htm"
          DESTINATION "${COOLPROP_EES_INSTALL_DIR}")
  install(
    FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp.LIB"
    DESTINATION "${COOLPROP_EES_INSTALL_DIR}"
    RENAME "${COOLPROP_EES_LIBRARY_NAME}")
  install(
    FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/EES/CoolProp_EES_Sample.EES"
    DESTINATION "${COOLPROP_EES_INSTALL_DIR}")
endif()

# Windows package
if(COOLPROP_WINDOWS_PACKAGE)

  message(
    STATUS "Creating Windows installer for COOLPROP_VERSION=${COOLPROP_VERSION}"
  )
  # Setting some basic build paths
  set(COOLPROP_WINDOWS_PACKAGE_32B_DIR "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL")
  set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL
      "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_stdcall")
  set(COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL
      "${CMAKE_CURRENT_BINARY_DIR}/32bitDLL_cdecl")
  set(COOLPROP_WINDOWS_PACKAGE_64B_DIR "${CMAKE_CURRENT_BINARY_DIR}/64bitDLL")
  set(COOLPROP_WINDOWS_PACKAGE_ARM64_DIR "${CMAKE_CURRENT_BINARY_DIR}/arm64bitDLL")
  set(COOLPROP_WINDOWS_PACKAGE_EES_DIR "${CMAKE_CURRENT_BINARY_DIR}/EES")
  set(COOLPROP_WINDOWS_PACKAGE_EES64_DIR "${CMAKE_CURRENT_BINARY_DIR}/EES64")
  set(COOLPROP_WINDOWS_PACKAGE_TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/InnoScript")
  # Pointers to the sources
  set(COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Excel")
  set(COOLPROP_WINDOWS_PACKAGE_ISS_DIR "${ExcelAddinInstaller_SOURCE_DIR}")
  # Generator for DLLs
  set(COOLPROP_WINDOWS_PACKAGE_DLL_GEN "${CMAKE_GENERATOR}"
  )# Use the currently selected generator, architecture is hard-coded below
  # Configure variables like version number and build year
  configure_file(
    "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/cmake-templates/config.iss"
    "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}/config.iss")
  # Find the installer generator executable
  set(BINDIR32_ENV_NAME "ProgramFiles(x86)")
  set(BINDIR32 $ENV{${BINDIR32_ENV_NAME}})
  set(BINDIR64_ENV_NAME "ProgramFiles")
  set(BINDIR64 $ENV{${BINDIR64_ENV_NAME}})
  find_program(
    COOLPROP_WINDOWS_PACKAGE_ISS_EXE
    NAMES iscc.exe
    HINTS "${BINDIR32}/Inno Setup 6" "${BINDIR64}/Inno Setup 6")

  # ******************************************************************
  # Add the targets that prepare the build directory for the subbuilds
  # ******************************************************************
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_PREPARE)
  # Prepare directories
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_PREPARE
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_32B_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_ARM64_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_EES64_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source"
    #COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy"
    #COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory" "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin"
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Preparing the directories for the Windows installer"
    VERBATIM)

  add_custom_target(COOLPROP_WINDOWS_PACKAGE_DELETE)
  # Delete directories
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_DELETE
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin"
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Removing the old build directories for the Windows installer"
    VERBATIM)

  # **************************************************************
  # Add the target for the shared libraries, 2x 32bit and 1x 64bit
  # **************************************************************
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
                   COOLPROP_WINDOWS_PACKAGE_PREPARE)
  # Copy the header file
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${CMAKE_CURRENT_SOURCE_DIR}/include/CoolProp/CoolPropLib.h"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolPropLib.h"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR}
    COMMENT "Copy the header file for the CoolProp library"
    VERBATIM)
  # Build the 32bit DLLs
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32"
      "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_STATIC_LIBRARY=OFF"
      "-DCOOLPROP_SHARED_LIBRARY=ON"
      "-DCOOLPROP_STDCALL_LIBRARY=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config"
            "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}/Release/CoolProp.dll"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_stdcall.dll"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR_STDCALL}
    COMMENT "Building the 32bit shared library with stdcall"
    VERBATIM)
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}" "-AWin32"
      "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_STATIC_LIBRARY=OFF"
      "-DCOOLPROP_SHARED_LIBRARY=ON"
      "-DCOOLPROP_CDECL_LIBRARY=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config"
            "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}/Release/CoolProp.dll"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_cdecl.dll"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_32B_DIR_CDECL}
    COMMENT "Building the 32bit shared library with cdecl"
    VERBATIM)
  # Build the 64bit DLL
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}"
            "-Ax64" "${CMAKE_CURRENT_SOURCE_DIR}"
            "-DCOOLPROP_STATIC_LIBRARY=OFF" "-DCOOLPROP_SHARED_LIBRARY=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config"
            "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_64B_DIR}/Release/CoolProp.dll"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_x64.dll"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_64B_DIR}
    COMMENT "Building the 64bit shared library with x86_64 architecture"
    VERBATIM)

  # Build the 64bit DLL
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}"
            "-Aarm64" "${CMAKE_CURRENT_SOURCE_DIR}"
            "-DCOOLPROP_STATIC_LIBRARY=OFF" "-DCOOLPROP_SHARED_LIBRARY=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "CoolProp" "--config"
            "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_ARM64_DIR}/Release/CoolProp.dll"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/CoolProp_arm64.dll"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_ARM64_DIR}
    COMMENT "Building the 64bit shared library with arm64 architecture"
    VERBATIM)

  # *************************************************************
  # Add the target for EES and populate it with custom commands
  # *************************************************************
  # One target per bitness, both pulled in by the installer target below.
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_EES)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_EES
                   COOLPROP_WINDOWS_PACKAGE_PREPARE)
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_EES
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}"
            "-AWin32" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_EES_MODULE=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "COOLPROP_EES"
            "--config" "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy_directory"
      "${COOLPROP_WINDOWS_PACKAGE_EES_DIR}"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/EES"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_EES_DIR}
    COMMENT "Building the 32bit library for EES"
    VERBATIM)

  add_custom_target(COOLPROP_WINDOWS_PACKAGE_EES64)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_EES64
                   COOLPROP_WINDOWS_PACKAGE_PREPARE)
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_EES64
    PRE_BUILD
    COMMAND ${CMAKE_COMMAND} ARGS "-G${COOLPROP_WINDOWS_PACKAGE_DLL_GEN}"
            "-Ax64" "${CMAKE_CURRENT_SOURCE_DIR}" "-DCOOLPROP_EES_MODULE=ON"
    COMMAND ${CMAKE_COMMAND} ARGS "--build" "." "--target" "COOLPROP_EES"
            "--config" "Release"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy_directory"
      "${COOLPROP_WINDOWS_PACKAGE_EES64_DIR}"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/EES64"
    WORKING_DIRECTORY ${COOLPROP_WINDOWS_PACKAGE_EES64_DIR}
    COMMENT "Building the 64bit library for EES"
    VERBATIM)

  # *************************************************************
  # Add the target for Excel and populate it with custom commands
  # *************************************************************
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_EXCEL)
  add_dependencies(
    COOLPROP_WINDOWS_PACKAGE_EXCEL COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES
    COOLPROP_WINDOWS_PACKAGE_PREPARE)
  # Copy the Excel files
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_EXCEL
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/source/"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "remove_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/"
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xla"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/CoolProp.xlam"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy"
      "${COOLPROP_WINDOWS_PACKAGE_EXCEL_DIR}/TestExcel.xlsx"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/MicrosoftExcel/"
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Copying the Excel files for the installer"
    VERBATIM)

  # *******************************************************************
  # Add the target for Inno Script and populate it with custom commands
  # *******************************************************************
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_ISS)
  add_dependencies(
    COOLPROP_WINDOWS_PACKAGE_ISS COOLPROP_WINDOWS_PACKAGE_EXCEL
    COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES COOLPROP_WINDOWS_PACKAGE_PREPARE)
  # Copy the ISS files
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_ISS
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy_directory"
      "${COOLPROP_WINDOWS_PACKAGE_ISS_DIR}"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}"
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    COMMENT "Copying the Inno Script files for the installer"
    VERBATIM)

  # *****************************************************************************
  # Add the target for the installer package and populate it with custom commands
  # *****************************************************************************
  add_custom_target(COOLPROP_WINDOWS_PACKAGE_INSTALLER)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_DELETE)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_PREPARE)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_SHARED_LIBRARIES)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_EES)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_EES64)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_EXCEL)
  add_dependencies(COOLPROP_WINDOWS_PACKAGE_INSTALLER
                   COOLPROP_WINDOWS_PACKAGE_ISS)
  # Build the installer and copy it to the bin directory
  add_custom_command(
    TARGET COOLPROP_WINDOWS_PACKAGE_INSTALLER
    POST_BUILD
    COMMAND ${COOLPROP_WINDOWS_PACKAGE_ISS_EXE} ARGS "addin-installer.iss"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy_directory"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/deploy"
      "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows"
    WORKING_DIRECTORY "${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}"
    COMMENT
      "The new installer is located in '${COOLPROP_WINDOWS_PACKAGE_TMP_DIR}/bin/Installers/Windows'"
    VERBATIM)
endif()

if(COOLPROP_OCTAVE_MODULE)

  # Must have SWIG and Octave
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})
  find_package(Octave REQUIRED)

  # Make a src directory to deal with file permissions problem with MinGW makefile
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src)

  # Set the include folders
  set(OCTAVE_WRAP_INCLUDE_DIRS ${INCLUDE_DIR})
  foreach(ITR ${OCTAVE_INCLUDE_DIRS})
    list(APPEND OCTAVE_WRAP_INCLUDE_DIRS ${ITR})
    # https://stackoverflow.com/questions/7035734/how-do-i-get-the-parent-directory-path-of-a-path-in-cmake
    get_filename_component(PARENT_DIR ${ITR} DIRECTORY)
    list(APPEND OCTAVE_WRAP_INCLUDE_DIRS ${PARENT_DIR})
    message(STATUS "PARENT_DIR: ${PARENT_DIR}")
  endforeach()
  include_directories(${OCTAVE_WRAP_INCLUDE_DIRS})
  message(STATUS "OCTAVE_WRAP_INCLUDE_DIRS: ${OCTAVE_WRAP_INCLUDE_DIRS}")

  # Disable internal error catching and allow swig to do the error catching itself
  add_definitions(-DNO_ERROR_CATCHING)

  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")

  set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON)

  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})
  swig_add_library(
    CoolProp
    LANGUAGE octave 
    SOURCES ${I_FILE} ${APP_SOURCES}
  )

  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    # We need to see which library to link with on OSX - clang++ or stdc++
    message(STATUS "OCTAVE_OCTAVE_LIBRARY = ${OCTAVE_OCTAVE_LIBRARY}")
    if(${CMAKE_VERSION} VERSION_LESS "3.10.0")
      execute_process(COMMAND "otool -L ${OCTAVE_OCTAVE_LIBRARY} | grep libc++"
                      OUTPUT_VARIABLE COOLPROP_OCTAVE_USING_CLANG)
      message(
        STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}")
      string(STRIP "${COOLPROP_OCTAVE_USING_CLANG}" COOLPROP_OCTAVE_USING_CLANG)
    else()
      execute_process(
        COMMAND "otool -L ${OCTAVE_OCTAVE_LIBRARY}"
        COMMAND "grep libc++"
        OUTPUT_VARIABLE COOLPROP_OCTAVE_USING_CLANG
        ERROR_VARIABLE COOLPROP_OCTAVE_USING_CLANG)
      message(
        STATUS "COOLPROP_OCTAVE_USING_CLANG = ${COOLPROP_OCTAVE_USING_CLANG}")
      string(STRIP "${COOLPROP_OCTAVE_USING_CLANG}" COOLPROP_OCTAVE_USING_CLANG)
    endif()

    string(LENGTH "${COOLPROP_OCTAVE_USING_CLANG}" LEN)
    if(${LEN} GREATER 0)
      message(
        STATUS
          "Using -stdlib=libc++, this might override the settings based on DARWIN_USE_LIBCPP"
      )
      set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
    else()
      message(
        STATUS
          "Using -stdlib=libstdc++, this might override the settings based on DARWIN_USE_LIBCPP"
      )
      set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libstdc++")
    endif()
  endif()

  if(WIN32)
    include_directories($ENV{OCTAVE_ROOT}/include)
    include_directories(
      $ENV{OCTAVE_ROOT}/include/octave-${OCTAVE_VERSION}/octave)
    set_target_properties(CoolProp PROPERTIES COMPILE_FLAGS "-fpermissive")
    swig_link_libraries(CoolProp octave octinterp)
    set_target_properties(
      CoolProp
      PROPERTIES
        LINK_FLAGS
        "-L$ENV{OCTAVE_ROOT}/mingw64/lib/octave/${OCTAVE_VERSION} -L$ENV{OCTAVE_ROOT}"
    )
  else()
    swig_link_libraries(CoolProp ${OCTAVE_LIBRARIES})
  endif()
  coolprop_hide_json_symbols(CoolProp)

  set_target_properties(CoolProp PROPERTIES SUFFIX ".oct" PREFIX "")
  add_dependencies(${app_name} generate_headers generate_examples)

  #add_custom_command(TARGET CoolProp
  #                   POST_BUILD
  #                   COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Octave "${CMAKE_CURRENT_BINARY_DIR}/Example.m"
  #                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples")
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.m" DESTINATION Octave)
  install(
    TARGETS ${app_name}
    DESTINATION
      Octave/Octave${OCTAVE_VERSION}_${CMAKE_SYSTEM_NAME}_${BITNESS}bit)
endif()

if(COOLPROP_CSHARP_MODULE)

  # Must have SWIG and C#
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})
  find_package(Csharp REQUIRED)

  # Make a src directory to deal with file permissions problem with MinGW makefile
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src)

  # SWIG's -dllimport sets the library name embedded in the generated C#
  # [DllImport(...)] attributes.  It must match the renamed native OUTPUT_NAME
  # ("CoolPropCsharp") on EVERY platform, not just Windows -- otherwise the
  # macOS/Linux bindings target the default "CoolProp" module name and fail to
  # load the renamed shared library.
  set(MORE_SWIG_FLAGS -dllimport \"CoolPropCsharp\")

  # Define which headers the CoolProp wrapper is dependent on
  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})

  set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}" "${MORE_SWIG_FLAGS}" "-DSWIG_CSHARP_NO_STRING_WITH_LENGTH_HELPER")
  string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}")
  message(STATUS "options passed to swig: ${SWIG_OPTIONS}")

  # Set properties before adding module
  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")
  set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}"
                                                   CPLUSPLUS ON)

  swig_add_module(CoolProp csharp ${I_FILE} ${APP_SOURCES})
  set_target_properties(CoolProp PROPERTIES OUTPUT_NAME "CoolPropCsharp")
  coolprop_hide_json_symbols(CoolProp)

  add_definitions(-DNO_ERROR_CATCHING)

  #disable internal error catching and allow swig to do the error catching itself

  if(WIN32)
    set_target_properties(CoolProp PROPERTIES PREFIX "")
    if(MSVC)
      _coolprop_set_msvc_runtime(CoolProp SHARED)
    endif()
  endif()
  if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    set_target_properties(CoolProp PROPERTIES PREFIX "lib")
  endif()
  if(UNIX)
    set_target_properties(CoolProp PROPERTIES PREFIX "lib")
  endif()

  add_dependencies(${app_name} generate_headers generate_examples)

  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z"
            "${CMAKE_CURRENT_BINARY_DIR}/*.cs" -x!Example.cs
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
  #add_custom_command(TARGET CoolProp
  #                   POST_BUILD
  #                   COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Csharp "${CMAKE_CURRENT_BINARY_DIR}/Example.cs"
  #                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples")
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.cs" DESTINATION Csharp)
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z"
          DESTINATION Csharp)
  install(TARGETS ${app_name}
          DESTINATION Csharp/${CMAKE_SYSTEM_NAME}_${BITNESS}bit)
  enable_testing()
  if(DEFINED BUILD_TESTING)
    execute_process(
      COMMAND ${CMAKE_COMMAND} -E make_directory
              ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS})
    # Copy the shared object to the folder with the executable - no idea like java.library.path in C#
    install(
      TARGETS ${app_name}
      DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS})
  endif()
  file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/*.cs cp_cs_path)
  if(${BITNESS} EQUAL "32")
    set(CSHARP_PLAT "-platform:x86")
  elseif((${BITNESS} EQUAL "64"))
    set(CSHARP_PLAT "-platform:x64")
  endif()
  add_test(
    NAME Csharptestbuild
    COMMAND ${CSHARP_COMPILER} -out:Example.exe ${CSHARP_PLAT} ${cp_cs_path}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS})
  add_test(
    NAME Csharptestrun
    COMMAND ${CSHARP_INTERPRETER} Example.exe
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Csharp${BITNESS})
endif()

if(COOLPROP_VBDOTNET_MODULE)

  # Must have SWIG and C#
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})
  find_package(Csharp REQUIRED)

  # Make a src directory to deal with file permissions problem with MinGW makefile
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB)

  set(MORE_SWIG_FLAGS -dllimport \"CoolPropCsharp\" -namespace CoolProp)
  set(CMAKE_SWIG_OUTDIR CoolPropVB/CsharpClassLibrary)

  # Define which headers the CoolProp wrapper is dependent on
  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})

  set(SWIG_OPTIONS "${MORE_SWIG_FLAGS}" "-DSWIG_CSHARP_NO_STRING_WITH_LENGTH_HELPER")
  string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}")
  message(STATUS "options passed to swig: ${SWIG_OPTIONS}")

  # Set properties before adding module
  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")
  set_property(SOURCE ${I_FILE} PROPERTY CPLUSPLUS ON)
  set_property(SOURCE ${I_FILE} PROPERTY SWIG_FLAGS ${SWIG_OPTIONS})
  swig_add_module(CoolProp csharp ${I_FILE} ${APP_SOURCES})
  set_target_properties(CoolProp PROPERTIES OUTPUT_NAME "CoolPropCsharp")
  coolprop_hide_json_symbols(CoolProp)

  add_definitions(-DNO_ERROR_CATCHING)

  #disable internal error catching and allow swig to do the error catching itself

  if(WIN32)
    set_target_properties(CoolProp PROPERTIES PREFIX "")
  endif()

  add_dependencies(${app_name} generate_headers)

  add_custom_command(
    TARGET CoolProp
    PRE_BUILD
    COMMAND
      ${CMAKE_COMMAND} -E copy_directory
      ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/VB.NET/CoolPropVB
      ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:CoolProp>
            ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CoolPropVB
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND
      ${CMAKE_COMMAND} -E remove
      ${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB/CsharpClassLibrary/CoolPropCSHARP_wrap.cxx
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z"
            "${CMAKE_CURRENT_BINARY_DIR}/CoolPropVB"
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/VB.net_VS2012_example.7z"
          DESTINATION VB.NET)

endif()

if(COOLPROP_R_MODULE)
  if(WIN32 AND MSVC)
    message(FATAL_ERROR "Must use MinGW Makefiles generator on windows")
  endif()

  # Must have SWIG
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})

  # Define which headers the swig wrapper is dependent on
  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})

  find_package(R REQUIRED)
  include_directories(${R_INCLUDE_DIRS})

  link_directories(${R_BIN_OUT})
  if(NOT MSVC)
    set(CMAKE_CXX_FLAGS_RELEASE
        "${CMAKE_CXX_FLAGS_RELEASE} ${COOLPROP_BITNESS_FLAG}")
    set(CMAKE_CXX_FLAGS_DEBUG
        "${CMAKE_CXX_FLAGS_DEBUG} ${COOLPROP_BITNESS_FLAG}")
  endif()

  add_definitions(-DNO_ERROR_CATCHING)

  #disable internal error catching and allow swig to do the error catching itself

  # Set properties before adding module
  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")
  set_source_files_properties(
    ${I_FILE} PROPERTIES SWIG_FLAGS "${COOLPROP_SWIG_OPTIONS}" CPLUSPLUS ON)

  swig_add_module(CoolProp r ${I_FILE} ${APP_SOURCES})
  swig_link_libraries(CoolProp "${R_LIBRARY}")
  coolprop_hide_json_symbols(CoolProp)
  set_target_properties(CoolProp PROPERTIES OUTPUT_NAME "CoolPropR")

  # No lib prefix for the shared library
  set_target_properties(CoolProp PROPERTIES PREFIX "")

  # Patch the generated R proxy's PACKAGE= references to the renamed library (#1674)
  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -DRFILE=${CMAKE_CURRENT_BINARY_DIR}/CoolProp.R -P
            ${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/patch_r_package.cmake
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")

  add_dependencies(${app_name} generate_headers generate_examples)
  #add_custom_command(TARGET CoolProp
  #                   POST_BUILD
  #                   COMMAND "${PYTHON_EXECUTABLE}" example_generator.py R "${CMAKE_CURRENT_BINARY_DIR}/Example.R"
  #                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples")
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.R" DESTINATION R)
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.R" DESTINATION R)
  install(TARGETS ${app_name} DESTINATION R/${CMAKE_SYSTEM_NAME}_${BITNESS}bit)

  enable_testing()

  add_test(R_test "${R_BIN_DIR}/Rscript" Example.R)

endif()

if(COOLPROP_JAVA_MODULE)

  # Must have SWIG and Java
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})
  find_package(Java REQUIRED)
  find_package(JNI)

  # Compile Java bindings for Java 11 (maximum compatibility)
  set(CMAKE_JAVA_COMPILE_FLAGS "-source 11 -target 11")
  
  # Determine if there is a custom Java package being used and ensure correct directory structure.
  string(REGEX MATCH "-package[ ]+([A-Za-z0-9_.]+)" _pkg_match "${COOLPROP_SWIG_OPTIONS}")
  set(JAVA_PACKAGE "${CMAKE_MATCH_1}")
  string(REPLACE "." "/" JAVA_PACKAGE_DIR "${JAVA_PACKAGE}")

  # Make a src directory to deal with file permissions problem with MinGW makefile
  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/src)

  message(STATUS "JAVA_INCLUDE_PATH = ${JAVA_INCLUDE_PATH}")

  include_directories(${JAVA_INCLUDE_PATH})
  include_directories(${JAVA_INCLUDE_PATH}/win32)
  include_directories(${JAVA_INCLUDE_PATH}/linux)
  include_directories(${JAVA_INCLUDE_PATH}/darwin)

  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")

  set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}")
  string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON)

  add_definitions(-DNO_ERROR_CATCHING)

  #disable internal error catching and allow swig to do the error catching itself

  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})
  swig_add_module(CoolProp java ${I_FILE} ${APP_SOURCES})
  set_target_properties(CoolProp PROPERTIES OUTPUT_NAME "CoolPropJava")
  coolprop_hide_json_symbols(CoolProp)

  # Relocate SWIG-generated Java files into the package directory (cross-platform).
  # Only when a -package was requested via COOLPROP_SWIG_OPTIONS: without one the
  # generated sources belong in the default package (flat in the binary dir) and
  # relocating would run with DST_DIR == SRC_DIR.
  if(NOT JAVA_PACKAGE_DIR STREQUAL "")
    add_custom_command(
        TARGET CoolProp
        POST_BUILD
        COMMAND ${CMAKE_COMMAND} -D SRC_DIR="${CMAKE_CURRENT_BINARY_DIR}"
                                 -D DST_DIR="${CMAKE_CURRENT_BINARY_DIR}/${JAVA_PACKAGE_DIR}"
                                 -P "${CMAKE_CURRENT_SOURCE_DIR}/dev/cmake/relocate_java.cmake"
    )
  endif()

  if(WIN32)
    set_target_properties(CoolProp PROPERTIES PREFIX "")
    if(MSVC)
      _coolprop_set_msvc_runtime(CoolProp SHARED)
    endif()
  endif()

  if(NOT MSVC)
    set_target_properties(
      CoolProp PROPERTIES COMPILE_FLAGS "${COOLPROP_BITNESS_FLAG}"
                          LINK_FLAGS "${COOLPROP_BITNESS_FLAG}")
  endif()

  add_dependencies(${app_name} generate_headers generate_examples)

  # With a package, the .java sources live under the package directory after
  # relocation; without one they are flat in the binary dir (the pre-package
  # behavior, where an empty JAVA_PACKAGE_DIR would otherwise make the glob
  # the literal filesystem root "/*.java" and archive nothing)
  if(NOT JAVA_PACKAGE_DIR STREQUAL "")
    set(JAVA_ARCHIVE_GLOB "${JAVA_PACKAGE_DIR}/*.java")
  else()
    set(JAVA_ARCHIVE_GLOB "${CMAKE_CURRENT_BINARY_DIR}/*.java" "-x!Example.java")
  endif()
  add_custom_command(
    TARGET CoolProp
    POST_BUILD
    COMMAND 7z a "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z"
            ${JAVA_ARCHIVE_GLOB}
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
  #add_custom_command(TARGET CoolProp
  #                   POST_BUILD
  #                   COMMAND "${PYTHON_EXECUTABLE}" example_generator.py Java "${CMAKE_CURRENT_BINARY_DIR}/Example.java"
  #                   WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/dev/scripts/examples")
  #
  # Install all the generated java files
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/Example.java"
          DESTINATION Java)
  # Ship the archive alongside the unpacked tree, matching the Csharp layout.
  # #3245 dropped this rule when it replaced the flat-glob install with the
  # package-tree DIRECTORY install, which left the release area without the
  # archive that dev/scripts/examples/win64run.py still fetches from
  # nightly/Java/platform-independent.7z (CoolProp-qrn3).
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/platform-independent.7z"
          DESTINATION Java)
  if(NOT JAVA_PACKAGE_DIR STREQUAL "")
    # Install the package tree rooted at its FIRST path component so the full
    # package layout is preserved under platform-independent/.  The parent-of-
    # leaf form (get_filename_component ... DIRECTORY) is empty for a single-
    # segment package -- which would install the entire binary dir -- and drops
    # the top-level directory for packages more than two segments deep.
    string(REGEX REPLACE "/.*" "" JAVA_PACKAGE_TOP "${JAVA_PACKAGE_DIR}")
    if(JAVA_PACKAGE_TOP STREQUAL "")
      # e.g. '-package .coolprop': an empty top component would make the
      # DIRECTORY rule below install the entire binary dir
      message(FATAL_ERROR "Invalid -package value in COOLPROP_SWIG_OPTIONS: '${JAVA_PACKAGE}'")
    endif()
    install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${JAVA_PACKAGE_TOP}"
        DESTINATION Java/platform-independent)
  else()
    # No package: flat default-package sources.  An empty JAVA_PACKAGE_TOP in
    # the DIRECTORY form above would install the entire binary dir.
    install(
      CODE "file( GLOB _GeneratedJavaSources \"${CMAKE_CURRENT_BINARY_DIR}/*.java\" )"
      CODE "file( INSTALL \${_GeneratedJavaSources} DESTINATION \${CMAKE_INSTALL_PREFIX}/Java/platform-independent )"
    )
  endif()


  install(
    TARGETS ${app_name}
    DESTINATION Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit)
  enable_testing()
  execute_process(
    COMMAND ${CMAKE_COMMAND} -E make_directory
            ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS})
  add_test(
    NAME Javatestbuild
    COMMAND javac -d . ${CMAKE_INSTALL_PREFIX}/Java/Example.java -cp
            ${CMAKE_INSTALL_PREFIX}/Java/platform-independent
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS})
  add_test(
    NAME Javatestrun
    COMMAND
      ${Java_JAVA_EXECUTABLE}
      -Djava.library.path=${CMAKE_INSTALL_PREFIX}/Java/${CMAKE_SYSTEM_NAME}_${BITNESS}bit
      Example
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/testing_root/Java${BITNESS})
endif()

# A module for Android
if(COOLPROP_ANDROID_MODULE)

  if(WIN32 AND (NOT MINGW))
    message(
      FATAL_ERROR "On windows, you must use the MinGW Makefiles generator ")
  endif()

  # For now, these must be changed manually
  set(ANDROID_MODULE_NAME "CoolProp")
  set(ANDROID_PACKAGE_NAME "CoolProp") # or blah.di.blah.CoolProp

  # Must have SWIG
  find_package(SWIG REQUIRED)

  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")

  list(APPEND APP_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx)
  string(REPLACE ";" " " APP_INCLUDE_DIRS "${APP_INCLUDE_DIRS}")
  string(REPLACE ";" " " APP_SOURCES "${APP_SOURCES}")

  file(MAKE_DIRECTORY jni)
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Android/Android.mk.template"
    "${CMAKE_CURRENT_BINARY_DIR}/jni/Android.mk")
  file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Android/Application.mk"
       DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/jni")
  string(REPLACE "." "/" ANDROID_PACKAGE_PATH "${ANDROID_PACKAGE_NAME}")
  file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_PACKAGE_PATH}")

  message(STATUS "WORKING_DIRECTORY=${CMAKE_CURRENT_BINARY_DIR}")
  get_filename_component(NDK_BUILD_PATH "${NDK_PATH}/ndk-build" ABSOLUTE)
  get_filename_component(SRC_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src" ABSOLUTE)
  get_filename_component(INCLUDE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/include"
                         ABSOLUTE)

  add_custom_target(
    CoolProp ALL
    COMMAND ${NDK_BUILD_PATH}
    DEPENDS jni/CoolProp_wrap.cxx
    VERBATIM)

  add_custom_command(
    OUTPUT jni/CoolProp_wrap.cxx
    COMMAND
      ${SWIG_EXECUTABLE} -v -c++ -java -I${SRC_PATH} -I${INCLUDE_PATH} -o
      ${CMAKE_CURRENT_BINARY_DIR}/jni/CoolProp_wrap.cxx -package
      ${ANDROID_PACKAGE_NAME} -outdir
      ${CMAKE_CURRENT_BINARY_DIR}/${ANDROID_PACKAGE_PATH} ${I_FILE}
    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
    VERBATIM)

  add_dependencies(CoolProp generate_headers)

endif()

if(COOLPROP_PHP_MODULE)

  # Must have SWIG
  find_package(SWIG REQUIRED)
  include(${SWIG_USE_FILE})

  execute_process(
    COMMAND php-config --includes
    OUTPUT_VARIABLE php_config_includes
    RESULT_VARIABLE php_config_failed)
  if(php_config_failed)
    message(FATAL_ERROR "calling \"php-config --includes\" failed; message:"
                        ${php_config_includes})
  endif()
  string(STRIP "${php_config_includes}" php_config_includes)
  string(REPLACE "-I" "" PHP_INCLUDES "${php_config_includes}")
  separate_arguments(PHP_INCLUDES)

  message(STATUS "php includes=${PHP_INCLUDES}")
  include_directories(${PHP_INCLUDES})

  add_definitions(-DNO_ERROR_CATCHING)

  #disable internal error catching and allow swig to do the error catching itself

  set(I_FILE "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolProp.i")

  set(SWIG_OPTIONS "${COOLPROP_SWIG_OPTIONS}")
  string(REPLACE " " ";" SWIG_OPTIONS "${SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES SWIG_FLAGS "${SWIG_OPTIONS}")
  set_source_files_properties(${I_FILE} PROPERTIES CPLUSPLUS ON)

  set(SWIG_MODULE_CoolProp_EXTRA_DEPS ${SWIG_DEPENDENCIES})
  swig_add_module(CoolProp php ${I_FILE} ${APP_SOURCES})
  set_target_properties(CoolProp PROPERTIES OUTPUT_NAME "CoolPropPHP")
  coolprop_hide_json_symbols(CoolProp)

  if(WIN32)
    set_target_properties(CoolProp PROPERTIES PREFIX "")
  endif()

  if(NOT MSVC)
    set_target_properties(
      CoolProp PROPERTIES COMPILE_FLAGS "${COOLPROP_BITNESS_FLAG}"
                          LINK_FLAGS "${COOLPROP_BITNESS_FLAG}")
  endif()
  add_dependencies(CoolProp generate_headers)

  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CoolProp.php
          DESTINATION PHP/cross-platform OPTIONAL)
  install(TARGETS ${app_name}
          DESTINATION PHP/${CMAKE_SYSTEM_NAME})

endif()

function(JOIN VALUES GLUE OUTPUT)
  string(REGEX REPLACE "([^\\]|^);" "\\1${GLUE}" _TMP_STR "${VALUES}")
  string(REGEX REPLACE "[\\](.)" "\\1" _TMP_STR "${_TMP_STR}") #fixes escaping
  set(${OUTPUT}
      "${_TMP_STR}"
      PARENT_SCOPE)
endfunction()

if(COOLPROP_PYTHON_BINARIES)
  if(WIN32)
    set(COOLPROP_PYTHON_BINARY_VERSIONS
        bdist_wheel --dist-dir ${CMAKE_INSTALL_PREFIX}/Python bdist_wininst
        --dist-dir ${CMAKE_INSTALL_PREFIX}/Python)
  elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
    set(COOLPROP_PYTHON_BINARY_VERSIONS bdist_wheel --dist-dir
                                        ${CMAKE_INSTALL_PREFIX}/Python)
  endif()

  add_custom_target(
    CoolProp
    COMMAND python setup.py ${COOLPROP_PYTHON_BINARY_VERSIONS}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python)

endif()

if(COOLPROP_PYTHON_PYPI)

  add_custom_target(
    CoolProp
    COMMAND python prepare_pypi.py --dist-dir=${CMAKE_INSTALL_PREFIX}/Python
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Python/pypi)
endif()

if(COOLPROP_LIBREOFFICE_MODULE)

  if("${LO_PROGRAM_PATH}" STREQUAL "")
    message(
      FATAL_ERROR
        "You must provide the path to LibreOffice programs, something like -DLO_PROGRAM_PATH=/usr/lib/libreoffice/program"
    )
  else()
    message(STATUS "LO_PROGRAM_PATH: ${LO_PROGRAM_PATH}")
  endif()

  if("${LO_SDK_PATH}" STREQUAL "")
    message(
      FATAL_ERROR
        "You must provide the path to LibreOffice SDK, something like -DLO_SDK_PATH=/usr/lib/libreoffice/sdk"
    )
  else()
    message(STATUS "LO_SDK_PATH: ${LO_SDK_PATH}")
  endif()

  # set paths for LibreOffice tools
  set(LO_UNOIDL_WRITE "${LO_SDK_PATH}/bin/unoidl-write")
  set(COOLPROP_LIBREOFFICE_TMP_DIR "${CMAKE_CURRENT_BINARY_DIR}/LibreOffice")

  # set version strings for LibreOffice extension
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/description.xml.in"
    "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml")
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src/scripts/scripts.py.in"
    "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py")

  add_custom_target(CoolPropLibreOfficeAddin ALL DEPENDS CoolProp.oxt)
    
  add_custom_command(
    OUTPUT CoolProp.oxt
    # copy source files to build directory
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy_directory"
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/src"
      "${COOLPROP_LIBREOFFICE_TMP_DIR}/src"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "remove"
      "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/description.xml.in"
      "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/scripts/scripts.py.in"
    # build the registry database file (rdb)
    COMMAND
      ${LO_UNOIDL_WRITE}
      ${LO_PROGRAM_PATH}/types.rdb ${LO_PROGRAM_PATH}/types/offapi.rdb
      XCoolProp.idl XCoolProp.rdb
    # download and bundle latest Python pip package (py2.py3, platform independent)
    COMMAND pip download pip -d pythonpath
    COMMAND 7z x "./pythonpath/pip-*.whl" -y -opythonpath
    # download and bundle latest Python certifi package (py2.py3, platform independent)
    COMMAND pip download certifi -d pythonpath
    COMMAND 7z x "./pythonpath/certifi-*.whl" -y -opythonpath
    # add license file
    COMMAND ${CMAKE_COMMAND} ARGS "-E" "make_directory"
            "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license"
    COMMAND
      ${CMAKE_COMMAND} ARGS "-E" "copy" "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE"
      "${COOLPROP_LIBREOFFICE_TMP_DIR}/src/license/."
    # package complete folder to extension
    COMMAND 7z a -tzip "../CoolProp.oxt"
    WORKING_DIRECTORY ${COOLPROP_LIBREOFFICE_TMP_DIR}/src
    COMMENT "Building LibreOffice wrapper"
    VERBATIM)

   # install LibreOffice extension and example spreadsheet file
   install(FILES "${COOLPROP_LIBREOFFICE_TMP_DIR}/CoolProp.oxt"
           DESTINATION LibreOffice)
   install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/LibreOffice/TestLibreOffice.ods"
           DESTINATION LibreOffice)
endif()

if(COOLPROP_JAVASCRIPT_MODULE)
  # cmake -DCOOLPROP_JAVASCRIPT_MODULE=ON
  #       -DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN}/cmake/Platform/Emscripten.cmake
  #       ../..

  # Toolchain MUST be defined in the call to CMake

  if(MSVC)
    message(
      FATAL_ERROR
        "Cannot use visual studio, use MinGW Makefiles generator on windows")
  endif()

  add_definitions(-sDISABLE_EXCEPTION_CATCHING=0)
  add_definitions(-DCOOLPROP_NO_INCBIN)
  # # If you want a monolithic file with no async memory loading, define EMSCRIPTEN_NO_MEMORY_INIT_FILE
  # if(EMSCRIPTEN_NO_MEMORY_INIT_FILE)
  #   set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 0")
  # else()
  #   set(EMSCRIPTEN_INIT_FLAG "--memory-init-file 1")
  # endif()

  set(CMAKE_EXE_LINKER_FLAGS
      "-lembind ${EMSCRIPTEN_INIT_FLAG} -s ASSERTIONS=1 -s DISABLE_EXCEPTION_CATCHING=0 -sALLOW_MEMORY_GROWTH=1 -s EXPORT_ES6=1 -s MODULARIZE=1"
  )
  set(CMAKE_BUILD_TYPE Release)

  list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp"
       "${CMAKE_CURRENT_SOURCE_DIR}/src/emscripten_interface.cxx")
  include_directories(${APP_INCLUDE_DIRS})
  add_executable(coolprop ${APP_SOURCES})
  add_dependencies(coolprop generate_headers)
  set_target_properties(coolprop PROPERTIES PREFIX "" SUFFIX .js)
  #install (TARGETS coolprop DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript)
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.js"
          DESTINATION Javascript)
  install(FILES "${CMAKE_CURRENT_BINARY_DIR}/coolprop.wasm"
          DESTINATION Javascript)
  #install (FILES "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt" DESTINATION ${CMAKE_INSTALL_PREFIX}/Javascript)
  install(
    FILES
      "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/wrappers/Javascript/index.html"
    DESTINATION Javascript)
endif()

if(COOLPROP_MATHEMATICA_MODULE)
  set(CMAKE_MODULE_PATH
      ${CMAKE_MODULE_PATH}
      "${FindMathematica_SOURCE_DIR}/CMake/Mathematica/"
  )
  find_package(Mathematica COMPONENTS WolframLibrary)
  message(
    STATUS
      "Mathematica_WolframLibrary_FOUND=${Mathematica_WolframLibrary_FOUND}")
  message(
    STATUS
      "Mathematica_WolframLibrary_INCLUDE_DIR=${Mathematica_WolframLibrary_INCLUDE_DIR}"
  )
  message(STATUS "Mathematica_USERBASE_DIR=${Mathematica_USERBASE_DIR}")

  # Build a fresh source list: core CoolProp sources WITHOUT CoolPropLib.cpp.
  set(MATHEMATICA_SOURCES ${APP_SOURCES})
  list(REMOVE_ITEM MATHEMATICA_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/CoolPropLib.cpp")
  list(
    APPEND MATHEMATICA_SOURCES
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/CoolPropMathematica.cpp")
  list(APPEND APP_INCLUDE_DIRS "${Mathematica_WolframLibrary_INCLUDE_DIR}")
  include_directories(${APP_INCLUDE_DIRS})
  
  # Embed Windows VERSIONINFO so the Mathematica CoolProp.dll Properties dialog shows
  # FileVersion/ProductVersion fields (#2391). The .rc is configured from
  # COOLPROP_VERSION_{MAJOR,MINOR,PATCH} above and added to the source list.
  # NOTE: Only if WIN32, where rc.exe (or MSYS2 windres) is available.
  if(MSVC OR MINGW)
    configure_file(
      "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/CoolProp.rc.in"
      "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.rc"
      @ONLY)
    list(APPEND MATHEMATICA_SOURCES "${CMAKE_CURRENT_BINARY_DIR}/CoolProp.rc")
  endif()
  # Source list complete, add all to library

  add_library(CoolProp SHARED ${MATHEMATICA_SOURCES})
  add_dependencies(CoolProp generate_headers)
  coolprop_hide_json_symbols(CoolProp)
  if(MSVC)
    _coolprop_set_msvc_runtime(CoolProp SHARED)
  endif()
  if(MINGW AND DEFINED ENV{MSYSTEM})
    # Add postfix for debugging (same as MSVC)
    set_property(TARGET ${app_name} PROPERTY PREFIX "")
    set_target_properties(${app_name} PROPERTIES IMPORT_PREFIX "" IMPORT_SUFFIX ".a")
    # COFF section-number overflow fix: HelmholtzEOSMixtureBackend.cpp emits
    # 33K+ COMDAT sections (one per template instantiation from Eigen/fmt/etc).
    # Standard COFF stores section numbers as a signed 16-bit integer (max 32767);
    # sections numbered above that get a negative SectionNumber in symbol-table
    # entries, making vtable symbols appear undefined to the linker.
    # -O1 inlines enough small template functions at call sites to keep the
    # per-TU section count below 32767 without requiring assembler bigobj support.
    # (Release builds already pass -O2/-O3 via CMAKE_BUILD_TYPE, so this only
    # matters for Debug/unoptimized builds.)
    if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "Debug")
      target_compile_options(${app_name} PRIVATE -O1)
    endif()
    # Statically link all MINGW libraries and make the file truly Windows portable
    # See (https://stackoverflow.com/questions/13768515/how-to-do-static-linking-of-libwinpthread-1-dll-in-mingw)
    # NOTE: use MSYS2/UCRT64 ntldd to check dependencies, MSYS2 & cygwin ldd will give false ucrt64 dependencies
    # Use -static-libgcc/-static-libstdc++ embed the GCC/C++ runtimes; -Bstatic/-Bdynamic scopes only winpthread
    target_link_options(${app_name} PRIVATE -static-libgcc -static-libstdc++)
    # Use -Bstatic/-Bdynamic scopes only winpthread so that Windows system DLLs (ucrt, kernel32, etc.) remain dynamically linked.
    target_link_libraries(${app_name} PRIVATE -Wl,-Bstatic -lwinpthread -Wl,-Bdynamic)
  endif()

  # Set the bitness
  if(NOT MSVC)
    if(NOT "${BITNESS}" STREQUAL "NATIVE")
      message(STATUS "Setting bitness flag ${COOLPROP_BITNESS_FLAG}")
      set_property(
        TARGET ${app_name}
        APPEND_STRING
        PROPERTY COMPILE_FLAGS " ${COOLPROP_BITNESS_FLAG}")
      set_property(
        TARGET ${app_name}
        APPEND_STRING
        PROPERTY LINK_FLAGS " ${COOLPROP_BITNESS_FLAG}")
    endif()
  endif()

  if(MSVC)
    add_custom_command(
      TARGET ${app_name}
      POST_BUILD
      COMMAND dumpbin /EXPORTS $<TARGET_FILE:CoolProp> >
              ${CMAKE_CURRENT_BINARY_DIR}/exports.txt)
  endif()

  install(FILES $<TARGET_FILE:CoolProp>
          DESTINATION Mathematica/${CMAKE_SYSTEM_NAME})
  install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/Mathematica/example.nb"
          DESTINATION Mathematica)
endif()

if(COOLPROP_SMATH_MODULE)
  if(COOLPROP_SMATH_WORK_INPLACE)
    set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
  else()
    set(COOLPROP_WORK_BASE_DIR ${CMAKE_CURRENT_BINARY_DIR})
  endif()
  set(COOLPROP_VERSION
      ${COOLPROP_VERSION_MAJOR}.${COOLPROP_VERSION_MINOR}.${COOLPROP_VERSION_PATCH}.0
  )
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs.template"
    "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs"
  )
  message(
    STATUS
      "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/Properties/AssemblyInfo.cs"
  )
  file(WRITE "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini"
       "${COOLPROP_VERSION}")
  message(
    STATUS "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/config.ini")
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat.template"
    "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat")
  message(
    STATUS
      "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/install.bat"
  )
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat.template"
    "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat")
  message(
    STATUS
      "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/build_zip.bat"
  )
  file(TO_NATIVE_PATH
       "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper"
       DOS_STYLE_SOURCE_DIR)
  file(TO_NATIVE_PATH
       "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper"
       DOS_STYLE_TARGET_DIR)
  configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj.template"
    "${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj"
  )
  message(
    STATUS
      "Generated ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj"
  )
  include_external_msproject(
    CoolPropWrapper
    ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj
    TYPE FAE04EC0-301F-11D3-BF4B-00C04F79EFBC
    PLATFORM AnyCPU)
  message(
    STATUS
      "C# project ${COOLPROP_WORK_BASE_DIR}/wrappers/SMath/coolprop_wrapper/coolprop_wrapper.csproj included"
  )

endif()

# Use like cmake ..\CoolProp.git -DCOOLPROP_MY_MAIN=dev/coverity/main.cxx
if(COOLPROP_MY_MAIN)
  set(_MY_MAIN_SOURCES ${APP_SOURCES})
  list(APPEND _MY_MAIN_SOURCES "${COOLPROP_MY_MAIN}")
  add_executable(Main ${_MY_MAIN_SOURCES})
  add_dependencies(Main generate_headers)
  if(UNIX)
    target_link_libraries(Main ${CMAKE_DL_LIBS})
  endif()
endif()

if(COOLPROP_MAIN_MODULE)
  # Allow you to independently add back the testing CPP files
  if(COOLPROP_TEST)
    list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/Tests.cpp")
    list(APPEND APP_SOURCES
         "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp")
  endif()
  list(APPEND APP_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cxx")
  add_executable(Main ${APP_SOURCES})
  add_dependencies(Main generate_headers)
  if(COOLPROP_TEST)
    set_target_properties(Main PROPERTIES COMPILE_FLAGS
                                          "${COMPILE_FLAGS} -DENABLE_CATCH")
  endif()

  if(UNIX)
    target_link_libraries(Main ${CMAKE_DL_LIBS})
  endif()
endif()

###      COOLPROP TESTING APP       ###
if(COOLPROP_CATCH_MODULE)

  enable_testing()

  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SVDComponents.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SBTLAdapter.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SVDSBTL.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-FactoryOptions.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SchemaValidation.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-PropsSIOptions.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SVDSBTLOptions.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SVDSBTLCriticalPatch.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-SVDSBTLFailMap.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-HS.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-HS-prototypes.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-DeltaOnly.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-HSU_D.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-PXcdj.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-PXFlash.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-CubicAlpha.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-CubicU.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-CubicEntropy.cpp")
  list(APPEND
       APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-CubicVolumeTranslation.cpp"
  )
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-NeonMelting.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-AirMelting.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-AirCritical.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-Michelsen.cpp"
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-FPUGuard.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-TermCacheProfile.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-JSONHelpers.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-CBOR.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-GERG.cpp")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/CoolProp-Tests-Expression.cpp")

  # CATCH TEST, compile everything with catch and set test entry point
  add_executable(CatchTestRunner ${APP_SOURCES})
  add_dependencies(CatchTestRunner generate_headers)

  target_link_libraries(CatchTestRunner PRIVATE Catch2::Catch2WithMain)
  target_compile_definitions(CatchTestRunner PRIVATE ENABLE_CATCH)
  target_compile_definitions(CatchTestRunner PRIVATE COOLPROP_ALL_FLUIDS_JSON_PATH="${CMAKE_CURRENT_SOURCE_DIR}/dev/all_fluids.json")
  target_compile_definitions(CatchTestRunner PRIVATE COOLPROP_NO_INCBIN) # Incbin is disabled for Catch2 because of a weird behavior where out-of-date zlib-compressed fluid information were being used.
  if(UNIX)
    target_link_libraries(CatchTestRunner PRIVATE ${CMAKE_DL_LIBS})
  endif()
  target_include_directories(CatchTestRunner PRIVATE "${multicomplex_SOURCE_DIR}/multicomplex/include")

  include(CTest)
  include(${Catch2_SOURCE_DIR}/extras/Catch.cmake)
  
  if (NOT CMAKE_GENERATOR STREQUAL Xcode)
    # Test discovery doesn't work in Xcode, due to a signing bug in Xcode which causes disovery to fail: https://github.com/catchorg/Catch2/issues/2411
    catch_discover_tests(CatchTestRunner DISCOVERY_MODE PRE_TEST)
  endif()

  if(COOLPROP_LAZY_LOAD_SUPERANCILLARIES)
    target_compile_definitions(CatchTestRunner PRIVATE LAZY_LOAD_SUPERANCILLARIES)
  else()
    # lazy load superancillaries by default in debug mode
    target_compile_definitions(CatchTestRunner PUBLIC $<$<CONFIG:Debug>:LAZY_LOAD_SUPERANCILLARIES>)
  endif()
endif()

if(COOLPROP_CPP_EXAMPLE_TEST)
  # C++ Documentation Test
  add_executable(docuTest.exe "Web/examples/C++/Example.cpp")
  _coolprop_set_canonical_msvc_runtime(docuTest.exe)
  add_dependencies(docuTest.exe ${app_name})
  target_link_libraries(docuTest.exe ${app_name})
  if(UNIX)
    target_link_libraries(docuTest.exe ${CMAKE_DL_LIBS})
  endif()
  add_test(DocumentationTest docuTest.exe)
endif()

if(COOLPROP_SVD_E2E)
  # Standalone Phase 2a validation tool.  Builds a self-contained
  # executable that compiles every CoolProp source plus the e2e harness
  # — same pattern as COOLPROP_MAIN_MODULE / CatchTestRunner.  Run with
  # ./SVDSBTL_E2E [csv_dir].
  #
  # Filter any main() implementation out of APP_SOURCES so co-enabling
  # COOLPROP_MY_MAIN / COOLPROP_MAIN_MODULE doesn't trigger a duplicate-
  # main link error when this target is also on.
  set(SVDSBTL_E2E_SOURCES ${APP_SOURCES})
  list(REMOVE_ITEM SVDSBTL_E2E_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cxx")
  add_executable(SVDSBTL_E2E
                 ${SVDSBTL_E2E_SOURCES}
                 "${CMAKE_CURRENT_SOURCE_DIR}/dev/svd_sbtl_e2e.cpp")
  add_dependencies(SVDSBTL_E2E generate_headers)
  if(UNIX)
    target_link_libraries(SVDSBTL_E2E ${CMAKE_DL_LIBS})
  endif()
endif()

if(COOLPROP_BUILD_SVD_TABLES)
  # Phase 2b bulk-table builder.  Writes one .svd.bin.z per fluid per
  # input pair under ~/.CoolProp/SVDTables/.  Same pattern as
  # COOLPROP_MAIN_MODULE / CatchTestRunner: link the whole project
  # statically into the standalone executable.
  add_executable(build_svd_tables
                 ${APP_SOURCES}
                 "${CMAKE_CURRENT_SOURCE_DIR}/dev/build_svd_tables.cpp")
  add_dependencies(build_svd_tables generate_headers)
  if(UNIX)
    target_link_libraries(build_svd_tables ${CMAKE_DL_LIBS})
  endif()
endif()

if(COOLPROP_BUILD_SVDSBTL_BENCH)
  # Phase 2c state-point benchmark.  Walks an (h, p) grid and writes a
  # CSV with per-point rel-err vs HEOS + ns/call for both backends.
  add_executable(bench_svdsbtl_ph
                 ${APP_SOURCES}
                 "${CMAKE_CURRENT_SOURCE_DIR}/dev/bench_svdsbtl_ph.cpp")
  add_dependencies(bench_svdsbtl_ph generate_headers)
  if(UNIX)
    target_link_libraries(bench_svdsbtl_ph ${CMAKE_DL_LIBS})
  endif()
endif()

if(COOLPROP_BUILD_SVDSBTL_PROFILE)
  # Phase 2c per-stage profiler.  Picks one representative state and
  # decomposes the SVDSBTL per-call cost into stages.
  add_executable(profile_svdsbtl
                 ${APP_SOURCES}
                 "${CMAKE_CURRENT_SOURCE_DIR}/dev/profile_svdsbtl.cpp")
  add_dependencies(profile_svdsbtl generate_headers)
  if(UNIX)
    target_link_libraries(profile_svdsbtl ${CMAKE_DL_LIBS})
  endif()
endif()

if(COOLPROP_SNIPPETS)
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/${COOLPROP_LIBRARY_SOURCE}")
  # Make the static library with which the snippets will be linked
  add_library(${app_name} STATIC ${APP_SOURCES})
  _coolprop_set_msvc_runtime("${app_name}" STATIC)
  add_dependencies(${app_name} generate_headers)
  set_property(
    TARGET ${app_name}
    APPEND_STRING
    PROPERTY COMPILE_FLAGS " -DEXTERNC")

  # Collect all the snippets
  file(GLOB_RECURSE snippets
       "${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/*.cxx")

  message(STATUS "snippets found = ${snippets}")
  foreach(snippet ${snippets})

    get_filename_component(snippet_name ${snippet} NAME)
    get_filename_component(snippet_exe ${snippet} NAME_WE)
    message(STATUS "snippet_name = ${snippet_name}")

    add_executable(${snippet_exe} ${snippet})
    _coolprop_set_msvc_runtime("${snippet_exe}" STATIC)
    add_dependencies(${snippet_exe} CoolProp)
    target_link_libraries(${snippet_exe} CoolProp)
    if(UNIX)
      target_link_libraries(${snippet_exe} ${CMAKE_DL_LIBS})
    endif()

    if(MSVC)
      set_target_properties(
        ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
                                  ${CMAKE_CURRENT_BINARY_DIR}/bin)
      set_target_properties(
        ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG
                                  ${CMAKE_CURRENT_BINARY_DIR}/bin)
      set_target_properties(
        ${snippet_exe} PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE
                                  ${CMAKE_CURRENT_BINARY_DIR}/bin)
      # etc for the other available configuration types (MinSizeRel, RelWithDebInfo)
      set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/bin")
    else()
      set(BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}")
    endif()

    set_property(
      TARGET ${snippet_exe}
      APPEND_STRING
      PROPERTY COMPILE_FLAGS " -DEXTERNC")

    # Run it and save the output to a file with .output appended
    add_custom_command(
      TARGET ${snippet_exe}
      POST_BUILD
      COMMAND
        ${BIN_PATH}/${snippet_exe} >
        ${CMAKE_CURRENT_SOURCE_DIR}/Web/coolprop/snippets/${snippet_name}.output
    )

  endforeach()

endif()

if(COOLPROP_CLANG_ADDRESS_SANITIZER)

  set(CMAKE_CXX_FLAGS "-fsanitize=address -g")
  list(APPEND APP_SOURCES
       "${CMAKE_CURRENT_SOURCE_DIR}/src/Tests/catch_always_return_success.cxx")
  # CATCH TEST, compile everything with catch and set test entry point
  add_executable(CatchTestRunner ${APP_SOURCES})
  add_dependencies(CatchTestRunner generate_headers)
  set_target_properties(
    CatchTestRunner PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -DENABLE_CATCH")
  set(CMAKE_CXX_FLAGS "-O1")
  set(CMAKE_EXE_LINKER_FLAGS
      "-fsanitize=address -fno-omit-frame-pointer -lstdc++")
  if(UNIX)
    target_link_libraries(CatchTestRunner ${CMAKE_DL_LIBS})
  endif()
  add_custom_command(
    TARGET CatchTestRunner
    POST_BUILD
    COMMAND ${CMAKE_CURRENT_BINARY_DIR}/CatchTestRunner)
endif()

if(COOLPROP_PROFILE)
  if(CMAKE_COMPILER_IS_GNUCXX)
    set(CMAKE_CXX_FLAGS "-g -O2")
    set(CMAKE_C_FLAGS "-g -O2")
  endif()
endif()

if(COOLPROP_COVERAGE)
  if(CMAKE_COMPILER_IS_GNUCXX)
    # See also http://stackoverflow.com/a/16536401 (detailed guide on using gcov with cmake)
    include(CodeCoverage)
    set(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
    set(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
    setup_target_for_coverage(CoolProp_coverage Main coverage)
  endif()
endif()

# TODO: check relevance of http://www.cmake.org/Wiki/BuildingWinDLL

#include_directories("${CMAKE_CURRENT_SOURCE_DIR}/CoolProp")
#FILE(GLOB coolprop_files "${CMAKE_CURRENT_SOURCE_DIR}/CoolProp/*.cpp")
#add_library(coolprop STATIC ${coolprop_files})

# include-what-you-use wiring (CoolProp-2uw.11). Placed at the bottom so it
# fires after every target-creation path: Main is created either inside
# `if(COOLPROP_MY_MAIN)` (used by CodeQL/Coverity/IWYU CI) or inside
# `if(COOLPROP_MAIN_MODULE)`; CatchTestRunner inside `if(COOLPROP_CATCH_MODULE)`.
# An earlier version of this wiring lived inside one of those conditionals
# and silently no-op'd for the IWYU CI path.
if(COOLPROP_IWYU)
  find_program(iwyu_path NAMES include-what-you-use iwyu)
  if(NOT iwyu_path)
    message(FATAL_ERROR "Could not find the program include-what-you-use")
  endif()
  foreach(_iwyu_target Main CatchTestRunner)
    if(TARGET ${_iwyu_target})
      set_property(TARGET ${_iwyu_target} PROPERTY CXX_INCLUDE_WHAT_YOU_USE
                                                   ${iwyu_path})
    endif()
  endforeach()
endif()

# clang-format developer targets (CoolProp-2uw.2)
# Whole-tree mode over src/ + include/, mirroring dev/ci/clang-format.sh's
# fallback path. Re-run cmake after adding new files for them to be picked up.
# Excludes:
#   - include/*_JSON.h, include/cubic_fluids_schema_JSON.h — auto-generated from
#     dev/fluids/ JSON, contain raw-string literals up to 60 MB; reformatting
#     them is wasteful and will be overwritten on the next regeneration.
#   - include/gitrevision.h — auto-generated.
#   - include/miniz.h — vendored copy of upstream miniz; format upstream, not us.
find_program(CLANG_FORMAT_EXE NAMES clang-format-18 clang-format)
if(CLANG_FORMAT_EXE)
  file(GLOB_RECURSE COOLPROP_FORMAT_FILES
       LIST_DIRECTORIES false
       "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c"
       "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp"
       "${CMAKE_CURRENT_SOURCE_DIR}/src/*.h"
       "${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp"
       "${CMAKE_CURRENT_SOURCE_DIR}/include/*.c"
       "${CMAKE_CURRENT_SOURCE_DIR}/include/*.cpp"
       "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h"
       "${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp")
  list(FILTER COOLPROP_FORMAT_FILES EXCLUDE REGEX
       "/include/(.*_JSON.*|gitrevision|miniz)\\.h$")
  add_custom_target(format
                    COMMAND ${CLANG_FORMAT_EXE} -style=file -fallback-style=none
                            -i ${COOLPROP_FORMAT_FILES}
                    COMMENT "clang-format -i over src/ and include/ (${CLANG_FORMAT_EXE})"
                    VERBATIM)
  add_custom_target(format-check
                    COMMAND ${CLANG_FORMAT_EXE} -style=file -fallback-style=none
                            --dry-run --Werror ${COOLPROP_FORMAT_FILES}
                    COMMENT "clang-format dry-run check over src/ and include/ (${CLANG_FORMAT_EXE})"
                    VERBATIM)
else()
  message(STATUS "clang-format not found; 'format' and 'format-check' targets disabled")
endif()
