cmake_minimum_required(VERSION 3.2.2)
PROJECT (H4H5 C CXX)

#-----------------------------------------------------------------------------
# Instructions for use : Normal Build
#
# For standard build of H4H5 libraries,tests and tools.
# Run cmake using the H4H5 source tree to generate a build tree.
# Enable/Disable options according to requirements and
# set CMAKE_INSTALL_PREFIX to the required install path.
# Make install can be used to install all components for system-wide use.
#
#-----------------------------------------------------------------------------
# Instructions for use : Sub-Project Build
#
# To include H4H5 as a sub-project within another project.
# Set H4H5_EXTERNALLY_CONFIGURED to 1 in the parent project and
# supply values for the following variables...
#
# H4H5_EXPORTED_TARGETS :
#   Set this to the name of the targets variable which controls exports
#   If unset (because parent project does not support/use the
#   install (EXPORT target...) syntax), then targets are not configured
#   for export during install.
#
# H4H5_LIB_DEPENDENCIES :
#   If the build of H4H5 libs is being customized, then rules for the
#   dependencies of the H4H5 libs may be 'incomplete', add additional
#   dependencies to this variable so that external projects pick them up
#
# H4H5_EXTERNAL_LIB_PREFIX :
#   If the pa5rent project needs to install hdf libraries, but avoid
#   name conflicts with system versions, then a prefix may be added
#   to ensure that the correct versions configured are used.
#
# Consider this example, it builds its own zlib
# library and tells H4H5 to add it as a dependency - this ensures that
# any project making use of this build of H4H5 will use the correct zlib
#
#   # Tell H4H5 that we are manually overriding certain settings
#   set (H4H5_EXTERNALLY_CONFIGURED 1)
#   # Avoid duplicating names of installed libraries
#   set (H4H5_EXTERNAL_LIB_PREFIX "prj")
#   # Targets linking to the H4H5 libs need to know their names
#   # if they are changed in the sub project, they should be here too
#   set (H4H5_LIB_NAME "prjH4H5")
#   set (H4H5_MF_LIB_NAME "prjH4H5_mf")
#   set (H4H5_LIBRARY "${H4H5_LIB_NAME};${H4H5_MF_LIB_NAME}")
#   # Export configuration to this export variable
#   set (H4H5_EXPORTED_TARGETS "project-targets")
#
#   # Setup all necessary overrides for zlib so that H4H5 uses our
#   # internally compiled zlib rather than any other version
#   if (HDF_ENABLE_Z_LIB_SUPPORT)
#    # We must tell the main H4H5 library that it depends on our zlib
#     set (H4H5_LIB_DEPENDENCIES prjzlib)
#     # Override the zlib header file
#     if (PRJ_USE_SYSTEM_ZLIB)
#       set (H4_ZLIB_HEADER "zlib.h")
#     else (PRJ_USE_SYSTEM_ZLIB)
#      set (H4_ZLIB_HEADER "prj_zlib.h")
#       # Set vars that FindZlib would have set if used in sub project
#       set (ZLIB_INCLUDE_DIRS "${PRJ_ZLIB_INCLUDE_DIRS}")
#       set (ZLIB_LIBRARIES prjzlib)
#     endif (PRJ_USE_SYSTEM_ZLIB)
#  endif (HDF_ENABLE_Z_LIB_SUPPORT)
#
#   # Add the sub project
#   add_subdirectory (Utilities/H4H5-1.2)
#   # Add the H4H5 dirs to our include path
#   set (H4H5_INCLUDE_DIR
#       ${PROJECT_SOURCE_DIR}/Utilities/H4H5-1.2/src
#       ${PROJECT_BINARY_DIR}/Utilities/H4H5-1.2
#   )
#
#-----------------------------------------------------------------------------

#-----------------------------------------------------------------------------
# Allow Visual Studio solution directories
#-----------------------------------------------------------------------------
# Provide a way for Visual Studio Express users to turn OFF the new FOLDER
# organization feature. Default to ON for non-Express users. Express users must
# explicitly turn off this option to build HDF5 in the Express IDE...
#
option (H4H5_USE_FOLDERS "Enable folder grouping of projects in IDEs." ON)
mark_as_advanced (H4H5_USE_FOLDERS)
if (H4H5_USE_FOLDERS)
  set_property (GLOBAL PROPERTY USE_FOLDERS ON)
endif (H4H5_USE_FOLDERS)
option (H4H5_NO_PACKAGES "CPACK - Disable packaging" OFF)
mark_as_advanced (H4H5_NO_PACKAGES)

#-----------------------------------------------------------------------------
# Set the core names of all the libraries
#-----------------------------------------------------------------------------
set (H4H5_LIB_CORENAME              "H4H5")
set (H4H5_SRC_LIB_CORENAME          "h4h5")

#-----------------------------------------------------------------------------
# Set the true names of all the libraries if customized by external project
#-----------------------------------------------------------------------------
set (H4H5_LIB_NAME              "${H4H5_EXTERNAL_LIB_PREFIX}${H4H5_LIB_CORENAME}")
set (H4H5_SRC_LIB_NAME          "${H4H5_EXTERNAL_LIB_PREFIX}${H4H5_SRC_LIB_CORENAME}")

#-----------------------------------------------------------------------------
# Set the target names of all the libraries
#-----------------------------------------------------------------------------
set (H4H5_LIB_TARGET              ${H4H5_LIB_CORENAME})
set (H4H5_SRC_LIB_TARGET          ${H4H5_SRC_LIB_CORENAME}-static)
set (H4H5_SRC_LIBSH_TARGET        ${H4H5_SRC_LIB_CORENAME}-shared)

#-----------------------------------------------------------------------------
# Define some CMake variables for use later in the project
#-----------------------------------------------------------------------------
set (HDF_RESOURCES_DIR        ${H4H5_SOURCE_DIR}/config/cmake)
set (HDF_RESOURCES_EXT_DIR    ${H4H5_SOURCE_DIR}/config/cmake_ext_mod)
set (H4H5_SRC_DIR             ${H4H5_SOURCE_DIR}/lib/src)
set (H4H5_TEST_SRC_DIR        ${H4H5_SOURCE_DIR}/lib/test)
set (H4H5_UTILS_SRC_DIR       ${H4H5_SOURCE_DIR}/utils)

if (NOT H4H5_INSTALL_BIN_DIR)
  set (H4H5_INSTALL_BIN_DIR bin)
endif ()
if (NOT H4H5_INSTALL_LIB_DIR)
  set (H4H5_INSTALL_LIB_DIR lib)
endif ()
if (NOT H4H5_INSTALL_INCLUDE_DIR)
  set (H4H5_INSTALL_INCLUDE_DIR include)
endif ()
if (NOT H4H5_INSTALL_DATA_DIR)
  if (NOT WIN32)
    set (H4H5_INSTALL_DATA_DIR share)
    set (H4H5_INSTALL_CMAKE_DIR share/cmake)
  else ()
    set (H4H5_INSTALL_DATA_DIR ".")
    set (H4H5_INSTALL_CMAKE_DIR cmake)
  endif ()
endif ()

#-----------------------------------------------------------------------------
# parse the full version number from ?.h and include in H4H5_VERS_INFO
#-----------------------------------------------------------------------------
file (READ ${H4H5_SRC_DIR}/h4toh5.h _h4toh5_h_contents)
string (REGEX REPLACE ".*#define[ \t]+H4TOH5_LIBVER_MAJOR[ \t]+([0-9]*).*$"
    "\\1" H4H5_VERS_MAJOR ${_h4toh5_h_contents})
string (REGEX REPLACE ".*#define[ \t]+H4TOH5_LIBVER_MINOR[ \t]+([0-9]*).*$"
    "\\1" H4H5_VERS_MINOR ${_h4toh5_h_contents})
string (REGEX REPLACE ".*#define[ \t]+H4TOH5_LIBVER_RELEASE[ \t]+([0-9]*).*$"
    "\\1" H4H5_VERS_RELEASE ${_h4toh5_h_contents})
message (STATUS "VERSION: ${H4H5_VERSION}")

#set (H4H5_VERS_MAJOR 2)
#set (H4H5_VERS_MINOR 2)
#set (H4H5_VERS_RELEASE 3)

set (H4H5_SOVERS_MAJOR 2)
set (H4H5_SOVERS_MINOR 2)
set (H4H5_SOVERS_INTERFACE 3)
set (H4H5_SOVERS_RELEASE 0)
math (EXPR H4H5_SOVERS_MAJOR ${H4H5_SOVERS_INTERFACE}-${H4H5_SOVERS_RELEASE})

#-----------------------------------------------------------------------------
# Basic H4H5 stuff here
#-----------------------------------------------------------------------------
set (H4H5_PACKAGE "h4h5")
set (H4H5_PACKAGE_NAME "H4H5")
set (H4H5_PACKAGE_VERSION "${H4H5_VERS_MAJOR}.${H4H5_VERS_MINOR}.${H4H5_VERS_RELEASE}")
set (H4H5_PACKAGE_VERSION_MAJOR "${H4H5_VERS_MAJOR}.${H4H5_VERS_MINOR}")
set (H4H5_PACKAGE_VERSION_MINOR "${H4H5_VERS_RELEASE}")
if (NOT "${H4H5_VERS_SUBRELEASE}" STREQUAL "")
  set (H4H5_PACKAGE_VERSION_STRING "${H4H5_PACKAGE_VERSION}-${H4H5_VERS_SUBRELEASE}")
else (NOT "${H4H5_VERS_SUBRELEASE}" STREQUAL "")
  set (H4H5_PACKAGE_VERSION_STRING "${H4H5_PACKAGE_VERSION}")
endif (NOT "${H4H5_VERS_SUBRELEASE}" STREQUAL "")
set (H4H5_PACKAGE_STRING "${H4H5_PACKAGE_NAME} ${H4H5_PACKAGE_VERSION_STRING}")
set (H4H5_PACKAGE_TARNAME "${H4H5_PACKAGE}${H4H5_PACKAGE_EXT}")
set (H4H5_PACKAGE_URL "https://support.hdfgroup.org/products/")
set (H4H5_PACKAGE_BUGREPORT "help@hdfgroup.org")

#-----------------------------------------------------------------------------
# Include some macros for reusable code
#-----------------------------------------------------------------------------
include (${HDF_RESOURCES_EXT_DIR}/HDFMacros.cmake)
include (${HDF_RESOURCES_EXT_DIR}/HDFLibMacros.cmake)
include (${HDF_RESOURCES_DIR}/H4H5Macros.cmake)
include (${HDF_RESOURCES_DIR}/HDF45Macros.cmake)

#-----------------------------------------------------------------------------
# Setup output Directories
#-----------------------------------------------------------------------------
if (NOT H4H5_EXTERNALLY_CONFIGURED)
  set (CMAKE_RUNTIME_OUTPUT_DIRECTORY
      ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all Executables."
  )
  set (CMAKE_LIBRARY_OUTPUT_DIRECTORY
      ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all Libraries"
  )
  set (CMAKE_ARCHIVE_OUTPUT_DIRECTORY
      ${PROJECT_BINARY_DIR}/bin CACHE PATH "Single Directory for all static libraries."
  )
else ()
  # if we are externally configured, but the project uses old cmake scripts
  # this may not be set and utilities like Hdetect will fail
  if (NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
    set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH})
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Targets built within this project are exported at Install time for use
# by other projects using FindH4H5.
#-----------------------------------------------------------------------------
if (NOT H4H5_EXPORTED_TARGETS)
  set (H4H5_EXPORTED_TARGETS "h4h5-targets")
endif ()

#-----------------------------------------------------------------------------
# To include a library in the list exported by the project AT BUILD TIME,
# add it to this variable. This is NOT used by Make Install, but for projects
# which include H4H5 as a sub-project within their build tree
#-----------------------------------------------------------------------------
set_global_variable (H4H5_LIBRARIES_TO_EXPORT "")
set_global_variable (H4H5_APPS_TO_EXPORT "")
set (EXTERNAL_HEADER_LIST "")
set (EXTERNAL_LIBRARY_LIST "")
set (EXTERNAL_LIBRARYDLL_LIST "")

#-----------------------------------------------------------------------------
# Run all the CMake configuration tests for our build environment
#-----------------------------------------------------------------------------
include (${HDF_RESOURCES_DIR}/ConfigureChecks.cmake)

set (CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

#-----------------------------------------------------------------------------
# Option to Build Shared/Static libs, default is static
#-----------------------------------------------------------------------------
option (BUILD_SHARED_LIBS "Build Shared Libraries" OFF)
set (LIB_TYPE STATIC)
if (BUILD_SHARED_LIBS)
  set (LIB_TYPE SHARED)
  set (H4H5_BUILT_AS_DYNAMIC_LIB 1)
else ()
  set (H4H5_BUILT_AS_STATIC_LIB 1)
endif ()
set (CMAKE_POSITION_INDEPENDENT_CODE ON)

if (NOT USE_SHARED_LIBS)
  set (H4H5_USE_STATIC_LIBRARIES 1)
endif ()

add_definitions (-DBIG_LONGS -DSWAP)
add_definitions (-DHAVE_CONFIG_H)

#-----------------------------------------------------------------------------
# Option to use code coverage
#-----------------------------------------------------------------------------
option (HDF_ENABLE_COVERAGE "Enable code coverage for Libraries and Programs" OFF)
if (HDF_ENABLE_COVERAGE)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
    set (LDFLAGS "${LDFLAGS} -fprofile-arcs -ftest-coverage")
endif ()

#-----------------------------------------------------------------------------
# Include user macros
#-----------------------------------------------------------------------------
include (UserMacros.cmake)

#-----------------------------------------------------------------------------
# Include the main src and config directories
#-----------------------------------------------------------------------------
set (H4H5_INCLUDE_DIRECTORIES
    ${H4H5_SRC_DIR}
    ${H4H5_BINARY_DIR}
    ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
)
INCLUDE_DIRECTORIES (${H4H5_INCLUDE_DIRECTORIES})

#-----------------------------------------------------------------------------
# When building utility executables that generate other (source) files :
# we make use of the following variables defined in the root CMakeLists.
# Certain systems may add /Debug or /Release to output paths
# and we need to call the executable from inside the CMake configuration
#-----------------------------------------------------------------------------
set (EXE_EXT "")
if (WIN32)
  set (EXE_EXT ".exe")
  if (NOT CYGWIN)
    add_definitions (-D_BIND_TO_CURRENT_VCLIBS_VERSION=1)
    add_definitions (-D_CRT_SECURE_NO_WARNINGS)
    add_definitions (-D_CONSOLE)
  endif ()
endif ()

if (MSVC)
  set (CMAKE_MFC_FLAG 0)
  set (WIN_COMPILE_FLAGS "")
  set (WIN_LINK_FLAGS "")
endif ()

set (MAKE_SYSTEM)
if (CMAKE_BUILD_TOOL MATCHES "make")
  set (MAKE_SYSTEM 1)
endif ()

set (CFG_INIT "/${CMAKE_CFG_INTDIR}")
if (MAKE_SYSTEM)
  set (CFG_INIT "")
endif ()

#-----------------------------------------------------------------------------
# Add some definitions for Debug Builds
#-----------------------------------------------------------------------------
if (CMAKE_BUILD_TYPE MATCHES Debug)
  #-- NMake Makefiles will overwhelm the console with warnings if -Wall is used.
  if (NOT WIN32)
    add_definitions (-Wall)
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Compiler specific flags : Shouldn't there be compiler tests for these
#-----------------------------------------------------------------------------
if (CMAKE_COMPILER_IS_GNUCC)
  if (CMAKE_BUILD_TYPE MATCHES Debug)
    set (CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS} -std=c99 -finline-functions -fno-common")
  else ()
    set (CMAKE_C_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_C_FLAGS} -std=c99 -fomit-frame-pointer -finline-functions -fno-common")
  endif ()
endif ()
if (CMAKE_COMPILER_IS_GNUCXX)
  if (CMAKE_BUILD_TYPE MATCHES Debug)
    set (CMAKE_CXX_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_CXX_FLAGS} -finline-functions -fno-common")
  else ()
    set (CMAKE_CXX_FLAGS "${CMAKE_ANSI_CFLAGS} ${CMAKE_CXX_FLAGS} -fomit-frame-pointer -finline-functions -fno-common")
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Option to allow the user to disable compiler warnings
#-----------------------------------------------------------------------------
option (HDF_DISABLE_COMPILER_WARNINGS "Disable compiler warnings" OFF)
if (HDF_DISABLE_COMPILER_WARNINGS)
  # MSVC uses /w to suppress warnings.  It also complains if another
  # warning level is given, so remove it.
  if (MSVC)
    set (HDF_WARNINGS_BLOCKED 1)
    string (REGEX REPLACE "(^| )([/-])W[0-9]( |$)" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /w")
    string (REGEX REPLACE "(^| )([/-])W[0-9]( |$)" " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /w")
  endif ()
  if (WIN32)
    add_definitions (-D_CRT_SECURE_NO_WARNINGS)
  endif ()
  # Borland uses -w- to suppress warnings.
  if (BORLAND)
    set (HDF_WARNINGS_BLOCKED 1)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w-")
  endif ()

  # Most compilers use -w to suppress warnings.
  if (NOT HDF_WARNINGS_BLOCKED)
    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w")
    set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w")
  endif ()
endif ()

#-----------------------------------------------------------------------------
# This is in here to help some of the GCC based IDES like Eclipse
# and code blocks parse the compiler errors and warnings better.
#-----------------------------------------------------------------------------
if (CMAKE_COMPILER_IS_GNUCC)
  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fmessage-length=0")
endif ()
if (CMAKE_COMPILER_IS_GNUCXX)
  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fmessage-length=0")
endif ()

#-----------------------------------------------------------------------------
# Option to Enable MPI Parallel
#-----------------------------------------------------------------------------
set (CMAKE_MODULE_PATH ${HDF_RESOURCES_DIR} ${HDF_RESOURCES_EXT_DIR} ${CMAKE_MODULE_PATH})
option (HDF_ENABLE_PARALLEL "Enable parallel build (requires MPI)" OFF)
if (HDF_ENABLE_PARALLEL)
  include (FindMPI)
  INCLUDE_DIRECTORIES (${MPI_C_INCLUDE_PATH})
  if (MPI_C_FOUND)
    set (H4H5_HAVE_PARALLEL 1)
    # MPI checks, only do these if MPI_C_FOUND is true, otherwise they always fail
    # and once set, they are cached as false and not regenerated
    set (CMAKE_REQUIRED_LIBRARIES "${MPI_C_LIBRARIES}" )
    # Used by Fortran + MPI
    CHECK_SYMBOL_EXISTS (MPI_Comm_c2f "${MPI_C_INCLUDE_PATH}/mpi.h"  H4H5_HAVE_MPI_MULTI_LANG_Comm)
    CHECK_SYMBOL_EXISTS (MPI_Info_c2f "${MPI_C_INCLUDE_PATH}/mpi.h"  H4H5_HAVE_MPI_MULTI_LANG_Info)
  else ()
    message (STATUS "Parallel libraries not found")
  endif ()
endif ()

# Parallel IO usage requires MPI to be Linked and Included
if (H4H5_HAVE_PARALLEL)
  set (LINK_LIBS ${LINK_LIBS} ${MPI_C_LIBRARIES})
  if (MPI_C_LINK_FLAGS)
    set (CMAKE_EXE_LINKER_FLAGS "${MPI_C_LINK_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}")
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Option to use 1.6.x API
#-----------------------------------------------------------------------------
option (HDF5_USE_16_API_DEFAULT "Use the HDF5 1.6.x API by default" ON)
set (H5_USE_16_API_DEFAULT 0)
if (HDF5_USE_16_API_DEFAULT)
  set (H5_USE_16_API_DEFAULT 1)
endif ()

#-----------------------------------------------------------------------------
# Include user macros
#-----------------------------------------------------------------------------
include (UserMacros.cmake)

#-----------------------------------------------------------------------------
# Include filter (zlib, szip, etc.) and HDF-HDF5 macros
#-----------------------------------------------------------------------------
include (CMakeFilters.cmake)

#-----------------------------------------------------------------------------
# Option for external libraries on windows
#-----------------------------------------------------------------------------
option (HDF_PACKAGE_EXTLIBS "CPACK - include external libraries" OFF)
if (HDF_PACKAGE_EXTLIBS)
  if (HDF4_FOUND)
    PACKAGE_HDF4_LIBRARY (${HDF_ALLOW_EXTERNAL_SUPPORT} ${LIB_TYPE})
  endif ()

  if (HDF5_FOUND)
    PACKAGE_HDF5_LIBRARY (${HDF_ALLOW_EXTERNAL_SUPPORT} ${LIB_TYPE})
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Dashboard and Testing Settings
#-----------------------------------------------------------------------------
option (BUILD_TESTING "Build H4H5 Unit Testing" OFF)
if (BUILD_TESTING)
  set (DART_TESTING_TIMEOUT 1200
      CACHE INTEGER
      "Timeout in seconds for each test (default 1200=20minutes)"
  )
  enable_testing ()
  include (CTest)
  include (${H4H5_SOURCE_DIR}/CTestConfig.cmake)
  configure_file (${HDF_RESOURCES_DIR}/CTestCustom.cmake ${H4H5_BINARY_DIR}/CTestCustom.ctest @ONLY)
endif ()

#-----------------------------------------------------------------------------
# Add the H4H5 Library Target to the build
#-----------------------------------------------------------------------------
add_subdirectory (${H4H5_SOURCE_DIR}/lib ${PROJECT_BINARY_DIR}/lib)

if (HDF_ALLOW_EXTERNAL_SUPPORT MATCHES "GIT" OR HDF_ALLOW_EXTERNAL_SUPPORT MATCHES "TGZ")
  if (HDF4_FOUND AND HDF4_USE_EXTERNAL)
    add_dependencies (${H4H5_SRC_LIB_TARGET} HDF4)
  endif ()
  if (HDF5_FOUND AND HDF5_USE_EXTERNAL)
    add_dependencies (${H4H5_SRC_LIB_TARGET} HDF5)
  endif ()
endif ()

#-----------------------------------------------------------------------------
# Option to build H4H5 Utilities
#-----------------------------------------------------------------------------
option (HDF_BUILD_UTILS  "Build H4H5 Utilities" OFF)
if (HDF_BUILD_UTILS)
  add_subdirectory (${H4H5_SOURCE_DIR}/utils ${PROJECT_BINARY_DIR}/utils)
endif ()

include (CMakeInstallation.cmake)
