From 30b873c05d6281b865ba08524bb1b90e0afd1ece Mon Sep 17 00:00:00 2001
From: Marc Chevrier <marc.chevrier@gmail.com>
Date: Sat, 4 May 2019 17:09:31 +0200
Subject: FindPython*: Manage weak link for Python modules

Add new target Python::Module which take care of platform requirements
for Python module development.

Fixes: #18100
---
 Help/release/dev/FindPython-module.rst             |   6 +
 Modules/FindPython.cmake                           |  12 +-
 Modules/FindPython/Support.cmake                   | 161 +++++++++++++--------
 Modules/FindPython2.cmake                          |  14 +-
 Modules/FindPython3.cmake                          |  14 +-
 Tests/FindPython/CMakeLists.txt                    |  22 +++
 Tests/FindPython/Python/CMakeLists.txt             |   3 +
 Tests/FindPython/Python2/CMakeLists.txt            |   3 +
 Tests/FindPython/Python2Embedded/CMakeLists.txt    |  29 ++++
 Tests/FindPython/Python3/CMakeLists.txt            |   3 +
 Tests/FindPython/Python3Embedded/CMakeLists.txt    |  29 ++++
 Tests/FindPython/display_time.c                    |  36 +++++
 Tests/FindPython/display_time.h                    |   2 +
 Tests/FindPython/main.c                            |   7 +
 Tests/RunCMake/UseSWIG/CMP0086-common.cmake        |   2 +-
 Tests/UseSWIG/ModuleName/CMakeLists.txt            |   2 +-
 Tests/UseSWIG/ModuleVersion2/CMakeLists.txt        |   4 +-
 Tests/UseSWIG/MultipleModules/CMakeLists.txt       |   2 +-
 Tests/UseSWIG/MultiplePython/CMakeLists.txt        |   4 +-
 Tests/UseSWIG/SwigSrcFileExtension/CMakeLists.txt  |   4 +-
 .../UseTargetINCLUDE_DIRECTORIES/CMakeLists.txt    |   4 +-
 21 files changed, 275 insertions(+), 88 deletions(-)
 create mode 100644 Help/release/dev/FindPython-module.rst
 create mode 100644 Tests/FindPython/Python2Embedded/CMakeLists.txt
 create mode 100644 Tests/FindPython/Python3Embedded/CMakeLists.txt
 create mode 100644 Tests/FindPython/display_time.c
 create mode 100644 Tests/FindPython/display_time.h
 create mode 100644 Tests/FindPython/main.c

diff --git a/Help/release/dev/FindPython-module.rst b/Help/release/dev/FindPython-module.rst
new file mode 100644
index 0000000..79ff9d8
--- /dev/null
+++ b/Help/release/dev/FindPython-module.rst
@@ -0,0 +1,6 @@
+FindPython-module
+-----------------
+
+* Modules :module:`FindPython`, :module:`FindPython2` and :module:`FindPython3`
+  gain a new target (respectively ``Python::Module``, ``Python2::Module``
+  and ``Python3::Module``) which can be used to develop Python modules.
diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake
index c5074e8..36c0611 100644
--- a/Modules/FindPython.cmake
+++ b/Modules/FindPython.cmake
@@ -46,7 +46,11 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
 ``Python::Compiler``
   Python compiler. Target defined if component ``Compiler`` is found.
 ``Python::Python``
-  Python library. Target defined if component ``Development`` is found.
+  Python library for Python embedding. Target defined if component
+  ``Development`` is found.
+``Python::Module``
+  Python library for Python module. Target defined if component ``Development``
+  is found.
 ``Python::NumPy``
   NumPy Python library. Target defined if component ``NumPy`` is found.
 
@@ -175,9 +179,9 @@ Commands
 
 This module defines the command ``Python_add_library`` (when
 :prop_gbl:`CMAKE_ROLE` is ``PROJECT``), which has the same semantics as
-:command:`add_library`, but takes care of Python module naming rules
-(only applied if library is of type ``MODULE``), and adds a dependency to target
-``Python::Python``::
+:command:`add_library` and adds a dependency to target ``Python::Python`` or,
+when library type is ``MODULE``, to target ``Python::Module`` and takes care of
+Python module naming rules::
 
   Python_add_library (my_module MODULE src1.cpp)
 
diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake
index 6572fb8..6d709e1 100644
--- a/Modules/FindPython/Support.cmake
+++ b/Modules/FindPython/Support.cmake
@@ -1253,72 +1253,104 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
   endif()
 
   if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
-      AND ${_PYTHON_PREFIX}_Development_FOUND AND NOT TARGET ${_PYTHON_PREFIX}::Python)
+      AND ${_PYTHON_PREFIX}_Development_FOUND)
 
-    if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
-        OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
-        OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
-      set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED)
-    else()
-      set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC)
-    endif()
-
-    add_library (${_PYTHON_PREFIX}::Python ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED)
-
-    set_property (TARGET ${_PYTHON_PREFIX}::Python
-                  PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
-
-    if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
-        OR (${_PYTHON_PREFIX}_LIBRARY_DEBUG AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG))
-      # System manage shared libraries in two parts: import and runtime
-      if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
-        set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
-                                          IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}"
-                                          IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
-                                          IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}"
-                                          IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+    macro (__PYTHON_IMPORT_LIBRARY __name)
+      if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+          OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+          OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+        set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED)
       else()
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
-                                          IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}"
-                                          IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}")
+        set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC)
       endif()
-    else()
-      if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
-        set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
-                                          IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
-                                          IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
+
+      add_library (${__name} ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED)
+
+      set_property (TARGET ${__name}
+                    PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+      if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
+          OR (${_PYTHON_PREFIX}_LIBRARY_DEBUG AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG))
+        # System manage shared libraries in two parts: import and runtime
+        if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+          set_property (TARGET ${__name} PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+                                            IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}"
+                                            IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+                                            IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}"
+                                            IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+        else()
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+                                            IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}"
+                                            IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}")
+        endif()
       else()
-        set_target_properties (${_PYTHON_PREFIX}::Python
-                               PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
-                                          IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}")
+        if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+          set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+                                            IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+                                            IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
+        else()
+          set_target_properties (${__name}
+                                 PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+                                            IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}")
+        endif()
       endif()
+
+      if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC")
+        # extend link information with dependent libraries
+        execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+                         RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                         OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+                         ERROR_QUIET
+                         OUTPUT_STRIP_TRAILING_WHITESPACE)
+        if (NOT _${_PYTHON_PREFIX}_RESULT)
+          string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}")
+          # remove elements relative to python library itself
+          list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython")
+          foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS)
+            list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}")
+          endforeach()
+          set_property (TARGET ${__name}
+                        PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES})
+        endif()
+      endif()
+    endmacro()
+
+    if (NOT TARGET ${_PYTHON_PREFIX}::Python)
+      __python_import_library (${_PYTHON_PREFIX}::Python)
     endif()
 
-    if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC")
-      # extend link information with dependent libraries
-      execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
-                       RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
-                       OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
-                       ERROR_QUIET
-                       OUTPUT_STRIP_TRAILING_WHITESPACE)
-      if (NOT _${_PYTHON_PREFIX}_RESULT)
-        string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}")
-        # remove elements relative to python library itself
-        list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython")
-        foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS)
-          list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}")
-        endforeach()
-        set_property (TARGET ${_PYTHON_PREFIX}::Python
-                      PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES})
+    if (NOT TARGET ${_PYTHON_PREFIX}::Module)
+      if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$")
+        # On Windows/CYGWIN/MSYS, Python::Module is the same as Python::Python
+        # but ALIAS cannot be used because the imported library is not GLOBAL.
+        __python_import_library (${_PYTHON_PREFIX}::Module)
+      else()
+        add_library (${_PYTHON_PREFIX}::Module INTERFACE IMPORTED)
+        set_property (TARGET ${_PYTHON_PREFIX}::Module
+                      PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+        # When available, enforce shared library generation with undefined symbols
+        if (APPLE)
+          set_property (TARGET ${_PYTHON_PREFIX}::Module
+                        PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup")
+        endif()
+        if (CMAKE_SYSTEM_NAME STREQUAL "SunOS")
+          set_property (TARGET ${_PYTHON_PREFIX}::Module
+                        PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-z,nodefs")
+         endif()
+        if (CMAKE_SYSTEM_NAME STREQUAL "AIX")
+          set_property (TARGET ${_PYTHON_PREFIX}::Module
+                        PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-b,erok")
+         endif()
       endif()
     endif()
 
@@ -1328,7 +1360,7 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
     #
     function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name)
       cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY
-                             "STATIC;SHARED;MODULE" "" "")
+        "STATIC;SHARED;MODULE" "" "")
 
       unset (type)
       if (NOT (PYTHON_ADD_LIBRARY_STATIC
@@ -1337,15 +1369,18 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
         set (type MODULE)
       endif()
       add_library (${name} ${type} ${ARGN})
-      target_link_libraries (${name} PRIVATE ${prefix}::Python)
 
-      # customize library name to follow module name rules
       get_property (type TARGET ${name} PROPERTY TYPE)
+
       if (type STREQUAL "MODULE_LIBRARY")
+        target_link_libraries (${name} PRIVATE ${prefix}::Module)
+        # customize library name to follow module name rules
         set_property (TARGET ${name} PROPERTY PREFIX "")
         if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
           set_property (TARGET ${name} PROPERTY SUFFIX ".pyd")
         endif()
+      else()
+        target_link_libraries (${name} PRIVATE ${prefix}::Python)
       endif()
     endfunction()
   endif()
@@ -1355,7 +1390,7 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
     add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED)
     set_property (TARGET ${_PYTHON_PREFIX}::NumPy
                   PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
-    target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Python)
+    target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module)
   endif()
 endif()
 
diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake
index a2be84f..67499d8 100644
--- a/Modules/FindPython2.cmake
+++ b/Modules/FindPython2.cmake
@@ -47,7 +47,11 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
 ``Python2::Compiler``
   Python 2 compiler. Target defined if component ``Compiler`` is found.
 ``Python2::Python``
-  Python 2 library. Target defined if component ``Development`` is found.
+  Python 2 library for Python embedding. Target defined if component
+  ``Development`` is found.
+``Python2::Module``
+  Python 2 library for Python module. Target defined if component
+  ``Development`` is found.
 ``Python2::NumPy``
   NumPy library for Python 2. Target defined if component ``NumPy`` is found.
 
@@ -174,11 +178,11 @@ Hints
 Commands
 ^^^^^^^^
 
-This module defines the command ``Python2_add_library`` (when
+This module defines the command ``Python_add_library`` (when
 :prop_gbl:`CMAKE_ROLE` is ``PROJECT``), which has the same semantics as
-:command:`add_library`, but takes care of Python module naming rules
-(only applied if library is of type ``MODULE``), and adds a dependency to target
-``Python2::Python``::
+:command:`add_library` and adds a dependency to target ``Python2::Python`` or,
+when library type is ``MODULE``, to target ``Python2::Module`` and takes care
+of Python module naming rules::
 
   Python2_add_library (my_module MODULE src1.cpp)
 
diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake
index 3409554..fdb99a6 100644
--- a/Modules/FindPython3.cmake
+++ b/Modules/FindPython3.cmake
@@ -47,7 +47,11 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
 ``Python3::Compiler``
   Python 3 compiler. Target defined if component ``Compiler`` is found.
 ``Python3::Python``
-  Python 3 library. Target defined if component ``Development`` is found.
+  Python 3 library for Python embedding. Target defined if component
+  ``Development`` is found.
+``Python3::Module``
+  Python 3 library for Python module. Target defined if component
+  ``Development`` is found.
 ``Python3::NumPy``
   NumPy library for Python 3. Target defined if component ``NumPy`` is found.
 
@@ -174,11 +178,11 @@ Hints
 Commands
 ^^^^^^^^
 
-This module defines the command ``Python3_add_library`` (when
+This module defines the command ``Python_add_library`` (when
 :prop_gbl:`CMAKE_ROLE` is ``PROJECT``), which has the same semantics as
-:command:`add_library`, but takes care of Python module naming rules
-(only applied if library is of type ``MODULE``), and adds a dependency to target
-``Python3::Python``::
+:command:`add_library` and adds a dependency to target ``Python3::Python`` or,
+when library type is ``MODULE``, to target ``Python3::Module`` and takes care
+of Python module naming rules::
 
   Python3_add_library (my_module MODULE src1.cpp)
 
diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt
index d6f50e7..8dfcf40 100644
--- a/Tests/FindPython/CMakeLists.txt
+++ b/Tests/FindPython/CMakeLists.txt
@@ -79,6 +79,28 @@ if(CMake_TEST_FindPython)
     --build-options ${build_options}
     --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
     )
+
+  add_test(NAME FindPython.Python2Embedded COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python2Embedded"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python2Embedded"
+    ${build_generator_args}
+    --build-project TestPython2Embedded
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+  add_test(NAME FindPython.Python3Embedded COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python3Embedded"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python3Embedded"
+    ${build_generator_args}
+    --build-project TestPython3Embedded
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+
 endif()
 
 if(CMake_TEST_FindPython_NumPy)
diff --git a/Tests/FindPython/Python/CMakeLists.txt b/Tests/FindPython/Python/CMakeLists.txt
index f7fc243..62c805e 100644
--- a/Tests/FindPython/Python/CMakeLists.txt
+++ b/Tests/FindPython/Python/CMakeLists.txt
@@ -16,6 +16,9 @@ endif()
 if(NOT TARGET Python::Python)
   message(SEND_ERROR "Python::Python not found")
 endif()
+if(NOT TARGET Python::Module)
+  message(SEND_ERROR "Python::Module not found")
+endif()
 
 Python_add_library (spam3 MODULE ../spam.c)
 target_compile_definitions (spam3 PRIVATE PYTHON3)
diff --git a/Tests/FindPython/Python2/CMakeLists.txt b/Tests/FindPython/Python2/CMakeLists.txt
index a0753f6..274745a 100644
--- a/Tests/FindPython/Python2/CMakeLists.txt
+++ b/Tests/FindPython/Python2/CMakeLists.txt
@@ -21,6 +21,9 @@ endif()
 if(NOT TARGET Python2::Python)
   message(SEND_ERROR "Python2::Python not found")
 endif()
+if(NOT TARGET Python2::Module)
+  message(SEND_ERROR "Python2::Module not found")
+endif()
 
 Python2_add_library (spam2 MODULE ../spam.c)
 target_compile_definitions (spam2 PRIVATE PYTHON2)
diff --git a/Tests/FindPython/Python2Embedded/CMakeLists.txt b/Tests/FindPython/Python2Embedded/CMakeLists.txt
new file mode 100644
index 0000000..0115dea
--- /dev/null
+++ b/Tests/FindPython/Python2Embedded/CMakeLists.txt
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython2Embedded C)
+
+include(CTest)
+
+find_package(Python2 REQUIRED COMPONENTS Development)
+if (NOT Python2_FOUND)
+  message (FATAL_ERROR "Fail to found Python 2")
+endif()
+
+if(NOT TARGET Python2::Python)
+  message(SEND_ERROR "Python2::Python not found")
+endif()
+
+Python2_add_library (display_time2 SHARED ../display_time.c)
+set_property (TARGET display_time2 PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
+target_compile_definitions (display_time2 PRIVATE PYTHON2)
+
+add_executable (main2 ../main.c)
+target_link_libraries (main2 PRIVATE display_time2)
+
+if (WIN32 OR CYGWIN OR MSYS OR MINGW)
+  list (JOIN Python2_RUNTIME_LIBRARY_DIRS "$<SEMICOLON>" RUNTIME_DIRS)
+  add_test (NAME Python2.Embedded COMMAND "${CMAKE_COMMAND}" -E env "PATH=${RUNTIME_DIRS}" $<TARGET_FILE:main2>)
+else()
+  add_test (NAME Python2.Embedded COMMAND main2)
+endif()
+set_property (TEST Python2.Embedded PROPERTY PASS_REGULAR_EXPRESSION "Today is")
diff --git a/Tests/FindPython/Python3/CMakeLists.txt b/Tests/FindPython/Python3/CMakeLists.txt
index 65eea4c..b21a15b 100644
--- a/Tests/FindPython/Python3/CMakeLists.txt
+++ b/Tests/FindPython/Python3/CMakeLists.txt
@@ -21,6 +21,9 @@ endif()
 if(NOT TARGET Python3::Python)
   message(SEND_ERROR "Python2::Python not found")
 endif()
+if(NOT TARGET Python3::Module)
+  message(SEND_ERROR "Python2::Module not found")
+endif()
 
 Python3_add_library (spam3 MODULE ../spam.c)
 target_compile_definitions (spam3 PRIVATE PYTHON3)
diff --git a/Tests/FindPython/Python3Embedded/CMakeLists.txt b/Tests/FindPython/Python3Embedded/CMakeLists.txt
new file mode 100644
index 0000000..4eb7ebc
--- /dev/null
+++ b/Tests/FindPython/Python3Embedded/CMakeLists.txt
@@ -0,0 +1,29 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython3Embedded C)
+
+include(CTest)
+
+find_package(Python3 REQUIRED COMPONENTS Development)
+if (NOT Python3_FOUND)
+  message (FATAL_ERROR "Fail to found Python 3")
+endif()
+
+if(NOT TARGET Python3::Python)
+  message(SEND_ERROR "Python3::Python not found")
+endif()
+
+Python3_add_library (display_time3 SHARED ../display_time.c)
+set_property (TARGET display_time3 PROPERTY WINDOWS_EXPORT_ALL_SYMBOLS ON)
+target_compile_definitions (display_time3 PRIVATE PYTHON3)
+
+add_executable (main3 ../main.c)
+target_link_libraries (main3 PRIVATE display_time3)
+
+if (WIN32 OR CYGWIN OR MSYS OR MINGW)
+  list (JOIN Python3_RUNTIME_LIBRARY_DIRS "$<SEMICOLON>" RUNTIME_DIRS)
+  add_test (NAME Python3.Embedded COMMAND "${CMAKE_COMMAND}" -E env "PATH=${RUNTIME_DIRS}" $<TARGET_FILE:main3>)
+else()
+  add_test (NAME Python3.Embedded COMMAND main3)
+endif()
+set_property (TEST Python3.Embedded PROPERTY PASS_REGULAR_EXPRESSION "Today is")
diff --git a/Tests/FindPython/display_time.c b/Tests/FindPython/display_time.c
new file mode 100644
index 0000000..0e78434
--- /dev/null
+++ b/Tests/FindPython/display_time.c
@@ -0,0 +1,36 @@
+
+#include <stdio.h>
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#include "display_time.h"
+
+void display_time()
+{
+#if defined(PYTHON3)
+  wchar_t* program = Py_DecodeLocale("display_time", NULL);
+  if (program == NULL) {
+    fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
+    exit(1);
+  }
+  char* cmd = "from time import time,ctime\n"
+              "print('Today is', ctime(time()))\n";
+#else
+  char* program = "display_time";
+  char* cmd = "from time import time,ctime\n"
+              "print 'Today is', ctime(time())\n";
+#endif
+
+  Py_SetProgramName(program); /* optional but recommended */
+  Py_Initialize();
+  PyRun_SimpleString(cmd);
+#if defined(PYTHON3)
+  if (Py_FinalizeEx() < 0) {
+    exit(120);
+  }
+  PyMem_RawFree(program);
+#else
+  Py_Finalize();
+#endif
+}
diff --git a/Tests/FindPython/display_time.h b/Tests/FindPython/display_time.h
new file mode 100644
index 0000000..d825e02
--- /dev/null
+++ b/Tests/FindPython/display_time.h
@@ -0,0 +1,2 @@
+
+void display_time();
diff --git a/Tests/FindPython/main.c b/Tests/FindPython/main.c
new file mode 100644
index 0000000..0acba29
--- /dev/null
+++ b/Tests/FindPython/main.c
@@ -0,0 +1,7 @@
+
+#include "display_time.h"
+
+int main()
+{
+  display_time();
+}
diff --git a/Tests/RunCMake/UseSWIG/CMP0086-common.cmake b/Tests/RunCMake/UseSWIG/CMP0086-common.cmake
index c02592a..ef90218 100644
--- a/Tests/RunCMake/UseSWIG/CMP0086-common.cmake
+++ b/Tests/RunCMake/UseSWIG/CMP0086-common.cmake
@@ -8,4 +8,4 @@ include(UseSWIG)
 set_property (SOURCE example.i PROPERTY SWIG_MODULE_NAME "new_example")
 
 swig_add_library(example LANGUAGE python TYPE MODULE SOURCES example.i)
-target_link_libraries(example PRIVATE Python::Python)
+target_link_libraries(example PRIVATE Python::Module)
diff --git a/Tests/UseSWIG/ModuleName/CMakeLists.txt b/Tests/UseSWIG/ModuleName/CMakeLists.txt
index de63883..435b441 100644
--- a/Tests/UseSWIG/ModuleName/CMakeLists.txt
+++ b/Tests/UseSWIG/ModuleName/CMakeLists.txt
@@ -34,7 +34,7 @@ set_target_properties (example1 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1")
-target_link_libraries(example1 PRIVATE Python2::Python)
+target_link_libraries(example1 PRIVATE Python2::Module)
 
 
 add_test (NAME ModuleName.example1
diff --git a/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt b/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt
index a7ee210..093e858 100644
--- a/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt
+++ b/Tests/UseSWIG/ModuleVersion2/CMakeLists.txt
@@ -33,7 +33,7 @@ set_target_properties (example1 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2")
-target_link_libraries(example1 PRIVATE Python2::Python)
+target_link_libraries(example1 PRIVATE Python2::Module)
 
 # re-use sample interface file for another plugin
 swig_add_library(example2
@@ -44,7 +44,7 @@ set_target_properties (example2 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3")
-target_link_libraries(example2 PRIVATE Python3::Python)
+target_link_libraries(example2 PRIVATE Python3::Module)
 
 
 add_test (NAME ModuleVersion2.example1
diff --git a/Tests/UseSWIG/MultipleModules/CMakeLists.txt b/Tests/UseSWIG/MultipleModules/CMakeLists.txt
index f1dc379..4380080 100644
--- a/Tests/UseSWIG/MultipleModules/CMakeLists.txt
+++ b/Tests/UseSWIG/MultipleModules/CMakeLists.txt
@@ -36,7 +36,7 @@ set_target_properties (example1 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python")
-target_link_libraries(example1 PRIVATE Python::Python)
+target_link_libraries(example1 PRIVATE Python::Module)
 
 # re-use sample interface file for another plugin
 set_property(SOURCE "../example.i" APPEND PROPERTY
diff --git a/Tests/UseSWIG/MultiplePython/CMakeLists.txt b/Tests/UseSWIG/MultiplePython/CMakeLists.txt
index 8f87755..cf6c80e 100644
--- a/Tests/UseSWIG/MultiplePython/CMakeLists.txt
+++ b/Tests/UseSWIG/MultiplePython/CMakeLists.txt
@@ -34,7 +34,7 @@ set_target_properties (example1 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python2")
-target_link_libraries(example1 PRIVATE Python2::Python)
+target_link_libraries(example1 PRIVATE Python2::Module)
 
 # re-use sample interface file for another plugin
 swig_add_library(example2
@@ -46,7 +46,7 @@ set_target_properties (example2 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/Python3")
-target_link_libraries(example2 PRIVATE Python3::Python)
+target_link_libraries(example2 PRIVATE Python3::Module)
 
 
 
diff --git a/Tests/UseSWIG/SwigSrcFileExtension/CMakeLists.txt b/Tests/UseSWIG/SwigSrcFileExtension/CMakeLists.txt
index 7eb73d4..f70ce49 100644
--- a/Tests/UseSWIG/SwigSrcFileExtension/CMakeLists.txt
+++ b/Tests/UseSWIG/SwigSrcFileExtension/CMakeLists.txt
@@ -16,11 +16,11 @@ set(SWIG_SOURCE_FILE_EXTENSIONS ".i" ".swg")
 
 # Generate a Python module out of `.i`
 swig_add_library(my_add LANGUAGE python SOURCES my_add.i)
-target_link_libraries(my_add Python::Python)
+target_link_libraries(my_add Python::Module)
 
 # Generate a Python module out of `.swg`
 swig_add_library(my_sub LANGUAGE python SOURCES my_sub.swg)
-target_link_libraries(my_sub Python::Python)
+target_link_libraries(my_sub Python::Module)
 
 # Add a test
 add_test(NAME SwigSrcFileExtension
diff --git a/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES/CMakeLists.txt b/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES/CMakeLists.txt
index fbb72d5..80a2e16 100644
--- a/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES/CMakeLists.txt
+++ b/Tests/UseSWIG/UseTargetINCLUDE_DIRECTORIES/CMakeLists.txt
@@ -25,7 +25,7 @@ set_target_properties (example1 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example1")
-target_link_libraries(example1 PRIVATE Python3::Python)
+target_link_libraries(example1 PRIVATE Python3::Module)
 
 
 # Check that source property override target property
@@ -42,4 +42,4 @@ set_target_properties (example2 PROPERTIES
   LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2"
   ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2"
   RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/example2")
-target_link_libraries(example2 PRIVATE Python3::Python)
+target_link_libraries(example2 PRIVATE Python3::Module)
-- 
cgit v0.12