Update FindMatlab.cmake to CMake's v3.14.3

Import latest CMake's FindMatlab.cmake file, from CMake v3.14.3
Exact file URL: https://raw.githubusercontent.com/Kitware/CMake/v3.14.3/Modules/FindMatlab.cmake

--- cmake/FindMatlab.cmake
+++ cmake/FindMatlab.cmake
@@ -1,224 +1,262 @@
-#.rst:
-# FindMatlab
-# ----------
+# CMake - Cross Platform Makefile Generator
+# Copyright 2000-2019 Kitware, Inc. and Contributors
+# All rights reserved.
 #
-# Finds Matlab installations and provides Matlab tools and libraries to cmake.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+#   notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+#   notice, this list of conditions and the following disclaimer in the
+#   documentation and/or other materials provided with the distribution.
 #
-# This package first intention is to find the libraries associated with Matlab
-# in order to be able to build Matlab extensions (mex files). It can also be
-# used:
-#
-# * run specific commands in Matlab
-# * declare Matlab unit test
-# * retrieve various information from Matlab (mex extensions, versions and
-#   release queries, ...)
-#
-# The module supports the following components:
-#
-# * ``MX_LIBRARY`` and ``ENG_LIBRARY`` respectively the MX and ENG libraries of
-#   Matlab
-# * ``MAIN_PROGRAM`` the Matlab binary program.
-#
-# .. note::
-#
-#   The version given to the :command:`find_package` directive is the Matlab
-#   **version**, which should not be confused with the Matlab *release* name
-#   (eg. `R2014`).
-#   The :command:`matlab_get_version_from_release_name` and
-#   :command:`matlab_get_release_name_from_version` allow a mapping
-#   from the release name to the version.
-#
-# The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give
-# the path of the desired Matlab version. Otherwise, the behaviour is platform
-# specific:
-#
-# * Windows: The installed versions of Matlab are retrieved from the
-#   Windows registry
-# * OS X: The installed versions of Matlab are given by the MATLAB
-#   paths in ``/Application``. If no such application is found, it falls back
-#   to the one that might be accessible from the PATH.
-# * Unix: The desired Matlab should be accessible from the PATH.
-#
-# Additional information is provided when :variable:`MATLAB_FIND_DEBUG` is set.
-# When a Matlab binary is found automatically and the ``MATLAB_VERSION``
-# is not given, the version is queried from Matlab directly.
-# On Windows, it can make a window running Matlab appear.
-#
-# The mapping of the release names and the version of Matlab is performed by
-# defining pairs (name, version).  The variable
-# :variable:`MATLAB_ADDITIONAL_VERSIONS` may be provided before the call to
-# the :command:`find_package` in order to handle additional versions.
-#
-# A Matlab scripts can be added to the set of tests using the
-# :command:`matlab_add_unit_test`. By default, the Matlab unit test framework
-# will be used (>= 2013a) to run this script, but regular ``.m`` files
-# returning an exit code can be used as well (0 indicating a success).
-#
-# Module Input Variables
-# ----------------------
-#
-# Users or projects may set the following variables to configure the module
-# behaviour:
-#
-# :variable:`Matlab_ROOT_DIR`
-#   the root of the Matlab installation.
-# :variable:`MATLAB_FIND_DEBUG`
-#   outputs debug information
-# :variable:`MATLAB_ADDITIONAL_VERSIONS`
-#   additional versions of Matlab for the automatic retrieval of the installed
-#   versions.
-#
-# Variables defined by the module
-# -------------------------------
-#
-# Result variables
-# ^^^^^^^^^^^^^^^^
-#
-# ``Matlab_FOUND``
-#   ``TRUE`` if the Matlab installation is found, ``FALSE``
-#   otherwise. All variable below are defined if Matlab is found.
-# ``Matlab_ROOT_DIR``
-#   the final root of the Matlab installation determined by the FindMatlab
-#   module.
-# ``Matlab_MAIN_PROGRAM``
-#   the Matlab binary program. Available only if the component ``MAIN_PROGRAM``
-#   is given in the :command:`find_package` directive.
-# ``Matlab_INCLUDE_DIRS``
-#  the path of the Matlab libraries headers
-# ``Matlab_MEX_LIBRARY``
-#   library for mex, always available.
-# ``Matlab_MX_LIBRARY``
-#   mx library of Matlab (arrays). Available only if the component
-#   ``MX_LIBRARY`` has been requested.
-# ``Matlab_ENG_LIBRARY``
-#   Matlab engine library. Available only if the component ``ENG_LIBRARY``
-#   is requested.
-# ``Matlab_LIBRARIES``
-#   the whole set of libraries of Matlab
-# ``Matlab_MEX_COMPILER``
-#   the mex compiler of Matlab. Currently not used.
-#   Available only if the component ``MEX_COMPILER`` is asked
-#
-# Cached variables
-# ^^^^^^^^^^^^^^^^
-#
-# ``Matlab_MEX_EXTENSION``
-#   the extension of the mex files for the current platform (given by Matlab).
-# ``Matlab_ROOT_DIR``
-#   the location of the root of the Matlab installation found. If this value
-#   is changed by the user, the result variables are recomputed.
-#
-# Provided macros
-# ---------------
-#
-# :command:`matlab_get_version_from_release_name`
-#   returns the version from the release name
-# :command:`matlab_get_release_name_from_version`
-#   returns the release name from the Matlab version
-#
-# Provided functions
-# ------------------
-#
-# :command:`matlab_add_mex`
-#   adds a target compiling a MEX file.
-# :command:`matlab_add_unit_test`
-#   adds a Matlab unit test file as a test to the project.
-# :command:`matlab_extract_all_installed_versions_from_registry`
-#   parses the registry for all Matlab versions. Available on Windows only.
-#   The part of the registry parsed is dependent on the host processor
-# :command:`matlab_get_all_valid_matlab_roots_from_registry`
-#   returns all the possible Matlab paths, according to a previously
-#   given list. Only the existing/accessible paths are kept. This is mainly
-#   useful for the searching all possible Matlab installation.
-# :command:`matlab_get_mex_suffix`
-#   returns the suffix to be used for the mex files
-#   (platform/architecture dependant)
-# :command:`matlab_get_version_from_matlab_run`
-#   returns the version of Matlab, given the full directory of the Matlab program.
-#
-#
-# Known issues
-# ------------
-#
-# **Symbol clash in a MEX target**
-#   By default, every symbols inside a MEX
-#   file defined with the command :command:`matlab_add_mex` have hidden
-#   visibility, except for the entry point. This is the default behaviour of
-#   the MEX compiler, which lowers the risk of symbol collision between the
-#   libraries shipped with Matlab, and the libraries to which the MEX file is
-#   linking to. This is also the default on Windows platforms.
-#
-#   However, this is not sufficient in certain case, where for instance your
-#   MEX file is linking against libraries that are already loaded by Matlab,
-#   even if those libraries have different SONAMES.
-#   A possible solution is to hide the symbols of the libraries to which the
-#   MEX target is linking to. This can be achieved in GNU GCC compilers with
-#   the linker option ``-Wl,--exclude-libs,ALL``.
-#
-# **Tests using GPU resources**
-#   in case your MEX file is using the GPU and
-#   in order to be able to run unit tests on this MEX file, the GPU resources
-#   should be properly released by Matlab. A possible solution is to make
-#   Matlab aware of the use of the GPU resources in the session, which can be
-#   performed by a command such as ``D = gpuDevice()`` at the beginning of
-#   the test script (or via a fixture).
-#
-#
-# Reference
-# --------------
-#
-# .. variable:: Matlab_ROOT_DIR
-#
-#    The root folder of the Matlab installation. If set before the call to
-#    :command:`find_package`, the module will look for the components in that
-#    path. If not set, then an automatic search of Matlab
-#    will be performed. If set, it should point to a valid version of Matlab.
-#
-# .. variable:: MATLAB_FIND_DEBUG
-#
-#    If set, the lookup of Matlab and the intermediate configuration steps are
-#    outputted to the console.
-#
-# .. variable:: MATLAB_ADDITIONAL_VERSIONS
-#
-#   If set, specifies additional versions of Matlab that may be looked for.
-#   The variable should be a list of strings, organised by pairs of release
-#   name and versions, such as follows::
-#
-#     set(MATLAB_ADDITIONAL_VERSIONS
-#         "release_name1=corresponding_version1"
-#         "release_name2=corresponding_version2"
-#         ...
-#         )
-#
-#   Example::
-#
-#     set(MATLAB_ADDITIONAL_VERSIONS
-#         "R2013b=8.2"
-#         "R2013a=8.1"
-#         "R2012b=8.0")
-#
-#   The order of entries in this list matters when several versions of
-#   Matlab are installed. The priority is set according to the ordering in
-#   this list.
-
-#=============================================================================
-# Copyright 2014-2015 Raffi Enficiaud, Max Planck Society
-#
-# Distributed under the OSI-approved BSD License (the "License");
-# see accompanying file Copyright.txt for details.
-#
-# This software is distributed WITHOUT ANY WARRANTY; without even the
-# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the License for more information.
-#=============================================================================
-# (To distribute this file outside of CMake, substitute the full
-#  License text for the above reference.)
+# * Neither the name of Kitware, Inc. nor the names of Contributors
+#   may be used to endorse or promote products derived from this
+#   software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#[=======================================================================[.rst:
+FindMatlab
+----------
+
+Finds Matlab or Matlab Compiler Runtime (MCR) and provides Matlab tools,
+libraries and compilers to CMake.
+
+This package primary purpose is to find the libraries associated with Matlab
+or the MCR in order to be able to build Matlab extensions (mex files). It
+can also be used:
+
+* to run specific commands in Matlab in case Matlab is available
+* for declaring Matlab unit test
+* to retrieve various information from Matlab (mex extensions, versions and
+  release queries, ...)
+
+The module supports the following components:
+
+* ``ENG_LIBRARY`` and ``MAT_LIBRARY``: respectively the ``ENG`` and ``MAT``
+  libraries of Matlab
+* ``MAIN_PROGRAM`` the Matlab binary program. Note that this component is not
+  available on the MCR version, and will yield an error if the MCR is found
+  instead of the regular Matlab installation.
+* ``MEX_COMPILER`` the MEX compiler.
+* ``MCC_COMPILER`` the MCC compiler, included with the Matlab Compiler add-on.
+* ``SIMULINK`` the Simulink environment.
+
+.. note::
+
+  The version given to the :command:`find_package` directive is the Matlab
+  **version**, which should not be confused with the Matlab *release* name
+  (eg. `R2014`).
+  The :command:`matlab_get_version_from_release_name` and
+  :command:`matlab_get_release_name_from_version` provide a mapping
+  between the release name and the version.
+
+The variable :variable:`Matlab_ROOT_DIR` may be specified in order to give
+the path of the desired Matlab version. Otherwise, the behaviour is platform
+specific:
+
+* Windows: The installed versions of Matlab/MCR are retrieved from the
+  Windows registry
+* OS X: The installed versions of Matlab/MCR are given by the MATLAB
+  default installation paths in ``/Application``. If no such application is
+  found, it falls back to the one that might be accessible from the ``PATH``.
+* Unix: The desired Matlab should be accessible from the ``PATH``. This does
+  not work for MCR installation and :variable:`Matlab_ROOT_DIR` should be
+  specified on this platform.
+
+Additional information is provided when :variable:`MATLAB_FIND_DEBUG` is set.
+When a Matlab/MCR installation is found automatically and the ``MATLAB_VERSION``
+is not given, the version is queried from Matlab directly (on Windows this
+may pop up a Matlab window) or from the MCR installation.
+
+The mapping of the release names and the version of Matlab is performed by
+defining pairs (name, version).  The variable
+:variable:`MATLAB_ADDITIONAL_VERSIONS` may be provided before the call to
+the :command:`find_package` in order to handle additional versions.
+
+A Matlab scripts can be added to the set of tests using the
+:command:`matlab_add_unit_test`. By default, the Matlab unit test framework
+will be used (>= 2013a) to run this script, but regular ``.m`` files
+returning an exit code can be used as well (0 indicating a success).
+
+Module Input Variables
+^^^^^^^^^^^^^^^^^^^^^^
+
+Users or projects may set the following variables to configure the module
+behaviour:
+
+:variable:`Matlab_ROOT_DIR`
+  the root of the Matlab installation.
+:variable:`MATLAB_FIND_DEBUG`
+  outputs debug information
+:variable:`MATLAB_ADDITIONAL_VERSIONS`
+  additional versions of Matlab for the automatic retrieval of the installed
+  versions.
+
+Variables defined by the module
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Result variables
+""""""""""""""""
+
+``Matlab_FOUND``
+  ``TRUE`` if the Matlab installation is found, ``FALSE``
+  otherwise. All variable below are defined if Matlab is found.
+``Matlab_ROOT_DIR``
+  the final root of the Matlab installation determined by the FindMatlab
+  module.
+``Matlab_MAIN_PROGRAM``
+  the Matlab binary program. Available only if the component ``MAIN_PROGRAM``
+  is given in the :command:`find_package` directive.
+``Matlab_INCLUDE_DIRS``
+ the path of the Matlab libraries headers
+``Matlab_MEX_LIBRARY``
+  library for mex, always available.
+``Matlab_MX_LIBRARY``
+  mx library of Matlab (arrays), always available.
+``Matlab_ENG_LIBRARY``
+  Matlab engine library. Available only if the component ``ENG_LIBRARY``
+  is requested.
+``Matlab_MAT_LIBRARY``
+  Matlab matrix library. Available only if the component ``MAT_LIBRARY``
+  is requested.
+``Matlab_ENGINE_LIBRARY``
+  Matlab C++ engine library, always available for R2018a and newer.
+``Matlab_DATAARRAY_LIBRARY``
+  Matlab C++ data array library, always available for R2018a and newer.
+``Matlab_LIBRARIES``
+  the whole set of libraries of Matlab
+``Matlab_MEX_COMPILER``
+  the mex compiler of Matlab. Currently not used.
+  Available only if the component ``MEX_COMPILER`` is requested.
+``Matlab_MCC_COMPILER``
+  the mcc compiler of Matlab. Included with the Matlab Compiler add-on.
+  Available only if the component ``MCC_COMPILER`` is requested.
+
+Cached variables
+""""""""""""""""
+
+``Matlab_MEX_EXTENSION``
+  the extension of the mex files for the current platform (given by Matlab).
+``Matlab_ROOT_DIR``
+  the location of the root of the Matlab installation found. If this value
+  is changed by the user, the result variables are recomputed.
+
+Provided macros
+^^^^^^^^^^^^^^^
+
+:command:`matlab_get_version_from_release_name`
+  returns the version from the release name
+:command:`matlab_get_release_name_from_version`
+  returns the release name from the Matlab version
+
+Provided functions
+^^^^^^^^^^^^^^^^^^
+
+:command:`matlab_add_mex`
+  adds a target compiling a MEX file.
+:command:`matlab_add_unit_test`
+  adds a Matlab unit test file as a test to the project.
+:command:`matlab_extract_all_installed_versions_from_registry`
+  parses the registry for all Matlab versions. Available on Windows only.
+  The part of the registry parsed is dependent on the host processor
+:command:`matlab_get_all_valid_matlab_roots_from_registry`
+  returns all the possible Matlab or MCR paths, according to a previously
+  given list. Only the existing/accessible paths are kept. This is mainly
+  useful for the searching all possible Matlab installation.
+:command:`matlab_get_mex_suffix`
+  returns the suffix to be used for the mex files
+  (platform/architecture dependent)
+:command:`matlab_get_version_from_matlab_run`
+  returns the version of Matlab/MCR, given the full directory of the Matlab/MCR
+  installation path.
+
+
+Known issues
+^^^^^^^^^^^^
+
+**Symbol clash in a MEX target**
+  By default, every symbols inside a MEX
+  file defined with the command :command:`matlab_add_mex` have hidden
+  visibility, except for the entry point. This is the default behaviour of
+  the MEX compiler, which lowers the risk of symbol collision between the
+  libraries shipped with Matlab, and the libraries to which the MEX file is
+  linking to. This is also the default on Windows platforms.
+
+  However, this is not sufficient in certain case, where for instance your
+  MEX file is linking against libraries that are already loaded by Matlab,
+  even if those libraries have different SONAMES.
+  A possible solution is to hide the symbols of the libraries to which the
+  MEX target is linking to. This can be achieved in GNU GCC compilers with
+  the linker option ``-Wl,--exclude-libs,ALL``.
+
+**Tests using GPU resources**
+  in case your MEX file is using the GPU and
+  in order to be able to run unit tests on this MEX file, the GPU resources
+  should be properly released by Matlab. A possible solution is to make
+  Matlab aware of the use of the GPU resources in the session, which can be
+  performed by a command such as ``D = gpuDevice()`` at the beginning of
+  the test script (or via a fixture).
+
+
+Reference
+^^^^^^^^^
+
+.. variable:: Matlab_ROOT_DIR
+
+   The root folder of the Matlab installation. If set before the call to
+   :command:`find_package`, the module will look for the components in that
+   path. If not set, then an automatic search of Matlab
+   will be performed. If set, it should point to a valid version of Matlab.
+
+.. variable:: MATLAB_FIND_DEBUG
+
+   If set, the lookup of Matlab and the intermediate configuration steps are
+   outputted to the console.
+
+.. variable:: MATLAB_ADDITIONAL_VERSIONS
+
+  If set, specifies additional versions of Matlab that may be looked for.
+  The variable should be a list of strings, organised by pairs of release
+  name and versions, such as follows::
+
+    set(MATLAB_ADDITIONAL_VERSIONS
+        "release_name1=corresponding_version1"
+        "release_name2=corresponding_version2"
+        ...
+        )
+
+  Example::
+
+    set(MATLAB_ADDITIONAL_VERSIONS
+        "R2013b=8.2"
+        "R2013a=8.1"
+        "R2012b=8.0")
+
+  The order of entries in this list matters when several versions of
+  Matlab are installed. The priority is set according to the ordering in
+  this list.
+#]=======================================================================]

 set(_FindMatlab_SELF_DIR "${CMAKE_CURRENT_LIST_DIR}")

-include(FindPackageHandleStandardArgs)
+include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
 include(CheckCXXCompilerFlag)
+include(CheckCCompilerFlag)

 # The currently supported versions. Other version can be added by the user by
@@ -228,6 +266,10 @@
 endif()

 set(MATLAB_VERSIONS_MAPPING
+  "R2018b=9.5"
+  "R2018a=9.4"
+  "R2017b=9.3"
+  "R2017a=9.2"
   "R2016b=9.1"
   "R2016a=9.0"
   "R2015b=8.6"
@@ -238,7 +280,6 @@
   "R2013a=8.1"
   "R2012b=8.0"
   "R2012a=7.14"
-
   "R2011b=7.13"
   "R2011a=7.12"
   "R2010b=7.11"
@@ -254,11 +295,12 @@
   file(MAKE_DIRECTORY "${_matlab_temporary_folder}")
 endif()

-#.rst:
-# .. command:: matlab_get_version_from_release_name
-#
-#   Returns the version of Matlab (17.58) from a release name (R2017k)
-macro (matlab_get_version_from_release_name release_name version_name)
+#[=======================================================================[.rst:
+.. command:: matlab_get_version_from_release_name
+
+  Returns the version of Matlab (17.58) from a release name (R2017k)
+#]=======================================================================]
+macro(matlab_get_version_from_release_name release_name version_name)

   string(REGEX MATCHALL "${release_name}=([0-9]+\\.?[0-9]*)" _matched ${MATLAB_VERSIONS_MAPPING})

@@ -266,7 +308,7 @@
   if(NOT _matched STREQUAL "")
     set(${version_name} ${CMAKE_MATCH_1})
   else()
-    message(WARNING "The release name ${release_name} is not registered")
+    message(WARNING "[MATLAB] The release name ${release_name} is not registered")
   endif()
   unset(_matched)

@@ -276,11 +318,12 @@

-#.rst:
-# .. command:: matlab_get_release_name_from_version
-#
-#   Returns the release name (R2017k) from the version of Matlab (17.58)
-macro (matlab_get_release_name_from_version version release_name)
+#[=======================================================================[.rst:
+.. command:: matlab_get_release_name_from_version
+
+  Returns the release name (R2017k) from the version of Matlab (17.58)
+#]=======================================================================]
+macro(matlab_get_release_name_from_version version release_name)

   set(${release_name} "")
   foreach(_var IN LISTS MATLAB_VERSIONS_MAPPING)
@@ -294,7 +337,7 @@
   unset(_var)
   unset(_matched)
   if(${release_name} STREQUAL "")
-    message(WARNING "The version ${version} is not registered")
+    message(WARNING "[MATLAB] The version ${version} is not registered")
   endif()

 endmacro()
@@ -336,69 +379,74 @@
 endmacro()

-#.rst:
-# .. command:: matlab_extract_all_installed_versions_from_registry
-#
-#   This function parses the registry and founds the Matlab versions that are
-#   installed. The found versions are returned in `matlab_versions`.
-#   Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for
-#   The returned list contains all versions under
-#   ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` or an empty list in case an error
-#   occurred (or nothing found).
-#
-#   .. note::
-#
-#     Only the versions are provided. No check is made over the existence of the
-#     installation referenced in the registry,
-#
+#[=======================================================================[.rst:
+.. command:: matlab_extract_all_installed_versions_from_registry
+
+  This function parses the registry and founds the Matlab versions that are
+  installed. The found versions are returned in `matlab_versions`.
+  Set `win64` to `TRUE` if the 64 bit version of Matlab should be looked for
+  The returned list contains all versions under
+  ``HKLM\\SOFTWARE\\Mathworks\\MATLAB`` and
+  ``HKLM\\SOFTWARE\\Mathworks\\MATLAB Runtime`` or an empty list in case an
+  error occurred (or nothing found).
+
+  .. note::
+
+    Only the versions are provided. No check is made over the existence of the
+    installation referenced in the registry,
+
+#]=======================================================================]
 function(matlab_extract_all_installed_versions_from_registry win64 matlab_versions)

   if(NOT CMAKE_HOST_WIN32)
-    message(FATAL_ERROR "This macro can only be called by a windows host (call to reg.exe")
-  endif()
-
-
-  if(${win64} AND ${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "64")
+    message(FATAL_ERROR "[MATLAB] This macro can only be called by a windows host (call to reg.exe)")
+  endif()
+
+  if(${win64} AND CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "64")
     set(APPEND_REG "/reg:64")
   else()
     set(APPEND_REG "/reg:32")
   endif()

-  # /reg:64 should be added on 64 bits capable OSs in order to enable the
-  # redirection of 64 bits applications
-  execute_process(
-    COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\MATLAB /f * /k ${APPEND_REG}
-    RESULT_VARIABLE resultMatlab
-    OUTPUT_VARIABLE varMatlab
-    ERROR_VARIABLE errMatlab
-    INPUT_FILE NUL
-    )
-
-
   set(matlabs_from_registry)
-  if(${resultMatlab} EQUAL 0)
-
-    string(
-      REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
-      matlab_versions_regex ${varMatlab})
-
-    foreach(match IN LISTS matlab_versions_regex)
+
+  foreach(_installation_type IN ITEMS "MATLAB" "MATLAB Runtime")
+
+    # /reg:64 should be added on 64 bits capable OSs in order to enable the
+    # redirection of 64 bits applications
+    execute_process(
+      COMMAND reg query HKEY_LOCAL_MACHINE\\SOFTWARE\\Mathworks\\${_installation_type} /f * /k ${APPEND_REG}
+      RESULT_VARIABLE resultMatlab
+      OUTPUT_VARIABLE varMatlab
+      ERROR_VARIABLE errMatlab
+      INPUT_FILE NUL
+      )
+
+
+    if(${resultMatlab} EQUAL 0)
+
       string(
-        REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)"
-        current_match ${match})
-
-      set(_matlab_current_version ${CMAKE_MATCH_1})
-      set(current_matlab_version_major ${CMAKE_MATCH_2})
-      set(current_matlab_version_minor ${CMAKE_MATCH_4})
-      if(NOT current_matlab_version_minor)
-        set(current_matlab_version_minor "0")
-      endif()
-
-      list(APPEND matlabs_from_registry ${_matlab_current_version})
-      unset(_matlab_current_version)
-    endforeach(match)
-
-  endif()
+        REGEX MATCHALL "MATLAB\\\\([0-9]+(\\.[0-9]+)?)"
+        matlab_versions_regex ${varMatlab})
+
+      foreach(match IN LISTS matlab_versions_regex)
+        string(
+          REGEX MATCH "MATLAB\\\\(([0-9]+)(\\.([0-9]+))?)"
+          current_match ${match})
+
+        set(_matlab_current_version ${CMAKE_MATCH_1})
+        set(current_matlab_version_major ${CMAKE_MATCH_2})
+        set(current_matlab_version_minor ${CMAKE_MATCH_4})
+        if(NOT current_matlab_version_minor)
+          set(current_matlab_version_minor "0")
+        endif()
+
+        list(APPEND matlabs_from_registry ${_matlab_current_version})
+        unset(_matlab_current_version)
+      endforeach()
+
+    endif()
+  endforeach()

   if(matlabs_from_registry)
     list(REMOVE_DUPLICATES matlabs_from_registry)
@@ -443,7 +491,6 @@
     # list(APPEND matlab_supported_versions MATLAB_ADDITIONAL_VERSIONS)
   # endif()

-
   # we order from more recent to older
   if(matlab_supported_versions)
     list(REMOVE_DUPLICATES matlab_supported_versions)
@@ -451,40 +498,40 @@
     list(REVERSE matlab_supported_versions)
   endif()

-
   set(${matlab_versions} ${matlab_supported_versions})
-
-
 endmacro()

-#.rst:
-# .. command:: matlab_get_all_valid_matlab_roots_from_registry
-#
-#   Populates the Matlab root with valid versions of Matlab.
-#   The returned matlab_roots is organized in pairs
-#   ``(version_number,matlab_root_path)``.
-#
-#   ::
-#
-#     matlab_get_all_valid_matlab_roots_from_registry(
-#         matlab_versions
-#         matlab_roots)
-#
-#   ``matlab_versions``
-#     the versions of each of the Matlab installations
-#   ``matlab_roots``
-#     the location of each of the Matlab installations
+#[=======================================================================[.rst:
+.. command:: matlab_get_all_valid_matlab_roots_from_registry
+
+  Populates the Matlab root with valid versions of Matlab or
+  Matlab Runtime (MCR).
+  The returned matlab_roots is organized in triplets
+  ``(type,version_number,matlab_root_path)``, where ``type``
+  indicates either ``MATLAB`` or ``MCR``.
+
+  ::
+
+    matlab_get_all_valid_matlab_roots_from_registry(
+        matlab_versions
+        matlab_roots)
+
+  ``matlab_versions``
+    the versions of each of the Matlab or MCR installations
+  ``matlab_roots``
+    the location of each of the Matlab or MCR installations
+#]=======================================================================]
 function(matlab_get_all_valid_matlab_roots_from_registry matlab_versions matlab_roots)

   # The matlab_versions comes either from
   # extract_matlab_versions_from_registry_brute_force or
   # matlab_extract_all_installed_versions_from_registry.

-
   set(_matlab_roots_list )
+  # check for Matlab installations
   foreach(_matlab_current_version ${matlab_versions})
     get_filename_component(
       current_MATLAB_ROOT
@@ -492,32 +539,47 @@
       ABSOLUTE)

     if(EXISTS ${current_MATLAB_ROOT})
-      list(APPEND _matlab_roots_list ${_matlab_current_version} ${current_MATLAB_ROOT})
-    endif()
-
-  endforeach(_matlab_current_version)
-  unset(_matlab_current_version)
+      list(APPEND _matlab_roots_list "MATLAB" ${_matlab_current_version} ${current_MATLAB_ROOT})
+    endif()
+
+  endforeach()
+
+  # Check for MCR installations
+  foreach(_matlab_current_version ${matlab_versions})
+    get_filename_component(
+      current_MATLAB_ROOT
+      "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MathWorks\\MATLAB Runtime\\${_matlab_current_version};MATLABROOT]"
+      ABSOLUTE)
+
+    # remove the dot
+    string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
+
+    if(EXISTS ${current_MATLAB_ROOT})
+      list(APPEND _matlab_roots_list "MCR" ${_matlab_current_version} "${current_MATLAB_ROOT}/v${_matlab_current_version_without_dot}")
+    endif()
+
+  endforeach()
   set(${matlab_roots} ${_matlab_roots_list} PARENT_SCOPE)
-  unset(_matlab_roots_list)
 endfunction()

-#.rst:
-# .. command:: matlab_get_mex_suffix
-#
-#   Returns the extension of the mex files (the suffixes).
-#   This function should not be called before the appropriate Matlab root has
-#   been found.
-#
-#   ::
-#
-#     matlab_get_mex_suffix(
-#         matlab_root
-#         mex_suffix)
-#
-#   ``matlab_root``
-#     the root of the Matlab installation
-#   ``mex_suffix``
-#     the variable name in which the suffix will be returned.
+#[=======================================================================[.rst:
+.. command:: matlab_get_mex_suffix
+
+  Returns the extension of the mex files (the suffixes).
+  This function should not be called before the appropriate Matlab root has
+  been found.
+
+  ::
+
+    matlab_get_mex_suffix(
+        matlab_root
+        mex_suffix)
+
+  ``matlab_root``
+    the root of the Matlab/MCR installation
+  ``mex_suffix``
+    the variable name in which the suffix will be returned.
+#]=======================================================================]
 function(matlab_get_mex_suffix matlab_root mex_suffix)

   # todo setup the extension properly. Currently I do not know if this is
@@ -550,7 +612,9 @@
       )
     endif()
   endforeach(current_mexext_suffix)
-
+  if(MATLAB_FIND_DEBUG)
+    message(STATUS "[MATLAB] Determining mex files extensions from '${matlab_root}/bin' with program '${Matlab_MEXEXTENSIONS_PROG}'")
+  endif()

   # the program has been found?
   if((NOT Matlab_MEXEXTENSIONS_PROG) OR (NOT EXISTS ${Matlab_MEXEXTENSIONS_PROG}))
@@ -570,12 +634,29 @@
     set(devnull INPUT_FILE NUL)
   endif()

+  # this is the preferred way. If this does not work properly (eg. MCR on Windows), then we use our own knowledge
   execute_process(
     COMMAND ${Matlab_MEXEXTENSIONS_PROG}
     OUTPUT_VARIABLE _matlab_mex_extension
+    #RESULT_VARIABLE _matlab_mex_extension_call
     ERROR_VARIABLE _matlab_mex_extension_error
     ${devnull})
-  string(STRIP ${_matlab_mex_extension} _matlab_mex_extension)
+
+  if(NOT "${_matlab_mex_extension_error}" STREQUAL "")
+    if(WIN32)
+      # this is only for intel architecture
+      if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+        set(_matlab_mex_extension "mexw64")
+      else()
+        set(_matlab_mex_extension "mexw32")
+      endif()
+    endif()
+  endif()
+
+  string(STRIP "${_matlab_mex_extension}"  _matlab_mex_extension)
+  if(MATLAB_FIND_DEBUG)
+    message(STATUS "[MATLAB] '${Matlab_MEXEXTENSIONS_PROG}' : returned '${_matlab_mex_extension_call}', determined extension '${_matlab_mex_extension}' and error string is '${_matlab_mex_extension_error}'")
+  endif()

   unset(Matlab_MEXEXTENSIONS_PROG CACHE)
   set(${mex_suffix} ${_matlab_mex_extension} PARENT_SCOPE)
@@ -584,26 +665,27 @@

-#.rst:
-# .. command:: matlab_get_version_from_matlab_run
-#
-#   This function runs Matlab program specified on arguments and extracts its
-#   version.
-#
-#   ::
-#
-#     matlab_get_version_from_matlab_run(
-#         matlab_binary_path
-#         matlab_list_versions)
-#
-#   ``matlab_binary_path``
-#     the location of the `matlab` binary executable
-#   ``matlab_list_versions``
-#     the version extracted from Matlab
+#[=======================================================================[.rst:
+.. command:: matlab_get_version_from_matlab_run
+
+  This function runs Matlab program specified on arguments and extracts its
+  version. If the path provided for the Matlab installation points to an MCR
+  installation, the version is extracted from the installed files.
+
+  ::
+
+    matlab_get_version_from_matlab_run(
+        matlab_binary_path
+        matlab_list_versions)
+
+  ``matlab_binary_path``
+    the location of the `matlab` binary executable
+  ``matlab_list_versions``
+    the version extracted from Matlab
+#]=======================================================================]
 function(matlab_get_version_from_matlab_run matlab_binary_program matlab_list_versions)

   set(${matlab_list_versions} "" PARENT_SCOPE)
-

   if(MATLAB_FIND_DEBUG)
     message(STATUS "[MATLAB] Determining the version of Matlab from ${matlab_binary_program}")
@@ -632,7 +714,7 @@
     set(devnull INPUT_FILE NUL)
   endif()

-  # timeout set to 30 seconds, in case it does not start
+  # timeout set to 120 seconds, in case it does not start
   # note as said before OUTPUT_VARIABLE cannot be used in a platform
   # independent manner however, not setting it would flush the output of Matlab
   # in the current console (unix variant)
@@ -641,11 +723,18 @@
     OUTPUT_VARIABLE _matlab_version_from_cmd_dummy
     RESULT_VARIABLE _matlab_result_version_call
     ERROR_VARIABLE _matlab_result_version_call_error
-    TIMEOUT 30
+    TIMEOUT 120
     WORKING_DIRECTORY "${_matlab_temporary_folder}"
     ${devnull}
     )

+  if("${_matlab_result_version_call}" MATCHES "timeout")
+    if(MATLAB_FIND_DEBUG)
+      message(WARNING "[MATLAB] Unable to determine the version of Matlab."
+        " Matlab call timed out after 120 seconds.")
+    endif()
+    return()
+  endif()

   if(${_matlab_result_version_call})
     if(MATLAB_FIND_DEBUG)
@@ -664,7 +753,7 @@
   file(REMOVE "${_matlab_temporary_folder}/matlabVersionLog.cmaketmp")

   set(index -1)
-  string(FIND ${_matlab_version_from_cmd} "ans" index)
+  string(FIND "${_matlab_version_from_cmd}" "ans" index)
   if(index EQUAL -1)

     if(MATLAB_FIND_DEBUG)
@@ -674,14 +763,14 @@
   else()
     set(matlab_list_of_all_versions_tmp)

-    string(SUBSTRING ${_matlab_version_from_cmd} ${index} -1 substring_ans)
+    string(SUBSTRING "${_matlab_version_from_cmd}" ${index} -1 substring_ans)
     string(
-      REGEX MATCHALL "ans[\r\n\t ]*=[\r\n\t ]*([0-9]+(\\.[0-9]+)?)"
+      REGEX MATCHALL "ans[\r\n\t ]*=[\r\n\t ]*'?([0-9]+(\\.[0-9]+)?)"
       matlab_versions_regex
       ${substring_ans})
     foreach(match IN LISTS matlab_versions_regex)
       string(
-        REGEX MATCH "ans[\r\n\t ]*=[\r\n\t ]*(([0-9]+)(\\.([0-9]+))?)"
+        REGEX MATCH "ans[\r\n\t ]*=[\r\n\t ]*'?(([0-9]+)(\\.([0-9]+))?)"
         current_match ${match})

       list(APPEND matlab_list_of_all_versions_tmp ${CMAKE_MATCH_1})
@@ -695,63 +784,77 @@

 endfunction()

-
-#.rst:
-# .. command:: matlab_add_unit_test
-#
-#   Adds a Matlab unit test to the test set of cmake/ctest.
-#   This command requires the component ``MAIN_PROGRAM``.
-#   The unit test uses the Matlab unittest framework (default, available
-#   starting Matlab 2013b+) except if the option ``NO_UNITTEST_FRAMEWORK``
-#   is given.
-#
-#   The function expects one Matlab test script file to be given.
-#   In the case ``NO_UNITTEST_FRAMEWORK`` is given, the unittest script file
-#   should contain the script to be run, plus an exit command with the exit
-#   value. This exit value will be passed to the ctest framework (0 success,
-#   non 0 failure). Additional arguments accepted by :command:`add_test` can be
-#   passed through ``TEST_ARGS`` (eg. ``CONFIGURATION <config> ...``).
-#
-#   ::
-#
-#     matlab_add_unit_test(
-#         NAME <name>
-#         UNITTEST_FILE matlab_file_containing_unittest.m
-#         [UNITTEST_PRECOMMAND matlab_command_to_run]
-#         [TIMEOUT timeout]
-#         [ADDITIONAL_PATH path1 [path2 ...]]
-#         [MATLAB_ADDITIONAL_STARTUP_OPTIONS option1 [option2 ...]]
-#         [TEST_ARGS arg1 [arg2 ...]]
-#         [NO_UNITTEST_FRAMEWORK]
-#         )
-#
-#   The function arguments are:
-#
-#   ``NAME``
-#     name of the unittest in ctest.
-#   ``UNITTEST_FILE``
-#     the matlab unittest file. Its path will be automatically
-#     added to the Matlab path.
-#   ``UNITTEST_PRECOMMAND``
-#     Matlab script command to be ran before the file
-#     containing the test (eg. GPU device initialisation based on CMake
-#     variables).
-#   ``TIMEOUT``
-#     the test timeout in seconds. Defaults to 180 seconds as the
-#     Matlab unit test may hang.
-#   ``ADDITIONAL_PATH``
-#     a list of paths to add to the Matlab path prior to
-#     running the unit test.
-#   ``MATLAB_ADDITIONAL_STARTUP_OPTIONS``
-#     a list of additional option in order
-#     to run Matlab from the command line.
-#   ``TEST_ARGS``
-#     Additional options provided to the add_test command. These
-#     options are added to the default options (eg. "CONFIGURATIONS Release")
-#   ``NO_UNITTEST_FRAMEWORK``
-#     when set, indicates that the test should not
-#     use the unittest framework of Matlab (available for versions >= R2013a).
-#
+#[=======================================================================[.rst:
+.. command:: matlab_add_unit_test
+
+  Adds a Matlab unit test to the test set of cmake/ctest.
+  This command requires the component ``MAIN_PROGRAM`` and hence is not
+  available for an MCR installation.
+
+  The unit test uses the Matlab unittest framework (default, available
+  starting Matlab 2013b+) except if the option ``NO_UNITTEST_FRAMEWORK``
+  is given.
+
+  The function expects one Matlab test script file to be given.
+  In the case ``NO_UNITTEST_FRAMEWORK`` is given, the unittest script file
+  should contain the script to be run, plus an exit command with the exit
+  value. This exit value will be passed to the ctest framework (0 success,
+  non 0 failure). Additional arguments accepted by :command:`add_test` can be
+  passed through ``TEST_ARGS`` (eg. ``CONFIGURATION <config> ...``).
+
+  ::
+
+    matlab_add_unit_test(
+        NAME <name>
+        UNITTEST_FILE matlab_file_containing_unittest.m
+        [CUSTOM_TEST_COMMAND matlab_command_to_run_as_test]
+        [UNITTEST_PRECOMMAND matlab_command_to_run]
+        [TIMEOUT timeout]
+        [ADDITIONAL_PATH path1 [path2 ...]]
+        [MATLAB_ADDITIONAL_STARTUP_OPTIONS option1 [option2 ...]]
+        [TEST_ARGS arg1 [arg2 ...]]
+        [NO_UNITTEST_FRAMEWORK]
+        )
+
+  The function arguments are:
+
+  ``NAME``
+    name of the unittest in ctest.
+  ``UNITTEST_FILE``
+    the matlab unittest file. Its path will be automatically
+    added to the Matlab path.
+  ``CUSTOM_TEST_COMMAND``
+    Matlab script command to run as the test.
+    If this is not set, then the following is run:
+    ``runtests('matlab_file_name'), exit(max([ans(1,:).Failed]))``
+    where ``matlab_file_name`` is the ``UNITTEST_FILE`` without the extension.
+  ``UNITTEST_PRECOMMAND``
+    Matlab script command to be ran before the file
+    containing the test (eg. GPU device initialisation based on CMake
+    variables).
+  ``TIMEOUT``
+    the test timeout in seconds. Defaults to 180 seconds as the
+    Matlab unit test may hang.
+  ``ADDITIONAL_PATH``
+    a list of paths to add to the Matlab path prior to
+    running the unit test.
+  ``MATLAB_ADDITIONAL_STARTUP_OPTIONS``
+    a list of additional option in order
+    to run Matlab from the command line.
+    ``-nosplash -nodesktop -nodisplay`` are always added.
+  ``TEST_ARGS``
+    Additional options provided to the add_test command. These
+    options are added to the default options (eg. "CONFIGURATIONS Release")
+  ``NO_UNITTEST_FRAMEWORK``
+    when set, indicates that the test should not
+    use the unittest framework of Matlab (available for versions >= R2013a).
+  ``WORKING_DIRECTORY``
+    This will be the working directory for the test. If specified it will
+    also be the output directory used for the log file of the test run.
+    If not specified the temporary directory ``${CMAKE_BINARY_DIR}/Matlab`` will
+    be used as the working directory and the log location.
+
+#]=======================================================================]
 function(matlab_add_unit_test)

   if(NOT Matlab_MAIN_PROGRAM)
@@ -759,11 +862,12 @@
   endif()

   set(options NO_UNITTEST_FRAMEWORK)
-  set(oneValueArgs NAME UNITTEST_PRECOMMAND UNITTEST_FILE TIMEOUT)
+  set(oneValueArgs NAME UNITTEST_FILE TIMEOUT WORKING_DIRECTORY
+    UNITTEST_PRECOMMAND CUSTOM_TEST_COMMAND)
   set(multiValueArgs ADDITIONAL_PATH MATLAB_ADDITIONAL_STARTUP_OPTIONS TEST_ARGS)

   set(prefix _matlab_unittest_prefix)
-  cmake_parse_arguments(${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} )
+  cmake_parse_arguments(PARSE_ARGV 0 ${prefix} "${options}" "${oneValueArgs}" "${multiValueArgs}" )

   if(NOT ${prefix}_NAME)
     message(FATAL_ERROR "[MATLAB] The Matlab test name cannot be empty")
@@ -771,15 +875,17 @@

   add_test(NAME ${${prefix}_NAME}
            COMMAND ${CMAKE_COMMAND}
-            -Dtest_name=${${prefix}_NAME}
-            -Dadditional_paths=${${prefix}_ADDITIONAL_PATH}
-            -Dtest_timeout=${${prefix}_TIMEOUT}
-            -Doutput_directory=${_matlab_temporary_folder}
-            -DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM}
-            -Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK}
-            -DMatlab_ADDITIONNAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS}
-            -Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}
-            -Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}
+            "-Dtest_name=${${prefix}_NAME}"
+            "-Dadditional_paths=${${prefix}_ADDITIONAL_PATH}"
+            "-Dtest_timeout=${${prefix}_TIMEOUT}"
+            "-Doutput_directory=${_matlab_temporary_folder}"
+            "-Dworking_directory=${${prefix}_WORKING_DIRECTORY}"
+            "-DMatlab_PROGRAM=${Matlab_MAIN_PROGRAM}"
+            "-Dno_unittest_framework=${${prefix}_NO_UNITTEST_FRAMEWORK}"
+            "-DMatlab_ADDITIONAL_STARTUP_OPTIONS=${${prefix}_MATLAB_ADDITIONAL_STARTUP_OPTIONS}"
+            "-Dunittest_file_to_run=${${prefix}_UNITTEST_FILE}"
+            "-Dcustom_Matlab_test_command=${${prefix}_CUSTOM_TEST_COMMAND}"
+            "-Dcmd_to_run_before_test=${${prefix}_UNITTEST_PRECOMMAND}"
             -P ${_FindMatlab_SELF_DIR}/MatlabTestsRedirect.cmake
            ${${prefix}_TEST_ARGS}
            ${${prefix}_UNPARSED_ARGUMENTS}
@@ -787,66 +893,82 @@
 endfunction()

-#.rst:
-# .. command:: matlab_add_mex
-#
-#   Adds a Matlab MEX target.
-#   This commands compiles the given sources with the current tool-chain in
-#   order to produce a MEX file. The final name of the produced output may be
-#   specified, as well as additional link libraries, and a documentation entry
-#   for the MEX file. Remaining arguments of the call are passed to the
-#   :command:`add_library` command.
-#
-#   ::
-#
-#      matlab_add_mex(
-#          NAME <name>
-#          SRC src1 [src2 ...]
-#          [OUTPUT_NAME output_name]
-#          [DOCUMENTATION file.txt]
-#          [LINK_TO target1 target2 ...]
-#          [...]
-#      )
-#
-#   ``NAME``
-#     name of the target.
-#   ``SRC``
-#     list of tje source files.
-#   ``LINK_TO``
-#     a list of additional link dependencies.  The target links to ``libmex``
-#     by default. If ``Matlab_MX_LIBRARY`` is defined, it also
-#     links to ``libmx``.
-#   ``OUTPUT_NAME``
-#     if given, overrides the default name. The default name is
-#     the name of the target without any prefix and
-#     with ``Matlab_MEX_EXTENSION`` suffix.
-#   ``DOCUMENTATION``
-#     if given, the file ``file.txt`` will be considered as
-#     being the documentation file for the MEX file. This file is copied into
-#     the same folder without any processing, with the same name as the final
-#     mex file, and with extension `.m`. In that case, typing ``help <name>``
-#     in Matlab prints the documentation contained in this file.
-#
-#   The documentation file is not processed and should be in the following
-#   format:
-#
-#   ::
-#
-#     % This is the documentation
-#     function ret = mex_target_output_name(input1)
-#
-function(matlab_add_mex )
+#[=======================================================================[.rst:
+.. command:: matlab_add_mex
+
+  Adds a Matlab MEX target.
+  This commands compiles the given sources with the current tool-chain in
+  order to produce a MEX file. The final name of the produced output may be
+  specified, as well as additional link libraries, and a documentation entry
+  for the MEX file. Remaining arguments of the call are passed to the
+  :command:`add_library` or :command:`add_executable` command.
+
+  ::
+
+     matlab_add_mex(
+         NAME <name>
+         [EXECUTABLE | MODULE | SHARED]
+         SRC src1 [src2 ...]
+         [OUTPUT_NAME output_name]
+         [DOCUMENTATION file.txt]
+         [LINK_TO target1 target2 ...]
+         [R2017b | R2018a]
+         [...]
+     )
+
+  ``NAME``
+    name of the target.
+  ``SRC``
+    list of source files.
+  ``LINK_TO``
+    a list of additional link dependencies.  The target links to ``libmex``
+    and ``libmx`` by default.
+  ``OUTPUT_NAME``
+    if given, overrides the default name. The default name is
+    the name of the target without any prefix and
+    with ``Matlab_MEX_EXTENSION`` suffix.
+  ``DOCUMENTATION``
+    if given, the file ``file.txt`` will be considered as
+    being the documentation file for the MEX file. This file is copied into
+    the same folder without any processing, with the same name as the final
+    mex file, and with extension `.m`. In that case, typing ``help <name>``
+    in Matlab prints the documentation contained in this file.
+  ``R2017b`` or ``R2018a`` may be given to specify the version of the C API
+    to use: ``R2017b`` specifies the traditional (separate complex) C API,
+    and corresponds to the ``-R2017b`` flag for the `mex` command. ``R2018a``
+    specifies the new interleaved complex C API, and corresponds to the
+    ``-R2018a`` flag for the `mex` command. Ignored if MATLAB version prior
+    to R2018a. Defaults to ``R2017b``.
+  ``MODULE`` or ``SHARED`` may be given to specify the type of library to be
+    created. ``EXECUTABLE`` may be given to create an executable instead of
+    a library. If no type is given explicitly, the type is ``SHARED``.
+
+  The documentation file is not processed and should be in the following
+  format:
+
+  ::
+
+    % This is the documentation
+    function ret = mex_target_output_name(input1)
+
+#]=======================================================================]
+function(matlab_add_mex)

   if(NOT WIN32)
     # we do not need all this on Windows
     # pthread options
-    check_cxx_compiler_flag(-pthread                    HAS_MINUS_PTHREAD)
+    if(CMAKE_CXX_COMPILER_LOADED)
+      check_cxx_compiler_flag(-pthread HAS_MINUS_PTHREAD)
+    elseif(CMAKE_C_COMPILER_LOADED)
+      check_c_compiler_flag(-pthread HAS_MINUS_PTHREAD)
+    endif()
     # we should use try_compile instead, the link flags are discarded from
     # this compiler_flag function.
     #check_cxx_compiler_flag(-Wl,--exclude-libs,ALL HAS_SYMBOL_HIDING_CAPABILITY)

   endif()

+  set(options EXECUTABLE MODULE SHARED R2017b R2018a)
   set(oneValueArgs NAME DOCUMENTATION OUTPUT_NAME)
   set(multiValueArgs LINK_TO SRC)

@@ -861,24 +983,56 @@
     set(${prefix}_OUTPUT_NAME ${${prefix}_NAME})
   endif()

-  add_library(${${prefix}_NAME}
-    SHARED
+  if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, add version source file
+    # TODO: check the file extensions in ${${prefix}_SRC} to see if they're C or C++ files
+    # Currently, the C and C++ versions of the version files are identical, so this doesn't matter.
+    set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/c_mexapi_version.c")
+    #set(MEX_VERSION_FILE "${Matlab_ROOT_DIR}/extern/version/cpp_mexapi_version.cpp")
+  endif()
+
+  if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # For 9.4 (R2018a) and newer, add API macro
+    if(${${prefix}_R2018a})
+      set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2018a")
+    else()
+      set(MEX_API_MACRO "MATLAB_DEFAULT_RELEASE=R2017b")
+    endif()
+  endif()
+
+  if(${prefix}_EXECUTABLE)
+    add_executable(${${prefix}_NAME}
       ${${prefix}_SRC}
+      ${MEX_VERSION_FILE}
       ${${prefix}_DOCUMENTATION}
       ${${prefix}_UNPARSED_ARGUMENTS})
+  else()
+    if(${prefix}_MODULE)
+      set(type MODULE)
+    else()
+      set(type SHARED)
+    endif()
+
+    add_library(${${prefix}_NAME}
+      ${type}
+      ${${prefix}_SRC}
+      ${MEX_VERSION_FILE}
+      ${${prefix}_DOCUMENTATION}
+      ${${prefix}_UNPARSED_ARGUMENTS})
+  endif()
+
   target_include_directories(${${prefix}_NAME} PRIVATE ${Matlab_INCLUDE_DIRS})

-  if(DEFINED Matlab_MX_LIBRARY)
-    target_link_libraries(${${prefix}_NAME} ${Matlab_MX_LIBRARY})
-  endif()
-
-  target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${${prefix}_LINK_TO})
+  if(Matlab_HAS_CPP_API)
+    target_link_libraries(${${prefix}_NAME} ${Matlab_ENGINE_LIBRARY} ${Matlab_DATAARRAY_LIBRARY})
+  endif()
+
+  target_link_libraries(${${prefix}_NAME} ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${${prefix}_LINK_TO})
   set_target_properties(${${prefix}_NAME}
       PROPERTIES
         PREFIX ""
         OUTPUT_NAME ${${prefix}_OUTPUT_NAME}
         SUFFIX ".${Matlab_MEX_EXTENSION}")

+  target_compile_definitions(${${prefix}_NAME} PRIVATE ${MEX_API_MACRO} MATLAB_MEX_FILE)

   # documentation
   if(NOT ${${prefix}_DOCUMENTATION} STREQUAL "")
@@ -887,73 +1041,87 @@
       TARGET ${${prefix}_NAME}
       PRE_BUILD
       COMMAND ${CMAKE_COMMAND} -E copy_if_different ${${prefix}_DOCUMENTATION} $<TARGET_FILE_DIR:${${prefix}_NAME}>/${output_name}.m
-      COMMENT "Copy ${${prefix}_NAME} documentation file into the output folder"
+      COMMENT "[MATLAB] Copy ${${prefix}_NAME} documentation file into the output folder"
     )
   endif() # documentation

   # entry point in the mex file + taking care of visibility and symbol clashes.
   if(WIN32)
+
+    if (MSVC)
+
+      set(_link_flags "${_link_flags} /EXPORT:mexFunction")
+      if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For 9.1 (R2016b) and newer, export version
+        set(_link_flags "${_link_flags} /EXPORT:mexfilerequiredapiversion")
+      endif()
+
+      if(Matlab_HAS_CPP_API)
+        set(_link_flags "${_link_flags} /EXPORT:mexCreateMexFunction /EXPORT:mexDestroyMexFunction /EXPORT:mexFunctionAdapter")
+        #TODO: Is this necessary?
+      endif()
+
+      set_property(TARGET ${${prefix}_NAME} APPEND PROPERTY LINK_FLAGS ${_link_flags})
+
+    endif() # TODO: what if there's a different compiler on Windows?
+
     set_target_properties(${${prefix}_NAME}
       PROPERTIES
         DEFINE_SYMBOL "DLL_EXPORT_SYM=__declspec(dllexport)")
+
   else()

-    if(HAS_MINUS_PTHREAD AND NOT APPLE)
-      # Apparently, compiling with -pthread generated the proper link flags
-      # and some defines at compilation
-      target_compile_options(${${prefix}_NAME} PRIVATE "-pthread")
-    endif()
-
-
-    # if we do not do that, the symbols linked from eg. boost remain weak and
-    # then clash with the ones defined in the matlab process. So by default
-    # the symbols are hidden.
-    # This also means that for shared libraries (like MEX), the entry point
-    # should be explicitly declared with default visibility, otherwise Matlab
-    # cannot find the entry point.
-    # Note that this is particularly meaningful if the MEX wrapper itself
-    # contains symbols that are clashing with Matlab (that are compiled in the
-    # MEX file). In order to propagate the visibility options to the libraries
-    # to which the MEX file is linked against, the -Wl,--exclude-libs,ALL
-    # option should also be specified.
-
-    set_target_properties(${${prefix}_NAME}
-      PROPERTIES
-        CXX_VISIBILITY_PRESET "hidden"
-        C_VISIBILITY_PRESET "hidden"
-        VISIBILITY_INLINES_HIDDEN "hidden"
-    )
-
-    #  get_target_property(
-    #    _previous_link_flags
-    #    ${${prefix}_NAME}
-    #    LINK_FLAGS)
-    #  if(NOT _previous_link_flags)
-    #    set(_previous_link_flags)
-    #  endif()
-
-    #  if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
-    #    set_target_properties(${${prefix}_NAME}
-    #      PROPERTIES
-    #        LINK_FLAGS "${_previous_link_flags} -Wl,--exclude-libs,ALL"
-    #        # -Wl,--version-script=${_FindMatlab_SELF_DIR}/MatlabLinuxVisibility.map"
-    #    )
-    #  elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
-    #    # in this case, all other symbols become hidden.
-    #    set_target_properties(${${prefix}_NAME}
-    #      PROPERTIES
-    #        LINK_FLAGS "${_previous_link_flags} -Wl,-exported_symbol,_mexFunction"
-    #        #-Wl,-exported_symbols_list,${_FindMatlab_SELF_DIR}/MatlabOSXVisilibity.map"
-    #    )
-    #  endif()
-
-
+    if(${Matlab_VERSION_STRING} VERSION_LESS "9.1") # For versions prior to 9.1 (R2016b)
+      set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/mexFunction.map)
+    else()                                          # For 9.1 (R2016b) and newer
+      set(_ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/c_exportsmexfileversion.map)
+    endif()
+
+    if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.5") # For 9.5 (R2018b) (and newer?)
+      target_compile_options(${${prefix}_NAME} PRIVATE "-fvisibility=default")
+      # This one is weird, it might be a bug in <mex.h> for R2018b. When compiling with
+      # -fvisibility=hidden, the symbol `mexFunction` cannot be exported. Reading the
+      # source code for <mex.h>, it seems that the preprocessor macro `MW_NEEDS_VERSION_H`
+      # needs to be defined for `__attribute__ ((visibility("default")))` to be added
+      # in front of the declaration of `mexFunction`. In previous versions of MATLAB this
+      # was not the case, there `DLL_EXPORT_SYM` needed to be defined.
+      # Adding `-fvisibility=hidden` to the `mex` command causes the build to fail.
+      # TODO: Check that this is still necessary in R2019a when it comes out.
+    endif()
+
+    if(APPLE)
+
+      if(Matlab_HAS_CPP_API)
+        list(APPEND _ver_map_files ${Matlab_EXTERN_LIBRARY_DIR}/cppMexFunction.map) # This one doesn't exist on Linux
+        set(_link_flags "${_link_flags} -Wl,-U,_mexCreateMexFunction -Wl,-U,_mexDestroyMexFunction -Wl,-U,_mexFunctionAdapter")
+        # On MacOS, the MEX command adds the above, without it the link breaks
+        # because we indiscriminately use "cppMexFunction.map" even for C API MEX-files.
+      endif()
+
+      set(_export_flag_name -exported_symbols_list)
+
+    else() # Linux
+
+      if(HAS_MINUS_PTHREAD)
+        # Apparently, compiling with -pthread generated the proper link flags
+        # and some defines at compilation
+        target_compile_options(${${prefix}_NAME} PRIVATE "-pthread")
+      endif()
+
+      set(_link_flags "${_link_flags} -Wl,--as-needed")
+
+      set(_export_flag_name --version-script)
+
+    endif()
+
+    foreach(_file ${_ver_map_files})
+      set(_link_flags "${_link_flags} -Wl,${_export_flag_name},${_file}")
+    endforeach()

     set_target_properties(${${prefix}_NAME}
       PROPERTIES
         DEFINE_SYMBOL "DLL_EXPORT_SYM=__attribute__ ((visibility (\"default\")))"
-    )
-
+        LINK_FLAGS "${_link_flags}"
+    ) # The `mex` command doesn't add this define. Is it necessary?

   endif()

@@ -963,10 +1131,10 @@
 # (internal)
 # Used to get the version of matlab, using caching. This basically transforms the
 # output of the root list, with possible unknown version, to a version
-#
-function(_Matlab_get_version_from_root matlab_root matlab_known_version matlab_final_version)
-
-  # if the version is not trivial, we query matlab for that
+# This can possibly run Matlab for extracting the version.
+function(_Matlab_get_version_from_root matlab_root matlab_or_mcr matlab_known_version matlab_final_version)
+
+  # if the version is not trivial, we query matlab (if not MCR) for that
   # we keep track of the location of matlab that induced this version
   #if(NOT DEFINED Matlab_PROG_VERSION_STRING_AUTO_DETECT)
   #  set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version")
@@ -979,170 +1147,211 @@
     return()
   endif()

-  #
-  set(_matlab_current_program ${Matlab_MAIN_PROGRAM})
-
-  # do we already have a matlab program?
-  if(NOT _matlab_current_program)
-
-    set(_find_matlab_options)
-    if(matlab_root AND EXISTS ${matlab_root})
-      set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH)
-    endif()
-
-    find_program(
-        _matlab_current_program
-        matlab
-        ${_find_matlab_options}
-        DOC "Matlab main program"
-      )
-  endif()
-
-  if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program})
-    # if not found, clear the dependent variables
+  if("${matlab_or_mcr}" STREQUAL "UNKNOWN")
     if(MATLAB_FIND_DEBUG)
-      message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}")
-    endif()
-    set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
-    set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+      message(WARNING "[MATLAB] Determining Matlab or MCR")
+    endif()
+
+    if(EXISTS "${matlab_root}/appdata/version.xml")
+      # we inspect the application version.xml file that contains the product information
+      file(STRINGS "${matlab_root}/appdata/version.xml" productinfo_string NEWLINE_CONSUME)
+      string(REGEX MATCH "<installedProductData.*displayedString=\"([a-zA-Z ]+)\".*/>"
+             product_reg_match
+             ${productinfo_string}
+            )
+
+      # default fallback to Matlab
+      set(matlab_or_mcr "MATLAB")
+      if(NOT "${CMAKE_MATCH_1}" STREQUAL "")
+        string(TOLOWER "${CMAKE_MATCH_1}" product_reg_match)
+
+        if("${product_reg_match}" STREQUAL "matlab runtime")
+          set(matlab_or_mcr "MCR")
+        endif()
+      endif()
+    endif()
+
+    if(MATLAB_FIND_DEBUG)
+      message(WARNING "[MATLAB] '${matlab_root}' contains the '${matlab_or_mcr}'")
+    endif()
+  endif()
+
+  # UNKNOWN is the default behaviour in case we
+  # - have an erroneous matlab_root
+  # - have an initial 'UNKNOWN'
+  if("${matlab_or_mcr}" STREQUAL "MATLAB" OR "${matlab_or_mcr}" STREQUAL "UNKNOWN")
+    # MATLAB versions
+    set(_matlab_current_program ${Matlab_MAIN_PROGRAM})
+
+    # do we already have a matlab program?
+    if(NOT _matlab_current_program)
+
+      set(_find_matlab_options)
+      if(matlab_root AND EXISTS ${matlab_root})
+        set(_find_matlab_options PATHS ${matlab_root} ${matlab_root}/bin NO_DEFAULT_PATH)
+      endif()
+
+      find_program(
+          _matlab_current_program
+          matlab
+          ${_find_matlab_options}
+          DOC "Matlab main program"
+        )
+    endif()
+
+    if(NOT _matlab_current_program OR NOT EXISTS ${_matlab_current_program})
+      # if not found, clear the dependent variables
+      if(MATLAB_FIND_DEBUG)
+        message(WARNING "[MATLAB] Cannot find the main matlab program under ${matlab_root}")
+      endif()
+      set(Matlab_PROG_VERSION_STRING_AUTO_DETECT "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+      set(Matlab_VERSION_STRING_INTERNAL "" CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+      unset(_matlab_current_program)
+      unset(_matlab_current_program CACHE)
+      return()
+    endif()
+
+    # full real path for path comparison
+    get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH)
     unset(_matlab_current_program)
     unset(_matlab_current_program CACHE)
-    return()
-  endif()
-
-  # full real path for path comparison
-  get_filename_component(_matlab_main_real_path_tmp "${_matlab_current_program}" REALPATH)
-  unset(_matlab_current_program)
-  unset(_matlab_current_program CACHE)
-
-  # is it the same as the previous one?
-  if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT)
+
+    # is it the same as the previous one?
+    if(_matlab_main_real_path_tmp STREQUAL Matlab_PROG_VERSION_STRING_AUTO_DETECT)
+      set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
+      return()
+    endif()
+
+    # update the location of the program
+    set(Matlab_PROG_VERSION_STRING_AUTO_DETECT
+        ${_matlab_main_real_path_tmp}
+        CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
+
+    set(matlab_list_of_all_versions)
+    matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions)
+
+    list(LENGTH matlab_list_of_all_versions list_of_all_versions_length)
+    if(${list_of_all_versions_length} GREATER 0)
+      list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
+    else()
+      set(_matlab_version_tmp "unknown")
+    endif()
+
+    # set the version into the cache
+    set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
+
+    # warning, just in case several versions found (should not happen)
+    if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG)
+      message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})")
+    endif()
+
+    # return the updated value
     set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
-    return()
-  endif()
-
-  # update the location of the program
-  set(Matlab_PROG_VERSION_STRING_AUTO_DETECT ${_matlab_main_real_path_tmp} CACHE INTERNAL "internal matlab location for the discovered version" FORCE)
-
-  set(matlab_list_of_all_versions)
-  matlab_get_version_from_matlab_run("${Matlab_PROG_VERSION_STRING_AUTO_DETECT}" matlab_list_of_all_versions)
-
-  list(GET matlab_list_of_all_versions 0 _matlab_version_tmp)
-
-  # set the version into the cache
-  set(Matlab_VERSION_STRING_INTERNAL ${_matlab_version_tmp} CACHE INTERNAL "Matlab version (automatically determined)" FORCE)
-
-  # warning, just in case several versions found (should not happen)
-  list(LENGTH matlab_list_of_all_versions list_of_all_versions_length)
-  if((${list_of_all_versions_length} GREATER 1) AND MATLAB_FIND_DEBUG)
-    message(WARNING "[MATLAB] Found several versions, taking the first one (versions found ${matlab_list_of_all_versions})")
-  endif()
-
-  # return the updated value
-  set(${matlab_final_version} ${Matlab_VERSION_STRING_INTERNAL} PARENT_SCOPE)
+  elseif(EXISTS "${matlab_root}/VersionInfo.xml")
+    # MCR
+    # we cannot run anything in order to extract the version. We assume that the file
+    # VersionInfo.xml exists under the MatlabRoot, we look for it and extract the version from there
+    set(_matlab_version_tmp "unknown")
+    file(STRINGS "${matlab_root}/VersionInfo.xml" versioninfo_string NEWLINE_CONSUME)
+
+    if(versioninfo_string)
+      # parses "<version>9.2.0.538062</version>"
+      string(REGEX MATCH "<version>(.*)</version>"
+             version_reg_match
+             ${versioninfo_string}
+            )
+
+      if(NOT "${version_reg_match}" STREQUAL "")
+        if("${CMAKE_MATCH_1}" MATCHES "(([0-9])\\.([0-9]))[\\.0-9]*")
+          set(_matlab_version_tmp "${CMAKE_MATCH_1}")
+        endif()
+      endif()
+    endif()
+    set(${matlab_final_version} "${_matlab_version_tmp}" PARENT_SCOPE)
+    set(Matlab_VERSION_STRING_INTERNAL
+        "${_matlab_version_tmp}"
+        CACHE INTERNAL "Matlab (MCR) version (automatically determined)"
+        FORCE)
+  endif() # Matlab or MCR

 endfunction()

-
-
-
-
-
-# ###################################
-# Exploring the possible Matlab_ROOTS
-
-# this variable will get all Matlab installations found in the current system.
-set(_matlab_possible_roots)
-
-
-
-if(Matlab_ROOT_DIR)
-  # if the user specifies a possible root, we keep this one
-
-  if(NOT EXISTS ${Matlab_ROOT_DIR})
-    # if Matlab_ROOT_DIR specified but erroneous
+# Utility function for finding Matlab or MCR on Win32
+function(_Matlab_find_instances_win32 matlab_roots)
+  # On WIN32, we look for Matlab installation in the registry
+  # if unsuccessful, we look for all known revision and filter the existing
+  # ones.
+
+  # testing if we are able to extract the needed information from the registry
+  set(_matlab_versions_from_registry)
+
+  if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+    set(_matlab_win64 ON)
+  else()
+    set(_matlab_win64 OFF)
+  endif()
+
+  matlab_extract_all_installed_versions_from_registry(_matlab_win64 _matlab_versions_from_registry)
+
+  # the returned list is empty, doing the search on all known versions
+  if(NOT _matlab_versions_from_registry)
     if(MATLAB_FIND_DEBUG)
-      message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})")
-    endif()
-  else()
-    # NOTFOUND indicates the code below to search for the version automatically
-    if(NOT DEFINED Matlab_VERSION_STRING_INTERNAL)
-      list(APPEND _matlab_possible_roots "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version
-    else()
-      list(APPEND _matlab_possible_roots ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version
-    endif()
-  endif()
-
-
-else()
-
-  # if the user does not specify the possible installation root, we look for
-  # one installation using the appropriate heuristics
-
-  if(WIN32)
-
-    # On WIN32, we look for Matlab installation in the registry
-    # if unsuccessful, we look for all known revision and filter the existing
-    # ones.
-
-    # testing if we are able to extract the needed information from the registry
-    set(_matlab_versions_from_registry)
-    matlab_extract_all_installed_versions_from_registry(CMAKE_CL_64 _matlab_versions_from_registry)
-
-    # the returned list is empty, doing the search on all known versions
-    if(NOT _matlab_versions_from_registry)
-
+      message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions")
+    endif()
+    extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry)
+  endif()
+
+  # filtering the results with the registry keys
+  matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots)
+  set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
+
+endfunction()
+
+# Utility function for finding Matlab or MCR on OSX
+function(_Matlab_find_instances_osx matlab_roots)
+
+  set(_matlab_possible_roots)
+  # on mac, we look for the /Application paths
+  # this corresponds to the behaviour on Windows. On Linux, we do not have
+  # any other guess.
+  matlab_get_supported_releases(_matlab_releases)
+  if(MATLAB_FIND_DEBUG)
+    message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported "
+                 "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation")
+  endif()
+
+  foreach(_matlab_current_release IN LISTS _matlab_releases)
+    matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version)
+    string(REPLACE "." "" _matlab_current_version_without_dot "${_matlab_current_version}")
+    set(_matlab_base_path "/Applications/MATLAB_${_matlab_current_release}.app")
+
+    # Check Matlab, has precedence over MCR
+    if(EXISTS ${_matlab_base_path})
       if(MATLAB_FIND_DEBUG)
-        message(STATUS "[MATLAB] Search for Matlab from the registry unsuccessful, testing all supported versions")
+        message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_base_path}")
       endif()
-
-      extract_matlab_versions_from_registry_brute_force(_matlab_versions_from_registry)
-    endif()
-
-    # filtering the results with the registry keys
-    matlab_get_all_valid_matlab_roots_from_registry("${_matlab_versions_from_registry}" _matlab_possible_roots)
-    unset(_matlab_versions_from_registry)
-
-  elseif(APPLE)
-
-    # on mac, we look for the /Application paths
-    # this corresponds to the behaviour on Windows. On Linux, we do not have
-    # any other guess.
-    matlab_get_supported_releases(_matlab_releases)
-    if(MATLAB_FIND_DEBUG)
-      message(STATUS "[MATLAB] Matlab supported versions ${_matlab_releases}. If more version should be supported "
-                   "the variable MATLAB_ADDITIONAL_VERSIONS can be set according to the documentation")
-    endif()
-
-    foreach(_matlab_current_release IN LISTS _matlab_releases)
-      set(_matlab_full_string "/Applications/MATLAB_${_matlab_current_release}.app")
-      if(EXISTS ${_matlab_full_string})
-        set(_matlab_current_version)
-        matlab_get_version_from_release_name("${_matlab_current_release}" _matlab_current_version)
-        if(MATLAB_FIND_DEBUG)
-          message(STATUS "[MATLAB] Found version ${_matlab_current_release} (${_matlab_current_version}) in ${_matlab_full_string}")
-        endif()
-        list(APPEND _matlab_possible_roots ${_matlab_current_version} ${_matlab_full_string})
-        unset(_matlab_current_version)
+      list(APPEND _matlab_possible_roots "MATLAB" ${_matlab_current_version} ${_matlab_base_path})
+    endif()
+
+    # Checks MCR
+    set(_mcr_path "/Applications/MATLAB/MATLAB_Runtime/v${_matlab_current_version_without_dot}")
+    if(EXISTS "${_mcr_path}")
+      if(MATLAB_FIND_DEBUG)
+        message(STATUS "[MATLAB] Found MCR version ${_matlab_current_release} (${_matlab_current_version}) in ${_mcr_path}")
       endif()
-
-      unset(_matlab_full_string)
-    endforeach(_matlab_current_release)
-
-    unset(_matlab_current_release)
-    unset(_matlab_releases)
-
-  endif()
-
-endif()
-
-
-
-list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
-if(_numbers_of_matlab_roots EQUAL 0)
-  # if we have not found anything, we fall back on the PATH
-
+      list(APPEND _matlab_possible_roots "MCR" ${_matlab_current_version} ${_mcr_path})
+    endif()
+
+  endforeach()
+  set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
+
+endfunction()
+
+# Utility function for finding Matlab or MCR from the PATH
+function(_Matlab_find_instances_from_path matlab_roots)
+
+  set(_matlab_possible_roots)

   # At this point, we have no other choice than trying to find it from PATH.
   # If set by the user, this wont change
@@ -1150,7 +1359,6 @@
     _matlab_main_tmp
     NAMES matlab)

-
   if(_matlab_main_tmp)
     # we then populate the list of roots, with empty version
     if(MATLAB_FIND_DEBUG)
@@ -1162,20 +1370,91 @@

     # get the directory (the command below has to be run twice)
     # this will be the matlab root
-    get_filename_component(_matlab_current_location "${_matlab_current_location}" PATH)
-    get_filename_component(_matlab_current_location "${_matlab_current_location}" PATH) # Matlab should be in bin
-
-    list(APPEND _matlab_possible_roots "NOTFOUND" ${_matlab_current_location})
-
-    unset(_matlab_current_location)
-
-  endif()
-  unset(_matlab_main_tmp CACHE)
-
-endif()
-
-
-
+    get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY)
+    get_filename_component(_matlab_current_location "${_matlab_current_location}" DIRECTORY) # Matlab should be in bin
+
+    # We found the Matlab program
+    list(APPEND _matlab_possible_roots "MATLAB" "NOTFOUND" ${_matlab_current_location})
+
+    # we remove this from the CACHE
+    unset(_matlab_main_tmp CACHE)
+  else()
+    find_program(
+      _matlab_mex_tmp
+      NAMES mex)
+    if(_matlab_mex_tmp)
+      # we then populate the list of roots, with empty version
+      if(MATLAB_FIND_DEBUG)
+        message(STATUS "[MATLAB] mex compiler found from PATH: ${_matlab_mex_tmp}")
+      endif()
+
+      # resolve symlinks
+      get_filename_component(_mex_current_location "${_matlab_mex_tmp}" REALPATH)
+
+      # get the directory (the command below has to be run twice)
+      # this will be the matlab root
+      get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY)
+      get_filename_component(_mex_current_location "${_mex_current_location}" DIRECTORY) # Matlab Runtime mex compiler should be in bin
+
+      # We found the Matlab program
+      list(APPEND _matlab_possible_roots "MCR" "NOTFOUND" ${_mex_current_location})
+
+      unset(_matlab_mex_tmp CACHE)
+    else()
+      if(MATLAB_FIND_DEBUG)
+        message(STATUS "[MATLAB] mex compiler not found")
+      endif()
+    endif()
+
+
+  endif()
+
+  set(${matlab_roots} ${_matlab_possible_roots} PARENT_SCOPE)
+endfunction()
+
+
+# ###################################
+# Exploring the possible Matlab_ROOTS
+
+# this variable will get all Matlab installations found in the current system.
+set(_matlab_possible_roots)
+
+if(Matlab_ROOT_DIR)
+  # if the user specifies a possible root, we keep this one
+
+  if(NOT EXISTS "${Matlab_ROOT_DIR}")
+    # if Matlab_ROOT_DIR specified but erroneous
+    if(MATLAB_FIND_DEBUG)
+      message(WARNING "[MATLAB] the specified path for Matlab_ROOT_DIR does not exist (${Matlab_ROOT_DIR})")
+    endif()
+  else()
+    # NOTFOUND indicates the code below to search for the version automatically
+    if("${Matlab_VERSION_STRING_INTERNAL}" STREQUAL "")
+      list(APPEND _matlab_possible_roots "UNKNOWN" "NOTFOUND" ${Matlab_ROOT_DIR}) # empty version, empty MCR/Matlab indication
+    else()
+      list(APPEND _matlab_possible_roots "UNKNOWN" ${Matlab_VERSION_STRING_INTERNAL} ${Matlab_ROOT_DIR}) # cached version
+    endif()
+  endif()
+else()
+
+  # if the user does not specify the possible installation root, we look for
+  # one installation using the appropriate heuristics.
+  # There is apparently no standard way on Linux.
+  if(CMAKE_HOST_WIN32)
+    _Matlab_find_instances_win32(_matlab_possible_roots_win32)
+    list(APPEND _matlab_possible_roots ${_matlab_possible_roots_win32})
+  elseif(APPLE)
+    _Matlab_find_instances_osx(_matlab_possible_roots_osx)
+    list(APPEND _matlab_possible_roots ${_matlab_possible_roots_osx})
+  endif()
+endif()
+
+
+list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
+if(_numbers_of_matlab_roots EQUAL 0)
+  # if we have not found anything, we fall back on the PATH
+  _Matlab_find_instances_from_path(_matlab_possible_roots)
+endif()

 if(MATLAB_FIND_DEBUG)
@@ -1189,37 +1468,45 @@
 # take the first possible Matlab root
 list(LENGTH _matlab_possible_roots _numbers_of_matlab_roots)
 set(Matlab_VERSION_STRING "NOTFOUND")
+set(Matlab_Or_MCR "UNKNOWN")
 if(_numbers_of_matlab_roots GREATER 0)
-  list(GET _matlab_possible_roots 0 Matlab_VERSION_STRING)
-  list(GET _matlab_possible_roots 1 Matlab_ROOT_DIR)
+  list(GET _matlab_possible_roots 0 Matlab_Or_MCR)
+  list(GET _matlab_possible_roots 1 Matlab_VERSION_STRING)
+  list(GET _matlab_possible_roots 2 Matlab_ROOT_DIR)

   # adding a warning in case of ambiguity
-  if(_numbers_of_matlab_roots GREATER 2 AND MATLAB_FIND_DEBUG)
+  if(_numbers_of_matlab_roots GREATER 3 AND MATLAB_FIND_DEBUG)
     message(WARNING "[MATLAB] Found several distributions of Matlab. Setting the current version to ${Matlab_VERSION_STRING} (located ${Matlab_ROOT_DIR})."
                     " If this is not the desired behaviour, provide the -DMatlab_ROOT_DIR=... on the command line")
   endif()
 endif()

-# check if the root changed against the previous defined one, if so
-# clear all the cached variables
+# check if the root changed wrt. the previous defined one, if so
+# clear all the cached variables for being able to reconfigure properly
 if(DEFINED Matlab_ROOT_DIR_LAST_CACHED)

   if(NOT Matlab_ROOT_DIR_LAST_CACHED STREQUAL Matlab_ROOT_DIR)
     set(_Matlab_cached_vars
+        Matlab_VERSION_STRING
         Matlab_INCLUDE_DIRS
         Matlab_MEX_LIBRARY
         Matlab_MEX_COMPILER
+        Matlab_MCC_COMPILER
         Matlab_MAIN_PROGRAM
         Matlab_MX_LIBRARY
         Matlab_ENG_LIBRARY
+        Matlab_MAT_LIBRARY
+        Matlab_ENGINE_LIBRARY
+        Matlab_DATAARRAY_LIBRARY
         Matlab_MEX_EXTENSION
+        Matlab_SIMULINK_INCLUDE_DIR

         # internal
         Matlab_MEXEXTENSIONS_PROG
         Matlab_ROOT_DIR_LAST_CACHED
         #Matlab_PROG_VERSION_STRING_AUTO_DETECT
-        Matlab_VERSION_STRING_INTERNAL
+        #Matlab_VERSION_STRING_INTERNAL
         )
     foreach(_var IN LISTS _Matlab_cached_vars)
       if(DEFINED ${_var})
@@ -1235,18 +1522,18 @@
 # Fix the version, in case this one is NOTFOUND
 _Matlab_get_version_from_root(
   "${Matlab_ROOT_DIR}"
+  "${Matlab_Or_MCR}"
   ${Matlab_VERSION_STRING}
   Matlab_VERSION_STRING
 )

-
-
-
 if(MATLAB_FIND_DEBUG)
   message(STATUS "[MATLAB] Current version is ${Matlab_VERSION_STRING} located ${Matlab_ROOT_DIR}")
 endif()

-
+if(NOT ${Matlab_VERSION_STRING} VERSION_LESS "9.4") # MATLAB 9.4 (R2018a) and newer have a new C++ API
+  set(Matlab_HAS_CPP_API 1)
+endif()

 if(Matlab_ROOT_DIR)
   file(TO_CMAKE_PATH ${Matlab_ROOT_DIR} Matlab_ROOT_DIR)
@@ -1285,12 +1572,18 @@
     ${Matlab_ROOT_DIR}/bin/${_matlab_bin_prefix}${_matlab_current_suffix})
 set(Matlab_EXTERN_LIBRARY_DIR
     ${Matlab_ROOT_DIR}/extern/lib/${_matlab_bin_prefix}${_matlab_current_suffix})
+set(Matlab_EXTERN_BINARIES_DIR
+    ${Matlab_ROOT_DIR}/extern/bin/${_matlab_bin_prefix}${_matlab_current_suffix})

 if(WIN32)
-  set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/microsoft)
+  if(MINGW)
+    set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/mingw64)
+  else()
+    set(_matlab_lib_dir_for_search ${Matlab_EXTERN_LIBRARY_DIR}/microsoft)
+  endif()
   set(_matlab_lib_prefix_for_search "lib")
 else()
-  set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR})
+  set(_matlab_lib_dir_for_search ${Matlab_BINARIES_DIR} ${Matlab_EXTERN_BINARIES_DIR})
   set(_matlab_lib_prefix_for_search "lib")
 endif()

@@ -1341,8 +1634,6 @@
   PATHS ${_matlab_lib_dir_for_search}
   NO_DEFAULT_PATH
 )
-
-
 list(APPEND _matlab_required_variables Matlab_MEX_LIBRARY)

 # the MEX extension is required
@@ -1350,7 +1641,6 @@

 # the matlab root is required
 list(APPEND _matlab_required_variables Matlab_ROOT_DIR)
-

 # component Mex Compiler
 list(FIND Matlab_FIND_COMPONENTS MEX_COMPILER _matlab_find_mex_compiler)
@@ -1362,7 +1652,6 @@
     DOC "Matlab MEX compiler"
     NO_DEFAULT_PATH
   )
-
   if(Matlab_MEX_COMPILER)
     set(Matlab_MEX_COMPILER_FOUND TRUE)
   endif()
@@ -1372,7 +1661,6 @@
 # component Matlab program
 list(FIND Matlab_FIND_COMPONENTS MAIN_PROGRAM _matlab_find_matlab_program)
 if(_matlab_find_matlab_program GREATER -1)
-
   find_program(
     Matlab_MAIN_PROGRAM
     matlab
@@ -1380,31 +1668,24 @@
     DOC "Matlab main program"
     NO_DEFAULT_PATH
   )
-
   if(Matlab_MAIN_PROGRAM)
     set(Matlab_MAIN_PROGRAM_FOUND TRUE)
   endif()
-
 endif()
 unset(_matlab_find_matlab_program)

-# Component MX library
-list(FIND Matlab_FIND_COMPONENTS MX_LIBRARY _matlab_find_mx)
-if(_matlab_find_mx GREATER -1)
-  _Matlab_find_library(
-    ${_matlab_lib_prefix_for_search}
-    Matlab_MX_LIBRARY
-    mx
-    PATHS ${_matlab_lib_dir_for_search}
-    NO_DEFAULT_PATH
-  )
-
-  if(Matlab_MX_LIBRARY)
-    set(Matlab_MX_LIBRARY_FOUND TRUE)
-  endif()
-endif()
-unset(_matlab_find_mx)
-
+# The MX library is required
+_Matlab_find_library(
+  ${_matlab_lib_prefix_for_search}
+  Matlab_MX_LIBRARY
+  mx
+  PATHS ${_matlab_lib_dir_for_search}
+  NO_DEFAULT_PATH
+)
+list(APPEND _matlab_required_variables Matlab_MX_LIBRARY)
+if(Matlab_MX_LIBRARY)
+  set(Matlab_MX_LIBRARY_FOUND TRUE)
+endif()

 # Component ENG library
 list(FIND Matlab_FIND_COMPONENTS ENG_LIBRARY _matlab_find_eng)
@@ -1422,15 +1703,92 @@
 endif()
 unset(_matlab_find_eng)

-
-
-
+# Component MAT library
+list(FIND Matlab_FIND_COMPONENTS MAT_LIBRARY _matlab_find_mat)
+if(_matlab_find_mat GREATER -1)
+  _Matlab_find_library(
+    ${_matlab_lib_prefix_for_search}
+    Matlab_MAT_LIBRARY
+    mat
+    PATHS ${_matlab_lib_dir_for_search}
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MAT_LIBRARY)
+    set(Matlab_MAT_LIBRARY_FOUND TRUE)
+  endif()
+endif()
+unset(_matlab_find_mat)
+
+# Component Simulink
+list(FIND Matlab_FIND_COMPONENTS SIMULINK _matlab_find_simulink)
+if(_matlab_find_simulink GREATER -1)
+  find_path(
+    Matlab_SIMULINK_INCLUDE_DIR
+    simstruc.h
+    PATHS "${Matlab_ROOT_DIR}/simulink/include"
+    NO_DEFAULT_PATH
+    )
+  if(Matlab_SIMULINK_INCLUDE_DIR)
+    set(Matlab_SIMULINK_FOUND TRUE)
+    list(APPEND Matlab_INCLUDE_DIRS "${Matlab_SIMULINK_INCLUDE_DIR}")
+  endif()
+endif()
+unset(_matlab_find_simulink)
+
+# component MCC Compiler
+list(FIND Matlab_FIND_COMPONENTS MCC_COMPILER _matlab_find_mcc_compiler)
+if(_matlab_find_mcc_compiler GREATER -1)
+  find_program(
+    Matlab_MCC_COMPILER
+    "mcc"
+    PATHS ${Matlab_BINARIES_DIR}
+    DOC "Matlab MCC compiler"
+    NO_DEFAULT_PATH
+  )
+  if(Matlab_MCC_COMPILER)
+    set(Matlab_MCC_COMPILER_FOUND TRUE)
+  endif()
+endif()
+unset(_matlab_find_mcc_compiler)
+
+if(Matlab_HAS_CPP_API)
+
+  # The MatlabEngine library is required for R2018a+
+  _Matlab_find_library(
+    ${_matlab_lib_prefix_for_search}
+    Matlab_ENGINE_LIBRARY
+    MatlabEngine
+    PATHS ${_matlab_lib_dir_for_search}
+    DOC "MatlabEngine Library"
+    NO_DEFAULT_PATH
+  )
+  list(APPEND _matlab_required_variables Matlab_ENGINE_LIBRARY)
+  if(Matlab_ENGINE_LIBRARY)
+    set(Matlab_ENGINE_LIBRARY_FOUND TRUE)
+  endif()
+
+  # The MatlabDataArray library is required for R2018a+
+  _Matlab_find_library(
+    ${_matlab_lib_prefix_for_search}
+    Matlab_DATAARRAY_LIBRARY
+    MatlabDataArray
+    PATHS ${_matlab_lib_dir_for_search}
+    DOC "MatlabDataArray Library"
+    NO_DEFAULT_PATH
+  )
+  list(APPEND _matlab_required_variables Matlab_DATAARRAY_LIBRARY)
+  if(Matlab_DATAARRAY_LIBRARY)
+    set(Matlab_DATAARRAY_LIBRARY_FOUND TRUE)
+  endif()
+
+endif()

 unset(_matlab_lib_dir_for_search)

-
-set(Matlab_LIBRARIES ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY} ${Matlab_ENG_LIBRARY})
-
+set(Matlab_LIBRARIES
+  ${Matlab_MEX_LIBRARY} ${Matlab_MX_LIBRARY}
+  ${Matlab_ENG_LIBRARY} ${Matlab_MAT_LIBRARY}
+  ${Matlab_DATAARRAY_LIBRARY} ${Matlab_ENGINE_LIBRARY})

 find_package_handle_standard_args(
   Matlab
@@ -1449,18 +1807,16 @@

 if(Matlab_INCLUDE_DIRS AND Matlab_LIBRARIES)
   mark_as_advanced(
-    #Matlab_LIBRARIES
     Matlab_MEX_LIBRARY
     Matlab_MX_LIBRARY
     Matlab_ENG_LIBRARY
+    Matlab_ENGINE_LIBRARY
+    Matlab_DATAARRAY_LIBRARY
+    Matlab_MAT_LIBRARY
     Matlab_INCLUDE_DIRS
     Matlab_FOUND
-    #Matlab_ROOT_DIR
-    #Matlab_VERSION_STRING
     Matlab_MAIN_PROGRAM
-    #Matlab_MEX_EXTENSION
     Matlab_MEXEXTENSIONS_PROG
     Matlab_MEX_EXTENSION
-    #Matlab_BINARIES_DIR
   )
 endif()


remove unused zeromq cmake macros

remove unused zeromq cmake macros

--- cmake/FindZeroMQ.cmake
+++ cmake/FindZeroMQ.cmake
@@ -1,41 +0,0 @@
-# - Try to find libzmq
-# Once done, this will define
-#
-#  ZeroMQ_FOUND - system has libzmq
-#  ZeroMQ_INCLUDE_DIRS - the libzmq include directories
-#  ZeroMQ_LIBRARIES - link these to use libzmq
-
-include(LibFindMacros)
-
-IF (UNIX)
-	# Use pkg-config to get hints about paths
-	libfind_pkg_check_modules(ZeroMQ_PKGCONF libzmq)
-
-	# Include dir
-	find_path(ZeroMQ_INCLUDE_DIR
-	  NAMES zmq.hpp
-	  PATHS ${ZEROMQ_ROOT}/include ${ZeroMQ_PKGCONF_INCLUDE_DIRS}
-	)
-
-	# Finally the library itself
-	find_library(ZeroMQ_LIBRARY
-	  NAMES zmq
-	  PATHS ${ZEROMQ_ROOT}/lib ${ZeroMQ_PKGCONF_LIBRARY_DIRS}
-	)
-ELSEIF (WIN32)
-	find_path(ZeroMQ_INCLUDE_DIR
-	  NAMES zmq.hpp
-	  PATHS ${ZEROMQ_ROOT}/include ${CMAKE_INCLUDE_PATH}
-	)
-	# Finally the library itself
-	find_library(ZeroMQ_LIBRARY
-	  NAMES libzmq
-	  PATHS ${ZEROMQ_ROOT}/lib ${CMAKE_LIB_PATH}
-	)
-ENDIF()
-
-# Set the include dir variables and the libraries and let libfind_process do the rest.
-# NOTE: Singular variables for this library, plural for libraries this this lib depends on.
-set(ZeroMQ_PROCESS_INCLUDES ZeroMQ_INCLUDE_DIR ZeroMQ_INCLUDE_DIRS)
-set(ZeroMQ_PROCESS_LIBS ZeroMQ_LIBRARY ZeroMQ_LIBRARIES)
-libfind_process(ZeroMQ)


Fix tbb on MinGW-w64

Fix tbb on MinGW-w64

--- cmake/TaichiCore.cmake
+++ cmake/TaichiCore.cmake
@@ -77,11 +77,18 @@
 if (WIN32)
     set_target_properties(${CORE_LIBRARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
             "${CMAKE_CURRENT_SOURCE_DIR}/runtimes")
-    target_link_libraries(${CORE_LIBRARY_NAME}
-      ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/embree.lib
-      ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbb.lib
-      ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbbmalloc.lib
-    )
+    if (MSVC)
+        target_link_libraries(${CORE_LIBRARY_NAME}
+          ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/embree.lib
+          ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbb.lib
+          ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbbmalloc.lib
+        )
+    else ()
+        target_link_libraries(${CORE_LIBRARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/embree.lib)
+        target_link_libraries(${CORE_LIBRARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbb.dll)
+        target_link_libraries(${CORE_LIBRARY_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/external/lib/tbbmalloc.dll)
+        target_link_libraries(${CORE_LIBRARY_NAME} ws2_32)
+    endif()
 endif ()

 include_directories(include)


Removed unused files.

Removed unused files.


COMP: Remove explicit dependency on MinimalPathExtraction module for itktubetk

--- ITKModules/TubeTKITK/itk-module.cmake
+++ ITKModules/TubeTKITK/itk-module.cmake
@@ -25,7 +25,7 @@

 itk_module( TubeTKITK
   DEPENDS
-    ITKCommon ITKSpatialObjects MinimalPathExtraction
+    ITKCommon ITKSpatialObjects
   EXCLUDE_FROM_DEFAULT
   DESCRIPTION
     "${DOCUMENTATION}"


PARQUET-1013: Fix ZLIB_INCLUDE_DIR

PARQUET-1013: Fix ZLIB_INCLUDE_DIR

Author: rip.nsk <rip.nsk@gmail.com>

Closes #347 from rip-nsk/PARQUET-1013 and squashes the following commits:

2aa8335 [rip.nsk] Fix ZLIB_INCLUDE_DIR

--- cmake_modules/ThirdpartyToolchain.cmake
+++ cmake_modules/ThirdpartyToolchain.cmake
@@ -133,7 +133,7 @@
 if (NOT ZLIB_FOUND)
   set(ZLIB_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/zlib_ep/src/zlib_ep-install")
   set(ZLIB_HOME "${ZLIB_PREFIX}")
-  set(ZLIB_INCLUDE_DIRS "${ZLIB_PREFIX}/include")
+  set(ZLIB_INCLUDE_DIR "${ZLIB_PREFIX}/include")
   if (MSVC)
     if (${UPPERCASE_BUILD_TYPE} STREQUAL "DEBUG")
       set(ZLIB_STATIC_LIB_NAME zlibstaticd.lib)
@@ -161,7 +161,7 @@
   set(ZLIB_VENDORED 0)
 endif()

-include_directories(SYSTEM ${ZLIB_INCLUDE_DIRS})
+include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
 add_library(zlibstatic STATIC IMPORTED)
 set_target_properties(zlibstatic PROPERTIES IMPORTED_LOCATION ${ZLIB_STATIC_LIB})

@@ -217,7 +217,7 @@

     set(THRIFT_CMAKE_ARGS "-DFLEX_EXECUTABLE=${WINFLEXBISON_PREFIX}/win_flex.exe"
                           "-DBISON_EXECUTABLE=${WINFLEXBISON_PREFIX}/win_bison.exe"
-                          "-DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIRS}"
+                          "-DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR}"
                           "-DZLIB_LIBRARY=${ZLIB_STATIC_LIB}"
                           "-DWITH_SHARED_LIB=OFF"
                           "-DWITH_PLUGIN=OFF"


turn on warnings by default

turn on warnings by default

--- components/ospcommon/cmake/macros.cmake
+++ components/ospcommon/cmake/macros.cmake
@@ -336,7 +336,7 @@
   # unhide compiler to make it easier for users to see what they are using
   MARK_AS_ADVANCED(CLEAR CMAKE_CXX_COMPILER)

-  OPTION(OSPRAY_STRICT_BUILD "Build with additional warning flags" OFF)
+  OPTION(OSPRAY_STRICT_BUILD "Build with additional warning flags" ON)
   MARK_AS_ADVANCED(OSPRAY_STRICT_BUILD)

   OPTION(OSPRAY_WARN_AS_ERRORS "Treat warnings as errors" OFF)


Allow custom config location

Allow custom config location

--- common.cmake
+++ common.cmake
@@ -7,4 +7,5 @@
 HunterGate(
     URL "https://github.com/ruslo/hunter/archive/android-005.tar.gz"
     SHA1 "a26088094228c90f748c41e003c6496a858a5f17"
+    ${CONFIG_FILE}
 )


workaround for execute_process: stderr intermangled with stdout (stderr printed separately after execute_process)

--- src/cake.cmake
+++ src/cake.cmake
@@ -523,9 +523,14 @@
 			execute_process(COMMAND
 				${cmake_command_line}
 				RESULT_VARIABLE r
+				ERROR_VARIABLE e
 			)
+			if(e)
+				cake_message(STATUS "STDERR from the previous CMake configuration/generation run:")
+				cake_message("${e}")
+			endif()
 			if(r)
-				cake_message(FATAL_ERROR "CMake generate step failed.")
+				cake_message(FATAL_ERROR "CMake generate step failed, result: ${r}.")
 			endif()
 		endif()
 	endforeach()
@@ -611,9 +616,14 @@
 			execute_process(COMMAND
 				${cmake_command_line}
 				RESULT_VARIABLE r
+				ERROR_VARIABLE e
 			)
+			if(e)
+				cake_message(STATUS "STDERR from the previous CMake build run:")
+				cake_message("${e}")
+			endif()
 			if(r)
-				cake_message(FATAL_ERROR "CMake build step failed.")
+				cake_message(FATAL_ERROR "CMake build step failed, result: ${r}.")
 			endif()
 		endforeach()
 	endforeach()


New boost version

New boost version

--HG--
branch : v1-9


Dependencies: make sure local freetype does not pull brotli

--- CMake/Dependencies.cmake
+++ CMake/Dependencies.cmake
@@ -100,6 +100,7 @@
             -DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE # disable third-party deps
             -DCMAKE_DISABLE_FIND_PACKAGE_HarfBuzz=TRUE
             -DCMAKE_DISABLE_FIND_PACKAGE_BZip2=TRUE
+            -DCMAKE_DISABLE_FIND_PACKAGE_BrotliDec=TRUE
             # workaround for broken iOS toolchain in freetype
             -DPROJECT_SOURCE_DIR=${PROJECT_BINARY_DIR}/freetype-2.12.1
             ${PROJECT_BINARY_DIR}/freetype-2.12.1


removed TomoPhantom

removed TomoPhantom

--- SuperBuild/External_CCPi-Framework.cmake
+++ SuperBuild/External_CCPi-Framework.cmake
@@ -22,7 +22,7 @@
 set(proj CCPi-Framework)

 # Set dependency list
-set(${proj}_DEPENDENCIES "TomoPhantom")
+set(${proj}_DEPENDENCIES "")

 # Include dependent projects if any
 ExternalProject_Include_Dependencies(${proj} DEPENDS_VAR ${proj}_DEPENDENCIES)


enh: Optional basis_add_export_target argument can be boolean FALSE [BASIS]

--- CMake/Basis/ExportTools.cmake
+++ CMake/Basis/ExportTools.cmake
@@ -35,20 +35,30 @@
 #
 # @param[out] EXPORT_OPTION Export option for install() command including
 #                           the EXPORT option name. Set to an empty string
-#                           if target is not installed.
+#                           if target is not installed (see @p ARGN).
 # @param[in]  TARGET_UID    UID of target to be exported.
 # @param[in]  IS_TEST       Whether given target is a test executable or library.
-# @param[in]  ARGN          Optional installation destinations.
+# @param[in]  ARGN          Optional installation destinations. The actual
+#                           values are ignored and argument @c TRUE should
+#                           be used if no specific destination paths are given,
+#                           but the target is also to be included in the export
+#                           set used for installation. If ARGN is empty, the
+#                           target is only added to the build tree export set.
+#                           When @p ARGN is @c 0, @c FALSE or @c OFF, the target
+#                           is not added to list of installation exports.
 function (basis_add_export_target EXPORT_OPTION TARGET_UID IS_TEST)
   set (EXPORT_SET "${TOPLEVEL_PROJECT_NAME}")
   if (IS_TEST)
     basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY TEST_EXPORT_TARGETS "${TARGET_UID}")
+    set (${EXPORT_OPTION} "" PARENT_SCOPE)
   else ()
     basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY EXPORT_TARGETS "${TARGET_UID}")
-    if (ARGN)
+    if (ARGN AND NOT "^${ARGN}$" STREQUAL "^(0|false|FALSE|off|OFF)$")
       basis_set_project_property (PROJECT "${EXPORT_SET}" APPEND PROPERTY INSTALL_EXPORT_TARGETS "${TARGET_UID}")
-    endif ()
-    set (${EXPORT_OPTION} "EXPORT;${EXPORT_SET}" PARENT_SCOPE)
+      set (${EXPORT_OPTION} "EXPORT;${EXPORT_SET}" PARENT_SCOPE)
+    else ()
+      set (${EXPORT_OPTION} "" PARENT_SCOPE)
+    endif ()
   endif ()
 endfunction ()


Support Clang flags and warnings

Support Clang flags and warnings

--- CMakeModules/BaseConfig.cmake
+++ CMakeModules/BaseConfig.cmake
@@ -1,12 +1,12 @@
 IF(NOT CMAKE_BUILD_TYPE)
-    set(CMAKE_BUILD_TYPE Debug)
-  # SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
-      # "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
-      # FORCE)
+    # set(CMAKE_BUILD_TYPE Debug)
+  SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
+      "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel."
+      FORCE)
 ENDIF(NOT CMAKE_BUILD_TYPE)

-if(CMAKE_COMPILER_IS_GNUCC)
-    SET(RSN_BASE_C_FLAGS "-std=c99 -pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter")
+if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    SET(RSN_BASE_C_FLAGS "-std=c99 -pedantic -Wall -Wextra -Wstrict-prototypes -Wno-unused-parameter -Werror -Wno-newline-eof")
     SET(RSN_BASE_CXX_FLAGS "-Wall")

     SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${RSN_BASE_C_FLAGS} -DLUA_USE_MKSTEMP")
@@ -39,4 +39,4 @@
         SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDEBUG -g3")
     ENDIF(${CMAKE_BUILD_TYPE} STREQUAL Debug)

-endif(CMAKE_COMPILER_IS_GNUCC)
+endif(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG)


move mitkIOUtilTest to cmake module test to run it on the dashboard

--- Core/Code/Testing/files.cmake
+++ Core/Code/Testing/files.cmake
@@ -17,6 +17,7 @@
   mitkImageEqualTest.cpp
   mitkImageDataItemTest.cpp
   mitkImageGeneratorTest.cpp
+  mitkIOUtilTest.cpp
   mitkBaseDataTest.cpp
   mitkImportItkImageTest.cpp
   mitkGrabItkImageMemoryTest.cpp
@@ -131,7 +132,6 @@
     mitkImageVtkMapper2DSwivelTest.cpp
     mitkImageVtkMapper2DTransferFunctionTest.cpp
     mitkImageVtkMapper2DLookupTableTest.cpp
-    mitkIOUtilTest.cpp
     mitkSurfaceVtkMapper3DTest
     mitkSurfaceVtkMapper3DTexturedSphereTest.cpp
     mitkSurfaceGLMapper2DColorTest.cpp


fix: Add support for more ARM processors detection (#608)

Internal change submitted. Merging this PR.
The unit test can be fixed in another PR.

--- absl/copts/AbseilConfigureCopts.cmake
+++ absl/copts/AbseilConfigureCopts.cmake
@@ -11,7 +11,7 @@
   else()
     set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_X64_FLAGS}")
   endif()
-elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "arm")
+elseif("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "arm.*|aarch64")
   if ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
     set(ABSL_RANDOM_RANDEN_COPTS "${ABSL_RANDOM_HWAES_ARM64_FLAGS}")
   elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")


COMP: Remove fragile ITKv3 conditionals

COMP: Remove fragile ITKv3 conditionals

DTIReg now builds under ITKv4 consistently and
the ITKv3 conditional compilation was failing
for some uses.

--- DTIReg.cmake
+++ DTIReg.cmake
@@ -11,16 +11,7 @@
   )

 #-----------------------------------------------------------------------------
-set(expected_ITK_VERSION_MAJOR ${ITK_VERSION_MAJOR})
-find_package(ITK NO_MODULE REQUIRED)
-if(${ITK_VERSION_MAJOR} VERSION_LESS ${expected_ITK_VERSION_MAJOR})
-  # Note: Since ITKv3 doesn't include a ITKConfigVersion.cmake file, let's check the version
-  #       explicitly instead of passing the version as an argument to find_package() command.
-  message(FATAL_ERROR "Could not find a configuration file for package \"ITK\" that is compatible "
-                      "with requested version \"${expected_ITK_VERSION_MAJOR}\".\n"
-                      "The following configuration files were considered but not accepted:\n"
-                      "  ${ITK_CONFIG}, version: ${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}\n")
-endif()
+find_package(ITK 4 NO_MODULE REQUIRED)

 include(${ITK_USE_FILE})


boards: nxp/fmurt1062-v1 disable vmount

boards: nxp/fmurt1062-v1 disable vmount

--- boards/nxp/fmurt1062-v1/default.cmake
+++ boards/nxp/fmurt1062-v1/default.cmake
@@ -73,7 +73,7 @@
 		sensors
 		sih
 		temperature_compensation
-		vmount
+		#vmount
 	SYSTEMCMDS
 #		bl_update
 		dmesg


Add warning for common user error

Add warning for common user error

--- Common.cmake
+++ Common.cmake
@@ -8,6 +8,10 @@
 # Output Variables
 # * COMMON_INCLUDES: generated include files (version, defines, api)
 # * COMMON_SOURCES: generated cpp files (version)
+
+if(CMAKE_INSTALL_PREFIX STREQUAL CMAKE_BINARY_DIR)
+  message(FATAL_ERROR "Cannot install into build directory")
+endif()

 cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
 if(CMAKE_VERSION VERSION_LESS 2.8.3)


fix c++17 building on windows

fix c++17 building on windows

--- build/cmake/DefineCMakeDefaults.cmake
+++ build/cmake/DefineCMakeDefaults.cmake
@@ -79,3 +79,14 @@
 if (NOT DEFINED CMAKE_CXX_EXTENSIONS)
   set(CMAKE_CXX_EXTENSIONS OFF)        # use standards compliant language level for portability
 endif()
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
+  include(CheckCXXCompilerFlag)
+  set(CMAKE_REQUIRED_QUIET ON)
+  check_cxx_compiler_flag("/Zc:__cplusplus" res_var)
+  if (res_var)
+    # Make MSVC reporting correct value for __cplusplus
+    # See https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/
+    add_compile_options("/Zc:__cplusplus")
+  endif()
+endif()


Update iOS demo build to use resources from 'scenes/'

--- toolchains/iOS.cmake
+++ toolchains/iOS.cmake
@@ -42,6 +42,7 @@
 endforeach()

 add_bundle_resources(RESOURCES "${PROJECT_SOURCE_DIR}/core/resources" "${EXECUTABLE_NAME}.app")
+add_bundle_resources(RESOURCES "${PROJECT_SOURCE_DIR}/scenes" "${EXECUTABLE_NAME}.app")

 file(GLOB_RECURSE IOS_RESOURCES ${PROJECT_SOURCE_DIR}/ios/resources/**)
 string(REGEX REPLACE "[.]DS_Store" "" IOS_RESOURCES "${IOS_RESOURCES}")