cmake_minimum_required(VERSION 3.11.2)

project(cmb-superbuild)

if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin" AND
    NOT CMAKE_HOST_SYSTEM_VERSION VERSION_LESS "20.2.0" # macOS 11
    AND CMAKE_VERSION VERSION_LESS "3.19.0")
  message(AUTHOR_WARNING
    "Note that macOS 11 has changes which requires CMake 3.19.0 to "
    "successfully package the applications.")
endif ()

list(INSERT CMAKE_MODULE_PATH 0
  "${CMAKE_CURRENT_LIST_DIR}/cmake")

macro(set_cmb_python_modules)
  set(cmb_python_modules
    smtk
    paraview
    cinema_python
    pygments
    six
    vtk
    vtkmodules)

  if (matplotlib_enabled)
    list(APPEND cmb_python_modules
      matplotlib
      PIL)
  endif ()

  if (numpy_enabled)
    list(APPEND cmb_python_modules
      numpy)
  endif ()

  if (pythongirderclient_enabled)
    list(APPEND cmb_python_modules
      diskcache
      requests
      certifi
      charset_normalizer
      idna
      urllib3
      PySocks
      requests_toolbelt
      girder_client)
  endif ()

  if (pythondocker_enabled)
    list(APPEND cmb_python_modules
      docker
      websocket
      requests
      certifi
      cffi
      charset_normalizer
      idna
      urllib3
      PySocks
      pycparser
      pyparsing
      )
  endif ()

  get_property(has_extra_python_modules GLOBAL PROPERTY cmb_extra_python_modules SET)
  if(has_extra_python_modules)
    get_property(extra_python_modules GLOBAL PROPERTY cmb_extra_python_modules)
    list(APPEND cmb_python_modules
      ${extra_python_modules})
  endif()
endmacro()

macro (superbuild_setup_variables)
  include(SuperbuildVersionMacros)

  superbuild_configure_project_version(cmb)
  superbuild_configure_project_version(smtk)
  superbuild_configure_project_version(paraview "for-v6.3.0" "master" "for-slac")

  superbuild_set_version_variables(vtk "9.0.0" "vtk-version.cmake")
  set(vtk_version "${vtk_version_major}.${vtk_version_minor}")
endmacro ()

function (superbuild_find_projects var)
  include(CMBSuperbuildMacros)

  set(projects
    boost
    bzip2
    cmb
    cmbusersguide
    cmbworkflows
    cumulus
    cxx11
    cxx14
    eigen
    freetype
    ftgl
    gdal
    hdf5cpp
    hdf5
    hdf5cpp
    itk
    itkvtkglue
    las
    libarchive
    libjpegturbo
    matplotlib
    moab
    netcdf
    netgen
    nlohmannjson
    numpy
    occt
    opencascadesession
    opencv
    paraview
    pegtl
    png
    protobuf
    pybind11
    python3
    pythonbeniget
    pythoncertifi
    pythoncharsetnormalizer
    pythoncffi
    pythoncppy
    pythoncryptography
    pythoncycler
    pythoncython
    pythondateutil
    pythondiskcache
    pythondocker
    pythongast
    pythongirderclient
    pythonidna
    pythonkiwisolver
    pythonmako
    pythonmeshio
    pythonpillow
    pythonply
    pythonpycparser
    pythonpyparsing
    pythonpysocks
    pythonpythran
    pythonrequests
    pythonrequeststoolbelt
    pythonsetuptools
    pythonsetuptoolsscm
    pythonsix
    pythontoml
    pythonurllib3
    pythonwebsocketclient
    pythonwheel
    pytz
    qhull
    qt5
    rggsession
    smtk
    smtkusersguide
    smtkxmsmesher
    szip
    vtk
    vtkonly
    vxl
    xmscore
    xmsgrid
    xmsinterp
    xmsmesher
    zlib
    )

  # These projects only support 64-bit versions of x86 processors.
  set(tbb_supported OFF)
  if (CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR
      CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64")
     set(tbb_supported ON)
     list(APPEND projects
       tbb) # x86_64-only
  endif ()
  set_property(GLOBAL PROPERTY
    supberbuild_tbb_supported "${tbb_supported}")

  if (ALLOW_openssl)
    list(APPEND projects openssl)
  endif ()

  if (NOT WIN32)
    list(APPEND projects
      ffi
      fontconfig
      fortran
      gperf
      lapack
      libxml2
      meshkit
      pkgconf
      sqlite)

    if (NOT APPLE)
      list(APPEND projects
        utillinux)
    endif ()
  endif ()

  if (UNIX AND NOT APPLE)
      list(APPEND projects
        expat
        glproto
        llvm
        ninja
        meson
        mesa)
  endif()

  if (WIN32)
    list(APPEND projects
      pywin32)
  endif ()

  if (NOT DEVELOPER_MODE_smtk)
    list(APPEND projects
      smtkresourcemanagerstate)
  endif ()

  # For now it's a convenient option to control smtk documentation.
  option(ENABLE_DOCUMENTATION "Enable smtk documentation" ON)

  option(USE_NONFREE_COMPONENTS "Enable the non-free parts of the superbuild" OFF)
  mark_as_advanced(USE_NONFREE_COMPONENTS)
  if (USE_NONFREE_COMPONENTS)
    list(APPEND projects
      capstone
      cubit
      triangle)
  endif ()

  # Capstone and Cubit are closed-source programs to which Kitware developers
  # have access. We provide logic for situating these programs into our
  # superbuild for development purposes only. These packages are not bundled or
  # distributed.
  set(KW_SHARE "" CACHE PATH "Location of Kitware-internal share directory.")

  if (NOT (capstone_enabled OR cubit_enabled))
    mark_as_advanced(KW_SHARE)
  endif ()

  set("${var}"
    ${projects}
    PARENT_SCOPE)
endfunction ()

function (superbuild_sanity_check)
  if (vtkonly_enabled AND paraview_enabled)
    message(FATAL_ERROR
      "Only one of the following projects should be enabled: vtkonly, paraview.")
  endif ()
  if (NOT smtk_enabled AND NOT cmb_enabled)
    message(FATAL_ERROR
      "At least one of the following projects must be enabled: cmb, or smtk.")
  endif ()
  if (NOT SUPERBUILD_PACKAGE_MODE STREQUAL "<none>")
    get_property(not_sane GLOBAL PROPERTY ${SUPERBUILD_PACKAGE_MODE}_REQUIRED_PROJECTS SET)
    get_property(package_required_projects GLOBAL PROPERTY ${SUPERBUILD_PACKAGE_MODE}_REQUIRED_PROJECTS)
    foreach (project IN LISTS package_required_projects)
      if (${project}_enabled)
        set(not_sane FALSE)
      endif ()
    endforeach ()
    if (not_sane)
      string(REPLACE ";" ", " required_projects "${package_required_projects}")
      message(FATAL_ERROR
        "At least one of the following projects must be enabled: ${require_projects}.")
    endif ()
  endif()
endfunction ()

function (superbuild_add_packaging)
  if (SUPERBUILD_PACKAGE_MODE STREQUAL "<none>" OR DEVELOPER_MODE_cmb)
    return ()
  endif ()

  # FUTURE: move this to superbuild_add_extra_package_test
  list(APPEND superbuild_export_variables SUPERBUILD_PACKAGE_MODE)

  if (WIN32)
    set(generators
      ZIP)
  elseif (APPLE)
    set(generators
      DragNDrop)
  else ()
    set(generators
      TGZ)
  endif ()

  set_cmb_python_modules()
  list(APPEND superbuild_export_variables cmb_python_modules)

  # Force qt SVG support, so CMB/ParaView can use SVG icons
  set(qt5_ENABLE_SVG ON CACHE INTERNAL "CMB/ParaView requires SVG support")

  if (UNIX AND NOT APPLE AND NOT USE_SYSTEM_qt5)
    set(Qt5_DIR "${superbuild_install_location}/lib/cmake/Qt5")
    set(qt5_version "${qt5_SOURCE_SELECTION}")
  else ()
    list(APPEND superbuild_export_variables
      Qt5_DIR)
    find_package(Qt5 QUIET REQUIRED COMPONENTS Core)
    set(qt5_version "${Qt5Core_VERSION_MAJOR}.${Qt5Core_VERSION_MINOR}")
  endif ()
  list(APPEND superbuild_export_variables
    qt5_version)

  list(APPEND superbuild_export_variables
    BOOST_ADDITIONAL_LIBRARIES)


  string(TOUPPER "${SUPERBUILD_PACKAGE_MODE}" PACKAGE_LABELS)

  # Setup the package suffix for user override
  superbuild_package_suffix("${SUPERBUILD_PACKAGE_MODE}_PACKAGE_SUFFIX")
  list(APPEND superbuild_export_variables
    ${SUPERBUILD_PACKAGE_MODE}_PACKAGE_SUFFIX
    )

  # Setup the package file name for override
  set("${SUPERBUILD_PACKAGE_MODE}_PACKAGE_FILE_NAME" ""
    CACHE STRING "If set, overrides the generated filename for the package")
  mark_as_advanced("${SUPERBUILD_PACKAGE_MODE}_PACKAGE_FILE_NAME")
  list(APPEND superbuild_export_variables
    ${SUPERBUILD_PACKAGE_MODE}_PACKAGE_FILE_NAME)

  # This must be included after the PACKAGE_SUFFIX and PACKAGE_FILE_NAME variables are determined
  include(package.test)

  foreach (generator IN LISTS generators)
    superbuild_add_extra_package_test("${SUPERBUILD_PACKAGE_MODE}" "${generator}"
      LABELS  "${PACKAGE_LABELS}"
      TIMEOUT 6400)

    add_package_extract_test("${SUPERBUILD_PACKAGE_MODE}" "${generator}"
      DEPENDS "cpack-${SUPERBUILD_PACKAGE_MODE}-${generator}"
      LABELS  "${PACKAGE_LABELS}"
      )

    add_package_import_test("${SUPERBUILD_PACKAGE_MODE}" "${generator}"
      DEPENDS "extract-${SUPERBUILD_PACKAGE_MODE}-${generator}"
      LABELS  "${PACKAGE_LABELS}"
      )
  endforeach ()
endfunction ()

macro (superbuild_setup_tests)
  if (cmb_enabled)
    set(DROP_LOCATION "/submit.php?project=CMB")
  elseif (smtk_enabled)
    set(DROP_LOCATION "/submit.php?project=SMTK")
  endif ()
endmacro ()

function (superbuild_add_tests)
  set_property(GLOBAL APPEND
    PROPERTY
      superbuild_test_projects cmb smtk)

  if (COMMAND cmb_extra_package_tests)
    cmb_extra_package_tests()
  endif ()
endfunction ()

# Make binaries on linux more compatible by default
option(SB_LINUX_CORE2_COMPATIBLE "On linux, enable core2 architecture compatible builds, disabling avx512f" ON)
mark_as_advanced(SB_LINUX_CORE2_COMPATIBLE)
if (SB_LINUX_CORE2_COMPATIBLE AND UNIX AND NOT APPLE AND
  (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR
   CMAKE_CXX_COMPILER_ID STREQUAL "GNU"))
  string(APPEND CMAKE_C_FLAGS " -march=core2 -mno-avx512f")
  string(APPEND CMAKE_CXX_FLAGS " -march=core2 -mno-avx512f")
endif()

# Default Qt5 to ON
set(_superbuild_default_qt5 ON)

# Add option to control OpenSSL
option(ALLOW_openssl "Make OpenSSL available (default OFF)" OFF)
mark_as_advanced(ALLOW_openssl)
if (ALLOW_openssl)
  set(_superbuild_enable_openssl ON)
endif ()

# Force these to be turned on manually
set(_superbuild_default_cmbusersguide OFF)
set(_superbuild_default_smtkusersguide OFF)

set(qt5_skip_modules
  qtconnectivity
  qtgamepad
  qtlocation
  qtmultimedia
  qtsensors
  qtserialport
  qtwayland
  qtwebchannel
  qtwebengine
  qtwebsockets)

set(BOOST_ADDITIONAL_LIBRARIES "" CACHE STRING "Additional boost libraries to build and package")
mark_as_advanced(BOOST_ADDITIONAL_LIBRARIES)

set(boost_minimum_version 1.64.0)
set(boost_libraries
  atomic
  chrono
  date_time
  filesystem
  iostreams
  log
  program_options
  regex
  serialization
  system
  thread
  timer
  ${BOOST_ADDITIONAL_LIBRARIES})

configure_file(
  "${CMAKE_CURRENT_LIST_DIR}/cmake/CTestCustom.cmake.in"
  "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom-cmb.cmake"
  @ONLY)

if (__BUILDBOT_INSTALL_LOCATION)
  set(superbuild_install_location "${__BUILDBOT_INSTALL_LOCATION}")
endif ()

set(suppress_projects
  boost
  freetype
  ftgl
  gdal
  hdf5
  netcdf
  numpy
  occt
  png
  pybind11
  szip
  vxl
  zlib)

# Default SMTK plugin omissions
list(APPEND smtk_plugin_omit
  smtkDelaunayPlugin
  smtkMeshSessionPlugin
  smtkOscillatorSessionPlugin
  smtkPolygonSessionPlugin)
set_property(GLOBAL PROPERTY smtk_plugin_omit ${smtk_plugin_omit})

foreach (suppress_project IN LISTS suppress_projects)
  set("_superbuild_suppress_${suppress_project}_output" ON)
endforeach ()

list(APPEND superbuild_version_files
  "${CMAKE_CURRENT_LIST_DIR}/versions.cmake")
list(APPEND superbuild_ctest_custom_files
  "${CMAKE_CURRENT_BINARY_DIR}/CTestCustom-cmb.cmake")
list(APPEND superbuild_project_roots
  "${CMAKE_CURRENT_LIST_DIR}/projects")
list(APPEND superbuild_package_roots
  "${CMAKE_CURRENT_LIST_DIR}/packages")

add_subdirectory(superbuild)

if (BUILD_TESTING)
  include(CTest)
endif ()
