Support.cmake 148 KB
Newer Older
1 2 3 4 5 6 7
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file Copyright.txt or https://cmake.org/licensing for details.

#
# This file is a "template" file used by various FindPython modules.
#

8 9
cmake_policy (GET CMP0094 _${_PYTHON_PREFIX}_LOOKUP_POLICY)

10 11
cmake_policy (VERSION 3.7)

12 13 14 15
if (_${_PYTHON_PREFIX}_LOOKUP_POLICY)
  cmake_policy (SET CMP0094 ${_${_PYTHON_PREFIX}_LOOKUP_POLICY})
endif()

16 17 18 19 20 21 22 23 24
#
# Initial configuration
#
if (NOT DEFINED _PYTHON_PREFIX)
  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
endif()
if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
endif()
25
if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3")
26
  set(_${_PYTHON_PREFIX}_VERSIONS 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
27
elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "2")
28 29 30 31 32
  set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
else()
  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
endif()

Kyle Edwards's avatar
Kyle Edwards committed
33 34
get_property(_${_PYTHON_PREFIX}_CMAKE_ROLE GLOBAL PROPERTY CMAKE_ROLE)

35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

#
# helper commands
#
macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG)
  if (${_PYTHON_PREFIX}_FIND_REQUIRED)
    message (FATAL_ERROR "${_PYTHON_MSG}")
  else()
    if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY)
      message(STATUS "${_PYTHON_MSG}")
    endif ()
  endif()

  set (${_PYTHON_PREFIX}_FOUND FALSE)
  string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX)
  set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE)
  return()
endmacro()


55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
function (_PYTHON_MARK_AS_INTERNAL)
  foreach (var IN LISTS ARGV)
    if (DEFINED CACHE{${var}})
      set_property (CACHE ${var} PROPERTY TYPE INTERNAL)
    endif()
  endforeach()
endfunction()


macro (_PYTHON_SELECT_LIBRARY_CONFIGURATIONS _PYTHON_BASENAME)
  if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_RELEASE)
    set(${_PYTHON_BASENAME}_LIBRARY_RELEASE "${_PYTHON_BASENAME}_LIBRARY_RELEASE-NOTFOUND")
  endif()
  if(NOT DEFINED ${_PYTHON_BASENAME}_LIBRARY_DEBUG)
    set(${_PYTHON_BASENAME}_LIBRARY_DEBUG "${_PYTHON_BASENAME}_LIBRARY_DEBUG-NOTFOUND")
  endif()

  get_property(_PYTHON_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  if (${_PYTHON_BASENAME}_LIBRARY_DEBUG AND ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND
      NOT ${_PYTHON_BASENAME}_LIBRARY_DEBUG STREQUAL ${_PYTHON_BASENAME}_LIBRARY_RELEASE AND
      (_PYTHON_isMultiConfig OR CMAKE_BUILD_TYPE))
    # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for
    # single-config generators, set optimized and debug libraries
78 79 80
    set (${_PYTHON_BASENAME}_LIBRARIES "")
    foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_RELEASE)
      list( APPEND ${_PYTHON_BASENAME}_LIBRARIES optimized "${_PYTHON_libname}")
81
    endforeach()
82 83
    foreach (_PYTHON_libname IN LISTS ${_PYTHON_BASENAME}_LIBRARY_DEBUG)
      list( APPEND ${_PYTHON_BASENAME}_LIBRARIES debug "${_PYTHON_libname}")
84 85
    endforeach()
  elseif (${_PYTHON_BASENAME}_LIBRARY_RELEASE)
86
    set (${_PYTHON_BASENAME}_LIBRARIES "${${_PYTHON_BASENAME}_LIBRARY_RELEASE}")
87
  elseif (${_PYTHON_BASENAME}_LIBRARY_DEBUG)
88
    set (${_PYTHON_BASENAME}_LIBRARIES "${${_PYTHON_BASENAME}_LIBRARY_DEBUG}")
89
  else()
90
    set (${_PYTHON_BASENAME}_LIBRARIES "${_PYTHON_BASENAME}_LIBRARY-NOTFOUND")
91 92 93 94
  endif()
endmacro()


95
macro (_PYTHON_FIND_FRAMEWORKS)
96
  if (CMAKE_HOST_APPLE OR APPLE)
97
    file(TO_CMAKE_PATH "$ENV{CMAKE_FRAMEWORK_PATH}" _pff_CMAKE_FRAMEWORK_PATH)
98
    set (_pff_frameworks ${CMAKE_FRAMEWORK_PATH}
99 100 101 102
                         ${_pff_CMAKE_FRAMEWORK_PATH}
                         ~/Library/Frameworks
                         /usr/local/Frameworks
                         ${CMAKE_SYSTEM_FRAMEWORK_PATH})
103
    list (REMOVE_DUPLICATES _pff_frameworks)
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
    foreach (_pff_implementation IN LISTS _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
      unset (_${_PYTHON_PREFIX}_${_pff_implementation}_FRAMEWORKS)
      if (_pff_implementation STREQUAL "CPython")
        foreach (_pff_framework IN LISTS _pff_frameworks)
          if (EXISTS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework)
            list (APPEND _${_PYTHON_PREFIX}_${_pff_implementation}_FRAMEWORKS ${_pff_framework}/Python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}.framework)
          endif()
          if (EXISTS ${_pff_framework}/Python.framework)
            list (APPEND _${_PYTHON_PREFIX}_${_pff_implementation}_FRAMEWORKS ${_pff_framework}/Python.framework)
          endif()
        endforeach()
      elseif (_pff_implementation STREQUAL "IronPython")
        foreach (_pff_framework IN LISTS _pff_frameworks)
          if (EXISTS ${_pff_framework}/IronPython.framework)
            list (APPEND _${_PYTHON_PREFIX}_${_pff_implementation}_FRAMEWORKS ${_pff_framework}/IronPython.framework)
          endif()
        endforeach()
121 122
      endif()
    endforeach()
123
    unset (_pff_implementation)
124 125 126 127 128
    unset (_pff_frameworks)
    unset (_pff_framework)
  endif()
endmacro()

129
function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS)
130 131 132 133 134
  cmake_parse_arguments (PARSE_ARGV 1 _PGF "" "" "IMPLEMENTATIONS;VERSION")

  if (NOT _PGF_IMPLEMENTATIONS)
    set (_PGF_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS})
  endif()
135 136 137

  set (framework_paths)

138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
  foreach (implementation IN LISTS _PGF_IMPLEMENTATIONS)
    if (implementation STREQUAL "CPython")
      foreach (version IN LISTS _PGF_VERSION)
        foreach (framework IN LISTS _${_PYTHON_PREFIX}_${implementation}_FRAMEWORKS)
          if (EXISTS "${framework}/Versions/${version}")
            list (APPEND framework_paths "${framework}/Versions/${version}")
          endif()
        endforeach()
      endforeach()
    elseif (implementation STREQUAL "IronPython")
      foreach (version IN LISTS _PGF_VERSION)
        foreach (framework IN LISTS _${_PYTHON_PREFIX}_${implementation}_FRAMEWORKS)
          # pick-up all available versions
          file (GLOB versions LIST_DIRECTORIES true RELATIVE "${framework}/Versions/"
                              "${framework}/Versions/${version}*")
          list (SORT versions ORDER DESCENDING)
          list (TRANSFORM versions PREPEND "${framework}/Versions/")
          list (APPEND framework_paths ${versions})
        endforeach()
      endforeach()
    endif()
159
  endforeach()
160 161

  set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${framework_paths} PARENT_SCOPE)
162 163
endfunction()

164 165 166 167 168 169 170 171 172 173 174 175 176 177 178
function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS)
  cmake_parse_arguments (PARSE_ARGV 1 _PGR "" "" "IMPLEMENTATIONS;VERSION")

  if (NOT _PGR_IMPLEMENTATIONS)
    set (_PGR_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS})
  endif()

  set (registries)

  foreach (implementation IN LISTS _PGR_IMPLEMENTATIONS)
    if (implementation STREQUAL "CPython")
      foreach (version IN LISTS _PGR_VERSION)
        string (REPLACE "." "" version_no_dots ${version})
        list (APPEND registries
                     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
179 180 181 182 183 184 185 186 187 188 189 190
                     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
        if (version VERSION_GREATER_EQUAL "3.5")
          get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME)
          if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit")
            list (APPEND registries
                         [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
          endif()
        else()
          list (APPEND registries
                       [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath])
        endif()
        list (APPEND registries
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
                     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
                     [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
                     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
                     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
                     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${version}\\InstallPath]
                     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
                     [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath])
      endforeach()
    elseif (implementation STREQUAL "IronPython")
      foreach (version  IN LISTS _PGR_VERSION)
        list (APPEND registries [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${version}\\InstallPath])
      endforeach()
    endif()
  endforeach()

  set (${_PYTHON_PGR_REGISTRY_PATHS} "${registries}" PARENT_SCOPE)
207 208 209
endfunction()


210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253
function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS)
  set (abiflags)
  list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug)
  list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc)
  list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode)

  if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY")
    set (abiflags "mu" "m" "u" "")
  elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON")
    set (abiflags "mu" "u")
  elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF")
    set (abiflags "m" "")
  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
    set (abiflags "mu" "m")
  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON")
    set (abiflags "mu")
  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF")
    set (abiflags "m")
  elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY")
    set (abiflags "u" "")
  elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON")
    set (abiflags "u")
  endif()

  if (pydebug STREQUAL "ON")
    if (abiflags)
      list (TRANSFORM abiflags PREPEND "d")
    else()
      set (abiflags "d")
    endif()
  elseif (pydebug STREQUAL "ANY")
    if (abiflags)
      set (flags "${abiflags}")
      list (TRANSFORM flags PREPEND "d")
      list (APPEND abiflags "${flags}")
    else()
      set (abiflags "" "d")
    endif()
  endif()

  set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE)
endfunction()

function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES)
254 255 256 257 258
  cmake_parse_arguments (PARSE_ARGV 1 _PGPS "INTERPRETER;COMPILER;LIBRARY;INCLUDE" "" "IMPLEMENTATIONS;VERSION")

  if (NOT _PGPS_IMPLEMENTATIONS)
    set (_PGPS_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS})
  endif()
259 260 261 262 263 264 265 266

  if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
    set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
  else()
    set (abi "mu" "m" "u" "")
  endif()

  set (path_suffixes)
267

268
  foreach (implementation IN LISTS _PGPS_IMPLEMENTATIONS)
269
    if (implementation STREQUAL "CPython")
270
      if (_PGPS_INTERPRETER)
271
        list (APPEND path_suffixes bin Scripts)
272
      else()
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
        foreach (version IN LISTS _PGPS_VERSION)
          if (_PGPS_LIBRARY)
            if (CMAKE_LIBRARY_ARCHITECTURE)
              list (APPEND path_suffixes lib/${CMAKE_LIBRARY_ARCHITECTURE})
            endif()
            list (APPEND path_suffixes lib libs)

            if (CMAKE_LIBRARY_ARCHITECTURE)
              set (suffixes "${abi}")
              if (suffixes)
                list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
                list (TRANSFORM suffixes APPEND "-${CMAKE_LIBRARY_ARCHITECTURE}")
              else()
                set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}-${CMAKE_LIBRARY_ARCHITECTURE}")
              endif()
              list (APPEND path_suffixes ${suffixes})
            endif()
            set (suffixes "${abi}")
            if (suffixes)
              list (TRANSFORM suffixes PREPEND "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
            else()
              set (suffixes "lib/python${_PGPS_VERSION}/config-${_PGPS_VERSION}")
            endif()
            list (APPEND path_suffixes ${suffixes})
          elseif (_PGPS_INCLUDE)
            set (suffixes "${abi}")
            if (suffixes)
              list (TRANSFORM suffixes PREPEND "include/python${_PGPS_VERSION}")
            else()
              set (suffixes "include/python${_PGPS_VERSION}")
            endif()
            list (APPEND path_suffixes ${suffixes} include)
          endif()
        endforeach()
      endif()
    elseif (implementation STREQUAL "IronPython")
309 310 311 312
      if (_PGPS_INTERPRETER OR _PGPS_COMPILER)
        foreach (version IN LISTS _PGPS_VERSION)
          list (APPEND path_suffixes "share/ironpython${version}")
        endforeach()
313
        list (APPEND path_suffixes ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES})
314
      endif()
315
    elseif (implementation STREQUAL "PyPy")
316
      if (_PGPS_INTERPRETER)
317 318 319 320 321 322
        list (APPEND path_suffixes ${_${_PYTHON_PREFIX}_PYPY_EXECUTABLE_PATH_SUFFIXES})
      elseif (_PGPS_LIBRARY)
        list (APPEND path_suffixes ${_${_PYTHON_PREFIX}_PYPY_LIBRARY_PATH_SUFFIXES})
      elseif (_PGPS_INCLUDE)
        list (APPEND path_suffixes ${_${_PYTHON_PREFIX}_PYPY_INCLUDE_PATH_SUFFIXES})
      endif()
323
    endif()
324 325
  endforeach()
  list (REMOVE_DUPLICATES path_suffixes)
326 327 328 329

  set (${_PYTHON_PGPS_PATH_SUFFIXES} ${path_suffixes} PARENT_SCOPE)
endfunction()

330
function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES)
331 332 333 334 335
  cmake_parse_arguments (PARSE_ARGV 1 _PGN "POSIX;INTERPRETER;COMPILER;CONFIG;LIBRARY;WIN32;DEBUG" "" "IMPLEMENTATIONS;VERSION")

  if (NOT _PGN_IMPLEMENTATIONS)
    set (_PGN_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS})
  endif()
336

337 338
  set (names)

339
  foreach (implementation IN LISTS _PGN_IMPLEMENTATIONS)
340 341 342 343
    if (implementation STREQUAL "CPython")
      foreach (version IN LISTS _PGN_VERSION)
        if (_PGN_WIN32)
          string (REPLACE "." "" version_no_dots ${version})
344

345 346 347 348
          set (name python${version_no_dots})
          if (_PGN_DEBUG)
            string (APPEND name "_d")
          endif()
349

350 351
          list (APPEND names "${name}")
        endif()
352

353 354 355 356
        if (_PGN_POSIX)
          if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS)
            set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}")
          else()
357
            if (_PGN_INTERPRETER OR _PGN_CONFIG)
358 359 360 361 362
              set (abi "")
            else()
              set (abi "mu" "m" "u" "")
            endif()
          endif()
363

364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
          if (abi)
            if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
              set (abinames "${abi}")
              list (TRANSFORM abinames PREPEND "${CMAKE_LIBRARY_ARCHITECTURE}-python${version}")
              list (TRANSFORM abinames APPEND "-config")
              list (APPEND names ${abinames})
            endif()
            set (abinames "${abi}")
            list (TRANSFORM abinames PREPEND "python${version}")
            if (_PGN_CONFIG)
              list (TRANSFORM abinames APPEND "-config")
            endif()
            list (APPEND names ${abinames})
          else()
            unset (abinames)
            if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE)
              set (abinames "${CMAKE_LIBRARY_ARCHITECTURE}-python${version}")
            endif()
            list (APPEND abinames "python${version}")
            if (_PGN_CONFIG)
              list (TRANSFORM abinames APPEND "-config")
            endif()
            list (APPEND names ${abinames})
          endif()
        endif()
      endforeach()
390
      if (_PGN_INTERPRETER)
391
        list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python)
392
      endif()
393
    elseif (implementation STREQUAL "IronPython")
394 395 396 397 398 399 400 401 402 403
      if (_PGN_INTERPRETER)
        if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
          # Do not use wrapper script on Linux because it is buggy: -c interpreter option cannot be used
          foreach (version IN LISTS _PGN_VERSION)
            list (APPEND names "ipy${version}")
          endforeach()
        endif()
        list (APPEND names ${_${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES})
      elseif (_PGN_COMPILER)
        list (APPEND names ${_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES})
404
      endif()
405
    elseif (implementation STREQUAL "PyPy")
406
      if (_PGN_INTERPRETER)
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
        list (APPEND names ${_${_PYTHON_PREFIX}_PYPY_NAMES})
      elseif (_PGN_LIBRARY)
        if (_PGN_WIN32)
          foreach (version IN LISTS _PGN_VERSION)
            string (REPLACE "." "" version_no_dots ${version})

            set (name "python${version_no_dots}")
            if (_PGN_DEBUG)
              string (APPEND name "_d")
            endif()
            list (APPEND names "${name}")
          endforeach()
        endif()
        list (APPEND names ${_${_PYTHON_PREFIX}_PYPY_LIB_NAMES})
      endif()
422
    endif()
423
  endforeach()
424 425

  set (${_PYTHON_PGN_NAMES} ${names} PARENT_SCOPE)
426 427
endfunction()

428 429 430
function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME)
  unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE)

431
  if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI)$")
432 433 434 435
    return()
  endif()

  if (_${_PYTHON_PREFIX}_CONFIG)
436 437 438 439 440
    if (NAME STREQUAL "SOABI")
      set (config_flag "--extension-suffix")
    else()
      set (config_flag "--${NAME}")
    endif()
441 442 443 444 445 446 447 448 449 450 451
    string (TOLOWER "${config_flag}" config_flag)
    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag}
                     RESULT_VARIABLE _result
                     OUTPUT_VARIABLE _values
                     ERROR_QUIET
                     OUTPUT_STRIP_TRAILING_WHITESPACE)
    if (_result)
      unset (_values)
    else()
      if (NAME STREQUAL "INCLUDES")
        # do some clean-up
452 453
        string (REGEX MATCHALL "(-I|-iwithsysroot)[ ]*[^ ]+" _values "${_values}")
        string (REGEX REPLACE "(-I|-iwithsysroot)[ ]*" "" _values "${_values}")
454
        list (REMOVE_DUPLICATES _values)
455 456
      elseif (NAME STREQUAL "SOABI")
        # clean-up: remove prefix character and suffix
457
        string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}")
458 459 460 461
      endif()
    endif()
  endif()

462
  if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING)
463
    if (NAME STREQUAL "PREFIX")
464
      execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n   from distutils import sysconfig\n   sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))\nexcept Exception:\n   import sysconfig\n   sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))"
465 466 467 468 469 470 471 472 473 474
                       RESULT_VARIABLE _result
                       OUTPUT_VARIABLE _values
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (_result)
        unset (_values)
      else()
        list (REMOVE_DUPLICATES _values)
      endif()
    elseif (NAME STREQUAL "INCLUDES")
475 476 477 478 479
      if (WIN32)
        set (_scheme "nt")
      else()
        set (_scheme "posix_prefix")
      endif()
480 481
      execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
                               "import sys\ntry:\n   from distutils import sysconfig\n   sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))\nexcept Exception:\n   import sysconfig\n   sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))"
482 483 484 485 486 487
                       RESULT_VARIABLE _result
                       OUTPUT_VARIABLE _values
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (_result)
        unset (_values)
488 489
      else()
        list (REMOVE_DUPLICATES _values)
490
      endif()
491
    elseif (NAME STREQUAL "SOABI")
492 493
      execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
                               "import sys\ntry:\n   from distutils import sysconfig\n   sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))\nexcept Exception:\n   import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('EXT_SUFFIX') or '']))"
494 495 496 497 498 499 500
                       RESULT_VARIABLE _result
                       OUTPUT_VARIABLE _soabi
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (_result)
        unset (_values)
      else()
501 502 503 504
        foreach (_item IN LISTS _soabi)
          if (_item)
            set (_values "${_item}")
            break()
505
          endif()
506 507 508 509
        endforeach()
        if (_values)
          # clean-up: remove prefix character and suffix
          string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}")
510 511
        endif()
      endif()
512 513 514 515 516
    else()
      set (config_flag "${NAME}")
      if (NAME STREQUAL "CONFIGDIR")
        set (config_flag "LIBPL")
      endif()
517 518
      execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
                               "import sys\ntry:\n   from distutils import sysconfig\n   sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n   import sysconfig\n   sys.stdout.write(sysconfig.get_config_var('${config_flag}'))"
519 520 521 522 523 524 525 526 527 528
                       RESULT_VARIABLE _result
                       OUTPUT_VARIABLE _values
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (_result)
        unset (_values)
      endif()
    endif()
  endif()

529 530 531 532 533
  if (config_flag STREQUAL "ABIFLAGS")
    set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE)
    return()
  endif()

534 535 536 537 538 539
  if (NOT _values OR _values STREQUAL "None")
    return()
  endif()

  if (NAME STREQUAL "LIBS")
    # do some clean-up
540
    string (REGEX MATCHALL "-(l|framework)[ ]*[^ ]+" _values "${_values}")
541 542 543 544 545
    # remove elements relative to python library itself
    list (FILTER _values EXCLUDE REGEX "-lpython")
    list (REMOVE_DUPLICATES _values)
  endif()

546 547 548 549
  if (WIN32 AND NAME MATCHES "^(PREFIX|CONFIGDIR|INCLUDES)$")
    file (TO_CMAKE_PATH "${_values}" _values)
  endif()

550 551 552
  set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE)
endfunction()

553 554 555 556 557 558 559 560 561 562 563
function (_PYTHON_GET_VERSION)
  cmake_parse_arguments (PARSE_ARGV 0 _PGV "LIBRARY;INCLUDE" "PREFIX" "")

  unset (${_PGV_PREFIX}VERSION PARENT_SCOPE)
  unset (${_PGV_PREFIX}VERSION_MAJOR PARENT_SCOPE)
  unset (${_PGV_PREFIX}VERSION_MINOR PARENT_SCOPE)
  unset (${_PGV_PREFIX}VERSION_PATCH PARENT_SCOPE)
  unset (${_PGV_PREFIX}ABI PARENT_SCOPE)

  if (_PGV_LIBRARY)
    # retrieve version and abi from library name
564
    if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE)
565
      # extract version from library name
566
      if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])([0-9]+)")
567 568 569 570
        set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
        set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
        set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
        set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
571
      elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])\\.([0-9]+)([dmu]*)")
572 573 574 575
        set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE)
        set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE)
        set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE)
        set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_3}" PARENT_SCOPE)
576 577 578 579 580 581 582 583
      elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "pypy(3)?")
        set (version "${CMAKE_MATCH_1}")
        if (version EQUAL "3")
          set (${_PGV_PREFIX}VERSION_MAJOR "3" PARENT_SCOPE)
          set (${_PGV_PREFIX}VERSION "3" PARENT_SCOPE)
        else()
          set (${_PGV_PREFIX}VERSION_MAJOR "2" PARENT_SCOPE)
          set (${_PGV_PREFIX}VERSION "2" PARENT_SCOPE)
584
        endif()
585
        set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
586
      endif()
587
    endif()
588
  else()
589
    if (_${_PYTHON_PREFIX}_INCLUDE_DIR)
590
      # retrieve version from header file
591
      file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" version
592 593 594 595 596 597 598 599
            REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
      string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
                            version "${version}")
      string (REGEX MATCHALL "[0-9]+" versions "${version}")
      list (GET versions 0 version_major)
      list (GET versions 1 version_minor)
      list (GET versions 2 version_patch)

600
      set (${_PGV_PREFIX}VERSION "${version_major}.${version_minor}.${version_patch}" PARENT_SCOPE)
601 602 603 604 605
      set (${_PGV_PREFIX}VERSION_MAJOR ${version_major} PARENT_SCOPE)
      set (${_PGV_PREFIX}VERSION_MINOR ${version_minor} PARENT_SCOPE)
      set (${_PGV_PREFIX}VERSION_PATCH ${version_patch} PARENT_SCOPE)

      # compute ABI flags
606
      if (version_major VERSION_GREATER "2")
607
        file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)")
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631
        set (abi)
        if (config MATCHES "#[ ]*define[ ]+MS_WIN32")
          # ABI not used on Windows
          set (abi "")
        else()
          if (config MATCHES "#[ ]*define[ ]+Py_DEBUG[ ]+1")
            string (APPEND abi "d")
          endif()
          if (config MATCHES "#[ ]*define[ ]+WITH_PYMALLOC[ ]+1")
            string (APPEND abi "m")
          endif()
          if (config MATCHES "#[ ]*define[ ]+Py_UNICODE_SIZE[ ]+4")
            string (APPEND abi "u")
          endif()
          set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE)
        endif()
      else()
        # ABI not supported
        set (${_PGV_PREFIX}ABI "" PARENT_SCOPE)
      endif()
    endif()
  endif()
endfunction()

632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661
function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME)
  cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "" "")

  unset ({_PYTHON_PGL_NAME} PARENT_SCOPE)

  if ((_PGL_INTERPRETER AND NOT _${_PYTHON_PREFIX}_EXECUTABLE)
      OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER))
    return()
  endif()

  if ("IronPython" IN_LIST _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS
      AND NOT SYSTEM_NAME MATCHES "Windows|Linux")
    if (_PGL_INTERPRETER)
      get_filename_component (name "${_${_PYTHON_PREFIX}_EXECUTABLE}" NAME)
      get_filename_component (ext "${_${_PYTHON_PREFIX}_EXECUTABLE}" LAST_EXT)
      if (name IN_LIST _${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES
          AND ext STREQUAL ".exe")
        set (${_PYTHON_PGL_NAME} "${${_PYTHON_PREFIX}_DOTNET_LAUNCHER}" PARENT_SCOPE)
      endif()
    else()
      get_filename_component (name "${_${_PYTHON_PREFIX}_COMPILER}" NAME)
      get_filename_component (ext "${_${_PYTHON_PREFIX}_COMPILER}" LAST_EXT)
      if (name IN_LIST _${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES
          AND ext STREQUAL ".exe")
        set (${_PYTHON_PGL_NAME} "${${_PYTHON_PREFIX}_DOTNET_LAUNCHER}" PARENT_SCOPE)
      endif()
    endif()
  endif()
endfunction()

662

663
function (_PYTHON_VALIDATE_INTERPRETER)
664
  if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
665 666 667
    return()
  endif()

668
  cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT;CHECK_EXISTS" "" "")
669
  if (_PVI_UNPARSED_ARGUMENTS)
670
    set (expected_version "${_PVI_UNPARSED_ARGUMENTS}")
671 672 673 674
  else()
    unset (expected_version)
  endif()

675 676
  if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}")
    # interpreter does not exist anymore
677
    set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
678
    set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
679 680 681
    return()
  endif()

682 683
  _python_get_launcher (launcher INTERPRETER)

684 685
  # validate ABI compatibility
  if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI)
686
    execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
687 688 689 690 691 692 693 694 695 696 697
                             "import sys; sys.stdout.write(sys.abiflags)"
                     RESULT_VARIABLE result
                     OUTPUT_VARIABLE abi
                     ERROR_QUIET
                     OUTPUT_STRIP_TRAILING_WHITESPACE)
    if (result)
      # assume ABI is not supported
      set (abi "")
    endif()
    if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
      # incompatible ABI
698
      set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
699
      set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
700 701 702 703
      return()
    endif()
  endif()

704
  get_filename_component (python_name "${_${_PYTHON_PREFIX}_EXECUTABLE}" NAME)
705

706 707 708 709 710 711 712 713 714 715 716
  if (expected_version)
    if (NOT python_name STREQUAL "python${expected_version}${abi}${CMAKE_EXECUTABLE_SUFFIX}")
      # compute number of components for version
      string (REGEX REPLACE "[^.]" "" dots "${expected_version}")
      # add one dot because there is one dot less than there are components
      string (LENGTH "${dots}." count)
      if (count GREATER 3)
        set (count 3)
      endif()

      # executable found must have a specific version
717
      execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
718 719 720 721 722 723 724 725
                               "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:${count}]]))"
                       RESULT_VARIABLE result
                       OUTPUT_VARIABLE version
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (result)
        # interpreter is not usable
        set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
726
        set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
727
      else()
728 729
        if (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version)
          # interpreter has wrong version
730
          set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
731
          set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
732 733 734 735 736 737 738 739 740
        else()
          # check that version is OK
          string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" major_version "${version}")
          string(REGEX REPLACE "^([0-9]+)\\.?.*$" "\\1" expected_major_version "${expected_version}")
          if (NOT major_version VERSION_EQUAL expected_major_version
              OR NOT version VERSION_GREATER_EQUAL expected_version)
            set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
            set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
          endif()
741
        endif()
742
      endif()
743 744 745
      if (NOT _${_PYTHON_PREFIX}_EXECUTABLE)
        return()
      endif()
746
    endif()
747
  else()
748
    if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}")
749 750
      # executable found do not have version in name
      # ensure major version is OK
751
      execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
752 753 754 755 756 757 758
                               "import sys; sys.stdout.write(str(sys.version_info[0]))"
                       RESULT_VARIABLE result
                       OUTPUT_VARIABLE version
                       ERROR_QUIET
                       OUTPUT_STRIP_TRAILING_WHITESPACE)
      if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
        # interpreter not usable or has wrong major version
759
        if (result)
760
          set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
761
        else()
762
          set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
763
        endif()
764
        set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
765 766 767
        return()
      endif()
    endif()
768 769
  endif()

770 771
  if (CMAKE_SIZEOF_VOID_P AND ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
        OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
772 773
      AND NOT CMAKE_CROSSCOMPILING)
    # In this case, interpreter must have same architecture as environment
774
    execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
775 776 777 778 779 780 781
                             "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))"
                     RESULT_VARIABLE result
                     OUTPUT_VARIABLE size
                     ERROR_QUIET
                     OUTPUT_STRIP_TRAILING_WHITESPACE)
    if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P)
      # interpreter not usable or has wrong architecture
782
      if (result)
783
        set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
784
      else()
785
        set (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"" PARENT_SCOPE)
786
      endif()
787
      set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND")
788 789 790 791 792 793
      return()
    endif()
  endif()
endfunction()


794
function (_PYTHON_VALIDATE_COMPILER)
795
  if (NOT _${_PYTHON_PREFIX}_COMPILER)
796 797 798
    return()
  endif()

799
  cmake_parse_arguments (PARSE_ARGV 0 _PVC "EXACT;CHECK_EXISTS" "" "")
800 801
  if (_PVC_UNPARSED_ARGUMENTS)
    set (major_version FALSE)
802
    set (expected_version "${_PVC_UNPARSED_ARGUMENTS}")
803 804
  else()
    set (major_version TRUE)
805
    set (expected_version "${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}")
806 807 808
    set (_PVC_EXACT TRUE)
  endif()

809 810
  if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}")
    # Compiler does not exist anymore
811
    set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot find the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
812
    set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
813 814 815
    return()
  endif()

816 817
  _python_get_launcher (launcher COMPILER)

818 819
  # retrieve python environment version from compiler
  set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
820 821 822 823
  if (major_version)
    # check only major version
    file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write(str(sys.version_info[0]))")
  else()
824 825 826 827 828 829 830 831
    # compute number of components for version
    string (REGEX REPLACE "[^.]" "" dots "${expected_version}")
    # add one dot because there is one dot less than there are components
    string (LENGTH "${dots}." count)
    if (count GREATER 3)
      set (count 3)
    endif()
    file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:${count}]]))\n")
832
  endif()
833 834 835
  execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_COMPILER}"
                           ${_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS}
                           /target:exe /embed "${working_dir}/version.py"
836 837 838 839
                   WORKING_DIRECTORY "${working_dir}"
                   OUTPUT_QUIET
                   ERROR_QUIET
                   OUTPUT_STRIP_TRAILING_WHITESPACE)
840 841 842
  get_filename_component (ir_dir "${_${_PYTHON_PREFIX}_COMPILER}" DIRECTORY)
  execute_process (COMMAND "${CMAKE_COMMAND}" -E env "MONO_PATH=${ir_dir}"
                                              ${${_PYTHON_PREFIX}_DOTNET_LAUNCHER} "${working_dir}/version.exe"
843 844 845 846
                   WORKING_DIRECTORY "${working_dir}"
                   RESULT_VARIABLE result
                   OUTPUT_VARIABLE version
                   ERROR_QUIET)
847 848 849
  file (REMOVE_RECURSE "${working_dir}")
  if (result)
    # compiler is not usable
850
    set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Cannot use the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
851 852 853 854
    set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
  elseif ((_PVC_EXACT AND NOT version VERSION_EQUAL expected_version)
          OR NOT version VERSION_GREATER_EQUAL expected_version)
    # Compiler has wrong version
855
    set (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE "Wrong version for the compiler \"${_${_PYTHON_PREFIX}_COMPILER}\"" PARENT_SCOPE)
856
    set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND")
857 858 859 860
  endif()
endfunction()


861
function (_PYTHON_VALIDATE_LIBRARY)
862
  if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
863
    unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG)
864 865 866
    return()
  endif()

867
  cmake_parse_arguments (PARSE_ARGV 0 _PVL "EXACT;CHECK_EXISTS" "" "")
868 869 870 871 872 873
  if (_PVL_UNPARSED_ARGUMENTS)
    set (expected_version ${_PVL_UNPARSED_ARGUMENTS})
  else()
    unset (expected_version)
  endif()

874 875
  if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
    # library does not exist anymore
876
    set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
877
    set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
878
    if (WIN32)
879
      set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
880
    endif()
881
    set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
882 883 884
    return()
  endif()

885 886 887 888 889
  # retrieve version and abi from library name
  _python_get_version (LIBRARY PREFIX lib_)

  if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
    # incompatible ABI
890
    set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
891
    set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
892 893
  else()
    if (expected_version)
894 895 896
      # library have only major.minor information
      string (REGEX MATCH "[0-9](\\.[0-9]+)?" version "${expected_version}")
      if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL version) OR (lib_VERSION VERSION_LESS version))
897
        # library has wrong version
898
        set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
899
        set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
900 901 902 903
      endif()
    else()
      if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
        # library has wrong major version
904
        set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the library \"${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}\"" PARENT_SCOPE)
905
        set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND")
906 907 908 909
      endif()
    endif()
  endif()

910 911
  if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
    if (WIN32)
912
      set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND")
913
    endif()
914 915 916
    unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE CACHE)
    unset (_${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG CACHE)
    set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
917 918 919 920 921
  endif()
endfunction()


function (_PYTHON_VALIDATE_INCLUDE_DIR)
922
  if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
923 924 925
    return()
  endif()

926
  cmake_parse_arguments (PARSE_ARGV 0 _PVID "EXACT;CHECK_EXISTS" "" "")
927 928 929 930 931 932
  if (_PVID_UNPARSED_ARGUMENTS)
    set (expected_version ${_PVID_UNPARSED_ARGUMENTS})
  else()
    unset (expected_version)
  endif()

933 934
  if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}")
    # include file does not exist anymore
935
    set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Cannot find the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
936
    set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
937 938 939
    return()
  endif()

940 941 942 943 944
  # retrieve version from header file
  _python_get_version (INCLUDE PREFIX inc_)

  if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)
    # incompatible ABI
945
    set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
946
    set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
947 948 949 950
  else()
    if (expected_version)
      if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version))
        # include dir has wrong version
951
        set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
952
        set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
953 954 955 956
      endif()
    else()
      if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
        # include dir has wrong major version
957
        set (_${_PYTHON_PREFIX}_Development_REASON_FAILURE "Wrong major version for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"" PARENT_SCOPE)
958
        set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND")
959 960 961 962 963 964
      endif()
    endif()
  endif()
endfunction()


965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB)
  string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}")
  # look at runtime part on systems supporting it
  if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR
      (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN"
        AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$"))
    set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
    # MSYS has a special syntax for runtime libraries
    if (CMAKE_SYSTEM_NAME MATCHES "MSYS")
      list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-")
    endif()
    find_library (${ARGV})
  endif()
endfunction()


function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT)
  unset (_PYTHON_DIRS)
983
  set (_PYTHON_LIBS ${ARGN})
984 985 986 987 988 989
  foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS)
    if (${_PYTHON_LIB})
      get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY)
      list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}")
    endif()
  endforeach()
990
  list (REMOVE_DUPLICATES _PYTHON_DIRS)
991 992 993 994
  set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE)
endfunction()


995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013
function (_PYTHON_SET_DEVELOPMENT_MODULE_FOUND module)
  if ("Development.${module}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
    string(TOUPPER "${module}" id)
    set (module_found TRUE)

    if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS
        AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
      set (module_found FALSE)
    endif()
    if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS
        AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
      set (module_found FALSE)
    endif()

    set (${_PYTHON_PREFIX}_Development.${module}_FOUND ${module_found} PARENT_SCOPE)
  endif()
endfunction()


1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025
# If major version is specified, it must be the same as internal major version
if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR
    AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
  _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
endif()


# handle components
if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS)
  set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter)
  set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE)
endif()
1026
if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
1027
  list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Interpreter" "Development.Module")
1028
endif()
1029 1030 1031 1032 1033
if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
  list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Development.Module" "Development.Embed")
endif()
list (REMOVE_DUPLICATES ${_PYTHON_PREFIX}_FIND_COMPONENTS)
foreach (_${_PYTHON_PREFIX}_COMPONENT IN ITEMS Interpreter Compiler Development Development.Module Development.Embed NumPy)
1034 1035
  set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE)
endforeach()
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development)
  set (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Module TRUE)
  set (${_PYTHON_PREFIX}_FIND_REQUIRED_Development.Embed TRUE)
endif()

unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS)
unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS)
if ("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
  if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$")
    list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS "LIBRARY")
  endif()
  list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS "INCLUDE_DIR")
endif()
if ("Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
  list (APPEND _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS "LIBRARY" "INCLUDE_DIR")
endif()
set (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS ${_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS} ${_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_EMBED_ARTIFACTS})
list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)

1056 1057 1058
# Set versions to search
## default: search any version
set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS})
1059
unset (_${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
1060

1061
if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT)
1062
  if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
1063
    set (_${_PYTHON_PREFIX}_FIND_VERSION_EXACT "EXACT")
1064 1065 1066 1067 1068
    set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR})
  else()
    unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
    # add all compatible versions
    foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS)
1069
      if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL "${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR}")
1070 1071 1072 1073 1074 1075
        list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION})
      endif()
    endforeach()
  endif()
endif()

1076 1077
# Set ABIs to search
## default: search any ABI
1078
if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS "3")
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
  # ABI not supported
  unset (_${_PYTHON_PREFIX}_FIND_ABI)
  set (_${_PYTHON_PREFIX}_ABIFLAGS "")
else()
  unset (_${_PYTHON_PREFIX}_FIND_ABI)
  unset (_${_PYTHON_PREFIX}_ABIFLAGS)
  if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI)
    # normalization
    string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI)
    list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON")
    list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF")
    if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$")
      message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it")
      unset (_${_PYTHON_PREFIX}_FIND_ABI)
    endif()
    _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS)
  endif()
endif()
1097
unset (${_PYTHON_PREFIX}_SOABI)
1098

1099
# Define lookup strategy
1100 1101 1102 1103 1104
if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW")
  set (_${_PYTHON_PREFIX}_FIND_STRATEGY "LOCATION")
else()
  set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION")
endif()
1105 1106 1107 1108 1109
if (DEFINED ${_PYTHON_PREFIX}_FIND_STRATEGY)
  if (NOT ${_PYTHON_PREFIX}_FIND_STRATEGY MATCHES "^(VERSION|LOCATION)$")
    message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_STRATEGY}: invalid value for '${_PYTHON_PREFIX}_FIND_STRATEGY'. 'VERSION' or 'LOCATION' expected.")
    set (_${_PYTHON_PREFIX}_FIND_STRATEGY "VERSION")
  else()
1110
    set (_${_PYTHON_PREFIX}_FIND_STRATEGY "${${_PYTHON_PREFIX}_FIND_STRATEGY}")
1111 1112 1113
  endif()
endif()

1114
# Python and Anaconda distributions: define which architectures can be used
1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
if (CMAKE_SIZEOF_VOID_P)
  # In this case, search only for 64bit or 32bit
  math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
  set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
else()
  # architecture unknown, search for both 64bit and 32bit
  set (_${_PYTHON_PREFIX}_ARCH 64)
  set (_${_PYTHON_PREFIX}_ARCH2 32)
endif()

# IronPython support
1126 1127 1128
unset (_${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES)
unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES)
unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS)
1129
if (CMAKE_SIZEOF_VOID_P)
1130 1131 1132 1133 1134
  if (_${_PYTHON_PREFIX}_ARCH EQUAL "32")
    set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x86")
  else()
    set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x64")
  endif()
1135
endif()
1136 1137 1138 1139 1140 1141 1142 1143
if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux")
  # Do not use wrapper script on Linux because it is buggy: -c interpreter option cannot be used
  list (APPEND _${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES "ipy${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}" "ipy64" "ipy32" "ipy")
  list (APPEND _${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES "ipyc")
endif()
list (APPEND _${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES "ipy.exe")
list (APPEND _${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES "ipyc.exe")
set (_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES net45 net40 bin)
1144

1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
# PyPy support
if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL "3")
  set (_${_PYTHON_PREFIX}_PYPY_NAMES pypy3)
  set (_${_PYTHON_PREFIX}_PYPY_LIB_NAMES pypy3-c)
  if (WIN32)
    # special name for runtime part
    list (APPEND _${_PYTHON_PREFIX}_PYPY_LIB_NAMES libpypy3-c)
  endif()
  set (_${_PYTHON_PREFIX}_PYPY_INCLUDE_PATH_SUFFIXES lib/pypy3)
else()
  set (_${_PYTHON_PREFIX}_PYPY_NAMES pypy)
  set (_${_PYTHON_PREFIX}_PYPY_LIB_NAMES pypy-c)
  if (WIN32)
    # special name for runtime part
    list (APPEND _${_PYTHON_PREFIX}_PYPY_LIB_NAMES libpypy-c)
  endif()
  set (_${_PYTHON_PREFIX}_PYPY_INCLUDE_PATH_SUFFIXES lib/pypy)
endif()
set (_${_PYTHON_PREFIX}_PYPY_EXECUTABLE_PATH_SUFFIXES bin)
set (_${_PYTHON_PREFIX}_PYPY_LIBRARY_PATH_SUFFIXES lib libs bin)
list (APPEND _${_PYTHON_PREFIX}_PYPY_INCLUDE_PATH_SUFFIXES include)

1167 1168 1169 1170
# Python Implementations handling
unset (_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
if (DEFINED ${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
  foreach (_${_PYTHON_PREFIX}_IMPLEMENTATION IN LISTS ${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
1171 1172
    if (NOT _${_PYTHON_PREFIX}_IMPLEMENTATION MATCHES "^(CPython|IronPython|PyPy)$")
      message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${_${_PYTHON_PREFIX}_IMPLEMENTATION}: invalid value for '${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS'. 'CPython', 'IronPython' or 'PyPy' expected. Value will be ignored.")
1173 1174 1175 1176 1177
    else()
      list (APPEND _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_IMPLEMENTATION})
    endif()
  endforeach()
else()
1178 1179 1180 1181 1182
  if (WIN32)
    set (_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS CPython IronPython)
  else()
    set (_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS CPython)
  endif()
1183 1184 1185 1186 1187 1188 1189
endif()

# compute list of names for header file
unset (_${_PYTHON_PREFIX}_INCLUDE_NAMES)
foreach (_${_PYTHON_PREFIX}_IMPLEMENTATION IN LISTS _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
  if (_${_PYTHON_PREFIX}_IMPLEMENTATION STREQUAL "CPython")
    list (APPEND _${_PYTHON_PREFIX}_INCLUDE_NAMES "Python.h")
1190 1191
  elseif (_${_PYTHON_PREFIX}_IMPLEMENTATION STREQUAL "PyPy")
    list (APPEND _${_PYTHON_PREFIX}_INCLUDE_NAMES "PyPy.h")
1192 1193 1194 1195
  endif()
endforeach()


1196
# Apple frameworks handling
1197 1198
_python_find_frameworks ()

1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK "FIRST")

if (DEFINED ${_PYTHON_PREFIX}_FIND_FRAMEWORK)
  if (NOT ${_PYTHON_PREFIX}_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$")
    message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_FRAMEWORK}: invalid value for '${_PYTHON_PREFIX}_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
  else()
    set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${${_PYTHON_PREFIX}_FIND_FRAMEWORK})
  endif()
elseif (DEFINED CMAKE_FIND_FRAMEWORK)
  if (CMAKE_FIND_FRAMEWORK STREQUAL "ONLY")
    message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: CMAKE_FIND_FRAMEWORK: 'ONLY' value is not supported. 'FIRST' will be used instead.")
  elseif (NOT CMAKE_FIND_FRAMEWORK MATCHES "^(FIRST|LAST|NEVER)$")
    message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${CMAKE_FIND_FRAMEWORK}: invalid value for 'CMAKE_FIND_FRAMEWORK'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
  else()
    set (_${_PYTHON_PREFIX}_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
  endif()
endif()

1217 1218 1219 1220 1221 1222 1223 1224
# Save CMAKE_FIND_APPBUNDLE
if (DEFINED CMAKE_FIND_APPBUNDLE)
  set (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE ${CMAKE_FIND_APPBUNDLE})
else()
  unset (_${_PYTHON_PREFIX}_CMAKE_FIND_APPBUNDLE)
endif()
# To avoid app bundle lookup
set (CMAKE_FIND_APPBUNDLE "NEVER")
1225 1226 1227 1228 1229 1230 1231

# Save CMAKE_FIND_FRAMEWORK
if (DEFINED CMAKE_FIND_FRAMEWORK)
  set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
else()
  unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
endif()
1232 1233
# To avoid framework lookup
set (CMAKE_FIND_FRAMEWORK "NEVER")
1234

1235 1236 1237
# Windows Registry handling
if (DEFINED ${_PYTHON_PREFIX}_FIND_REGISTRY)
  if (NOT ${_PYTHON_PREFIX}_FIND_REGISTRY MATCHES "^(FIRST|LAST|NEVER)$")
1238
    message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_REGISTRY}: invalid value for '${_PYTHON_PREFIX}_FIND_REGISTRY'. 'FIRST', 'LAST' or 'NEVER' expected. 'FIRST' will be used instead.")
1239 1240 1241 1242 1243 1244 1245 1246
    set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
  else()
    set (_${_PYTHON_PREFIX}_FIND_REGISTRY ${${_PYTHON_PREFIX}_FIND_REGISTRY})
  endif()
else()
  set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
endif()

1247 1248
# virtual environments recognition
if (DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX})
1249 1250
  if (DEFINED ${_PYTHON_PREFIX}_FIND_VIRTUALENV)
    if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
1251
      message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_VIRTUALENV}: invalid value for '${_PYTHON_PREFIX}_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'STANDARD' expected. 'FIRST' will be used instead.")
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262
      set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV "FIRST")
    else()
      set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV ${${_PYTHON_PREFIX}_FIND_VIRTUALENV})
    endif()
  else()
    set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV FIRST)
  endif()
else()
  set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STANDARD)
endif()

1263

1264 1265
# Compute search signature
# This signature will be used to check validity of cached variables on new search
1266
set (_${_PYTHON_PREFIX}_SIGNATURE "${${_PYTHON_PREFIX}_ROOT_DIR}:${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS}:${_${_PYTHON_PREFIX}_FIND_STRATEGY}:${${_PYTHON_PREFIX}_FIND_VIRTUALENV}")
1267 1268 1269 1270
if (NOT WIN32)
  string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${${_PYTHON_PREFIX}_USE_STATIC_LIBS}:")
endif()
if (CMAKE_HOST_APPLE)
Marc Chevrier's avatar
Marc Chevrier committed
1271
  string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_FRAMEWORK}")
1272 1273
endif()
if (CMAKE_HOST_WIN32)
Marc Chevrier's avatar
Marc Chevrier committed
1274
  string (APPEND _${_PYTHON_PREFIX}_SIGNATURE ":${_${_PYTHON_PREFIX}_FIND_REGISTRY}")
1275 1276
endif()

1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289
function (_PYTHON_CHECK_DEVELOPMENT_SIGNATURE module)
  if ("Development.${module}" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
    string (TOUPPER "${module}" id)
    set (signature "${_${_PYTHON_PREFIX}_SIGNATURE}:")
    if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
      list (APPEND signature "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:")
    endif()
    if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
      list (APPEND signature "${_${_PYTHON_PREFIX}_INCLUDE_DIR}:")
    endif()
    string (MD5 signature "${signature}")
    if (signature STREQUAL _${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE)
      if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
1290 1291 1292
        _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION}
                                  ${_${_PYTHON_PREFIX}_FIND_VERSION_EXACT}
                                  CHECK_EXISTS)
1293 1294
      endif()
      if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
1295 1296 1297
        _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION}
                                      ${_${_PYTHON_PREFIX}_FIND_VERSION_EXACT}
                                      CHECK_EXISTS)
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334
      endif()
    else()
      if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
        unset (_${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE)
        unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE)
      endif()
      if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
        unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE)
      endif()
    endif()
    if (("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS
          AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
        OR ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS
          AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR))
      unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
      unset (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE CACHE)
    endif()
  endif()
endfunction()

function (_PYTHON_COMPUTE_DEVELOPMENT_SIGNATURE module)
  string (TOUPPER "${module}" id)
  if (${_PYTHON_PREFIX}_Development.${module}_FOUND)
    set (signature "${_${_PYTHON_PREFIX}_SIGNATURE}:")
    if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
      list (APPEND signature "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:")
    endif()
    if ("INCLUDE_DIR" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_${id}_ARTIFACTS)
      list (APPEND signature "${_${_PYTHON_PREFIX}_INCLUDE_DIR}:")
    endif()
    string (MD5 signature "${signature}")
    set (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE "${signature}" CACHE INTERNAL "")
  else()
    unset (_${_PYTHON_PREFIX}_DEVELOPMENT_${id}_SIGNATURE CACHE)
  endif()
endfunction()

1335

1336
unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
1337
unset (_${_PYTHON_PREFIX}_CACHED_VARS)
1338 1339 1340 1341
unset (_${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE)
unset (_${_PYTHON_PREFIX}_Compiler_REASON_FAILURE)
unset (_${_PYTHON_PREFIX}_Development_REASON_FAILURE)
unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE)
1342 1343


1344 1345 1346 1347 1348 1349 1350 1351 1352
# preamble
## For IronPython on platforms other than Windows, search for the .Net interpreter
if ("IronPython" IN_LIST _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS
    AND NOT WIN32)
  find_program (${_PYTHON_PREFIX}_DOTNET_LAUNCHER
                NAMES "mono")
endif()