FindPython: enforce artifacts consistency when cross-compiling

Fixes: #26696
This commit is contained in:
Marc Chevrier 2025-02-16 18:27:23 +01:00
parent 7065c7a586
commit 5c1521c54d
24 changed files with 325 additions and 19 deletions

View File

@ -98,6 +98,7 @@ Policies Introduced by CMake 4.1
.. toctree::
:maxdepth: 1
CMP0190: FindPython enforce consistency in cross-compiling mode. </policy/CMP0190>
CMP0189: TARGET_PROPERTY evaluates LINK_LIBRARIES properties transitively. </policy/CMP0189>
CMP0188: The FindGCCXML module is removed. </policy/CMP0188>
CMP0187: Include source file without an extension after the same name with an extension. </policy/CMP0187>

31
Help/policy/CMP0190.rst Normal file
View File

@ -0,0 +1,31 @@
CMP0190
-------
.. versionadded:: 4.1
Modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
enforce consistency of artifacts in cross-compiling mode.
Starting with CMake 4.1, Modules :module:`FindPython3`, :module:`FindPython2`
and :module:`FindPython` apply, in cross-compiling mode (i.e. the
:variable:`CMAKE_CROSSCOMPILING` variable is set to true), the following
constraints to the requested components:
* ``Interpreter`` or ``Compiler`` alone: the host artifacts will be searched.
* ``Interpreter`` or ``Compiler`` with ``Development`` or any sub-component:
The target artifacts will be searched. In this case, the
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable must be defined and will
be used to execute the interpreter or the compiler.
This policy provides compatibility with projects that expect the legacy
behavior.
The ``OLD`` behavior for this policy does not enforce consistency in
cross-compiling mode and will, potentially, returns a mix of artifacts
(i.e. host and target artifacts).
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
.. include:: STANDARD_ADVICE.txt
.. include:: DEPRECATED.txt

View File

@ -0,0 +1,6 @@
FindPython-crosscompiling-consistency
-------------------------------------
* Modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
enforce consistency of artifacts in cross-compiling mode. This prevent mixing
host and target artifacts. See policy :policy:`CMP0190` for more information.

View File

@ -48,6 +48,21 @@ If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
``Development.Module`` and ``Development.Embed``.
.. versionchanged:: 4.1
In a cross-compiling mode (i.e. the :variable:`CMAKE_CROSSCOMPILING` variable
is defined to true), the following constraints, when the policy
:policy:`CMP0190` is set to ``NEW``, now apply to the requested components:
* ``Interpreter`` or ``Compiler`` alone: the host artifacts will be searched.
* ``Interpreter`` or ``Compiler`` with ``Development`` or any sub-component:
The target artifacts will be searched. In this case, the
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable must be defined and will
be used to execute the interpreter or the compiler.
When both host and target artifacts are needed, two different calls to the
:command:`find_package` command should be done. The
``Python_ARTIFACTS_PREFIX`` variable can be helpful in this situation.
To ensure consistent versions between components ``Interpreter``, ``Compiler``,
``Development`` (or one of its sub-components) and ``NumPy``, specify all
components at the same time:

View File

@ -39,13 +39,17 @@ include(FindPackageHandleStandardArgs)
# helper commands
#
macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG)
if (${_PYTHON_BASE}_FIND_REQUIRED)
if (${ARGC} GREATER 1 AND "${ARGV1}" STREQUAL "FATAL")
set (_${_PYTHON_PREFIX}_FATAL TRUE)
endif()
if (${_PYTHON_BASE}_FIND_REQUIRED OR _${_PYTHON_PREFIX}_FATAL)
message (FATAL_ERROR "${_PYTHON_MSG}")
else()
if (NOT ${_PYTHON_BASE}_FIND_QUIETLY)
message(STATUS "${_PYTHON_MSG}")
endif ()
endif()
unset(_${_PYTHON_PREFIX}_FATAL)
set (${_PYTHON_BASE}_FOUND FALSE)
set (${_PYTHON_PREFIX}_FOUND FALSE)
@ -528,7 +532,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME)
endif()
if ("Interpreter" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS AND _${_PYTHON_PREFIX}_EXECUTABLE
AND NOT CMAKE_CROSSCOMPILING)
AND (_${_PYTHON_PREFIX}_CROSSCOMPILING OR NOT CMAKE_CROSSCOMPILING))
if (NAME STREQUAL "PREFIX")
execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))\nexcept Exception:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))"
RESULT_VARIABLE _result
@ -846,6 +850,11 @@ function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME)
return()
endif()
if (_${_PYTHON_PREFIX}_CROSSCOMPILING)
set (${_PYTHON_PGL_NAME} "${CMAKE_CROSSCOMPILING_EMULATOR}" PARENT_SCOPE)
return()
endif()
if ("IronPython" IN_LIST _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS
AND NOT SYSTEM_NAME MATCHES "Windows|Linux")
if (_PGL_INTERPRETER)
@ -1001,7 +1010,7 @@ function (_PYTHON_VALIDATE_INTERPRETER)
if (CMAKE_SIZEOF_VOID_P AND ("Development.Module" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
OR "Development.SABIModule" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
OR "Development.Embed" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS)
AND NOT CMAKE_CROSSCOMPILING)
AND (_${_PYTHON_PREFIX}_CROSSCOMPILING OR NOT CMAKE_CROSSCOMPILING))
# In this case, interpreter must have same architecture as environment
execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c
"import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))"
@ -1440,6 +1449,22 @@ if (${_PYTHON_BASE}_FIND_REQUIRED_Development)
set (${_PYTHON_BASE}_FIND_REQUIRED_Development.Embed TRUE)
endif()
## handle cross-compiling constraints for components:
## If Interpreter and/or Compiler are specified with Development components
## the CMAKE_CROSSCOMPILING_EMULATOR variable should be defined
cmake_policy (GET CMP0190 _${_PYTHON_PREFIX}_CROSSCOMPILING_POLICY)
unset (_${_PYTHON_PREFIX}_CROSSCOMPILING)
if (CMAKE_CROSSCOMPILING AND _${_PYTHON_PREFIX}_CROSSCOMPILING_POLICY STREQUAL "NEW")
if (${_PYTHON_BASE}_FIND_COMPONENTS MATCHES "Interpreter|Compiler"
AND ${_PYTHON_BASE}_FIND_COMPONENTS MATCHES "Development")
if (CMAKE_CROSSCOMPILING_EMULATOR)
set (_${_PYTHON_PREFIX}_CROSSCOMPILING TRUE)
else()
_python_display_failure ("${_PYTHON_PREFIX}: When cross-compiling, Interpreter and/or Compiler components cannot be searched when CMAKE_CROSSCOMPILING_EMULATOR variable is not specified (see policy CMP0190)." FATAL)
endif()
endif()
endif()
unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_MODULE_ARTIFACTS)
unset (_${_PYTHON_PREFIX}_FIND_DEVELOPMENT_SABIMODULE_ARTIFACTS)
@ -2827,7 +2852,8 @@ if (("Development.Module" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
# if python interpreter is found, use it to look-up for artifacts
# to ensure consistency between interpreter and development environments.
# If not, try to locate a compatible config tool
if ((NOT ${_PYTHON_PREFIX}_Interpreter_FOUND OR CMAKE_CROSSCOMPILING)
if ((NOT ${_PYTHON_PREFIX}_Interpreter_FOUND
OR (NOT _${_PYTHON_PREFIX}_CROSSCOMPILING AND CMAKE_CROSSCOMPILING))
AND "CPython" IN_LIST _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS)
set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
@ -3093,7 +3119,9 @@ if (("Development.Module" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
if ("LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS)
if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE)
if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG)
if ((${_PYTHON_PREFIX}_Interpreter_FOUND
AND (_${_PYTHON_PREFIX}_CROSSCOMPILING OR NOT CMAKE_CROSSCOMPILING))
OR _${_PYTHON_PREFIX}_CONFIG)
# retrieve root install directory
_python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX)
@ -3361,7 +3389,9 @@ if (("Development.Module" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
NO_DEFAULT_PATH)
else()
if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG)
if ((${_PYTHON_PREFIX}_Interpreter_FOUND
AND (_${_PYTHON_PREFIX}_CROSSCOMPILING OR NOT CMAKE_CROSSCOMPILING))
OR _${_PYTHON_PREFIX}_CONFIG)
# retrieve root install directory
_python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX)
@ -3622,7 +3652,9 @@ if (("Development.Module" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS
break()
endif()
if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG)
if ((${_PYTHON_PREFIX}_Interpreter_FOUND
AND (_${_PYTHON_PREFIX}_CROSSCOMPILING OR NOT CMAKE_CROSSCOMPILING))
OR _${_PYTHON_PREFIX}_CONFIG)
_python_get_config_var (_${_PYTHON_PREFIX}_INCLUDE_DIRS INCLUDES)
find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR

View File

@ -41,6 +41,21 @@ If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
``Development.Module`` and ``Development.Embed``.
.. versionchanged:: 4.1
In a cross-compiling mode (i.e. the :variable:`CMAKE_CROSSCOMPILING` variable
is defined to true), the following constraints, when the policy
:policy:`CMP0190` is set to ``NEW``, now apply to the requested components:
* ``Interpreter`` or ``Compiler`` alone: the host artifacts will be searched.
* ``Interpreter`` or ``Compiler`` with ``Development`` or any sub-component:
The target artifacts will be searched. In this case, the
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable must be defined and will
be used to execute the interpreter or the compiler.
When both host and target artifacts are needed, two different calls to the
:command:`find_package` command should be done. The
``Python_ARTIFACTS_PREFIX`` variable can be helpful in this situation.
To ensure consistent versions between components ``Interpreter``, ``Compiler``,
``Development`` (or one of its sub-components) and ``NumPy``, specify all
components at the same time:

View File

@ -48,6 +48,22 @@ If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
If component ``Development`` is specified, it implies sub-components
``Development.Module`` and ``Development.Embed``.
.. versionchanged:: 4.1
In a cross-compiling mode (i.e. the :variable:`CMAKE_CROSSCOMPILING` variable
is defined to true), the following constraints, when the policy
:policy:`CMP0190` is set to ``NEW``, now apply to the requested components:
* ``Interpreter`` or ``Compiler`` alone: the host artifacts will be searched.
* ``Interpreter`` or ``Compiler`` with ``Development`` or any sub-component:
The target artifacts will be searched. In this case, the
:variable:`CMAKE_CROSSCOMPILING_EMULATOR` variable must be defined and will
be used to execute the interpreter or the compiler.
When both host and target artifacts are needed, two different calls to the
:command:`find_package` command should be done. The
``Python_ARTIFACTS_PREFIX`` variable can be helpful in this situation.
To ensure consistent versions between components ``Interpreter``, ``Compiler``,
``Development`` (or one of its sub-components) and ``NumPy``, specify all
components at the same time:

View File

@ -566,7 +566,10 @@ class cmMakefile;
SELECT(POLICY, CMP0188, "The FindGCCXML module is removed.", 4, 1, 0, WARN) \
SELECT(POLICY, CMP0189, \
"TARGET_PROPERTY evaluates LINK_LIBRARIES properties transitively.", \
4, 1, 0, WARN)
4, 1, 0, WARN) \
SELECT(POLICY, CMP0190, \
"FindPython enforce consistency in cross-compiling mode.", 4, 1, 0, \
WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \

View File

@ -423,10 +423,10 @@ endif()
add_RunCMake_test(ConfigDir)
if(CMake_TEST_FindPython2)
add_RunCMake_test(FindPython2.CPython TEST_DIR FindPython
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
"-DRunCMake_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
-DCMake_TEST_FindPython2_CPython=TRUE
-DCMake_TEST_FindPython2=TRUE)
-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}
"-DRunCMake_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
-DCMake_TEST_FindPython2_CPython=TRUE
-DCMake_TEST_FindPython2=TRUE)
set_property(TEST RunCMake.FindPython2.CPython PROPERTY LABELS Python2)
endif()
if(CMake_TEST_FindPython3)

View File

@ -1,3 +1,3 @@
cmake_minimum_required(VERSION 3.12...4.0)
cmake_minimum_required(VERSION 3.20...4.1)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,33 @@
cmake_policy(SET CMP0190 NEW)
enable_language(C)
# Search for host Interpreter
set(${PYTHON}_ARTIFACTS_PREFIX "_HOST")
find_package(${PYTHON} ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter)
unset(${PYTHON}_ARTIFACTS_PREFIX)
# Search cross-compilation artifacts
## First, built an pseudo-emulator
set(PSEUDO_EMULATOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/pseudo_emulator")
file(MAKE_DIRECTORY "${PSEUDO_EMULATOR_DIR}")
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" -DCMAKE_BUILD_TYPE=Release
-S "${CMAKE_CURRENT_SOURCE_DIR}/pseudo_emulator"
-B "${PSEUDO_EMULATOR_DIR}"
COMMAND_ERROR_IS_FATAL ANY)
execute_process(COMMAND "${CMAKE_COMMAND}" --build "${PSEUDO_EMULATOR_DIR}"
COMMAND_ERROR_IS_FATAL ANY)
## Now, configure this pseudo-emulator
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_CROSSCOMPILING_EMULATOR "${PSEUDO_EMULATOR_DIR}/pseudo_emulator")
find_package(${PYTHON} ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter Development)

View File

@ -0,0 +1,4 @@
CMake Error at .+/Support.cmake:[0-9]+ \(message\):
Python: When cross-compiling, Interpreter and/or Compiler components cannot
be searched when CMAKE_CROSSCOMPILING_EMULATOR variable is not specified
\(see policy CMP0190\).

View File

@ -0,0 +1,4 @@
CMake Error at .+/Support.cmake:[0-9]+ \(message\):
Python: When cross-compiling, Interpreter and/or Compiler components cannot
be searched when CMAKE_CROSSCOMPILING_EMULATOR variable is not specified
\(see policy CMP0190\).

View File

@ -0,0 +1,4 @@
CMake Error at .+/Support.cmake:[0-9]+ \(message\):
Python2: When cross-compiling, Interpreter and/or Compiler components
cannot be searched when CMAKE_CROSSCOMPILING_EMULATOR variable is not
specified \(see policy CMP0190\).

View File

@ -0,0 +1,4 @@
CMake Error at .+/Support.cmake:[0-9]+ \(message\):
Python3: When cross-compiling, Interpreter and/or Compiler components
cannot be searched when CMAKE_CROSSCOMPILING_EMULATOR variable is not
specified \(see policy CMP0190\).

View File

@ -0,0 +1,4 @@
cmake_policy(SET CMP0190 NEW)
include(CrossCompiling-CMP0190.cmake)

View File

@ -0,0 +1,4 @@
cmake_policy(SET CMP0190 OLD)
include(CrossCompiling-CMP0190.cmake)

View File

@ -0,0 +1,6 @@
set(CMAKE_CROSSCOMPILING TRUE)
unset(CMAKE_CROSSCOMPILING_EMULATOR)
enable_language(C)
find_package(${PYTHON} ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter Development)

View File

@ -0,0 +1,8 @@
cmake_policy(SET CMP0190 NEW)
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_CROSSCOMPILING_EMULATOR "${CMAKE_COMMAND}" -P raise-error.cmake)
enable_language(C)
find_package(${PYTHON} ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter)

View File

@ -0,0 +1,23 @@
cmake_policy(SET CMP0190 NEW)
enable_language(C)
## First, built an pseudo-emulator
set(PSEUDO_EMULATOR_DIR "${CMAKE_CURRENT_BINARY_DIR}/pseudo_emulator")
file(MAKE_DIRECTORY "${PSEUDO_EMULATOR_DIR}")
execute_process(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" -DCMAKE_BUILD_TYPE=Release
-S "${CMAKE_CURRENT_SOURCE_DIR}/pseudo_emulator"
-B "${PSEUDO_EMULATOR_DIR}"
COMMAND_ERROR_IS_FATAL ANY)
execute_process(COMMAND "${CMAKE_COMMAND}" --build "${PSEUDO_EMULATOR_DIR}"
COMMAND_ERROR_IS_FATAL ANY)
## Now, configure this pseudo-emulator
set(CMAKE_CROSSCOMPILING TRUE)
set(CMAKE_CROSSCOMPILING_EMULATOR "${PSEUDO_EMULATOR_DIR}/pseudo_emulator")
find_package(${PYTHON} ${Python_REQUESTED_VERSION} REQUIRED COMPONENTS Interpreter Development)

View File

@ -7,9 +7,10 @@ else()
endif()
function(run_python test)
set(options_args CHECK_RESULT)
set(one_value_args TYPE ACTION VARIANT STRATEGY)
set(multi_value_args OPTIONS)
cmake_parse_arguments(PARSE_ARGV 1 RP "" "${one_value_args}" "${multi_value_args}")
cmake_parse_arguments(PARSE_ARGV 1 RP "${options_args}" "${one_value_args}" "${multi_value_args}")
if(RP_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "run_python: unparsed arguments: ${RP_UNPARSED_ARGUMENTS}")
@ -37,6 +38,11 @@ function(run_python test)
list(APPEND options -DCMAKE_BUILD_TYPE=${Python_BUILD_TYPE})
endif()
if(RP_CHECK_RESULT)
set(RunCMake_TEST_EXPECT_RESULT 1)
file(READ "${RunCMake_SOURCE_DIR}/${test_name}-stderr.txt" RunCMake_TEST_EXPECT_stderr)
endif()
set(RunCMake_TEST_BINARY_DIR "${RunCMake_BINARY_DIR}/${test_name}-build")
if(options)
run_cmake_with_options(${test} ${options})
@ -121,11 +127,9 @@ function(required_artifacts)
endif()
endfunction()
function(custom_failure_message_check name components)
set(RunCMake_TEST_EXPECT_RESULT 1)
file(READ "${RunCMake_SOURCE_DIR}/CustomFailureMessage.${name}-stderr.txt" RunCMake_TEST_EXPECT_stderr)
run_python(CustomFailureMessage VARIANT "${name}" OPTIONS "-DCHECK_COMPONENTS=${components}" ${ARGN})
endfunction()
macro(custom_failure_message_check name components)
run_python(CustomFailureMessage VARIANT "${name}" CHECK_RESULT OPTIONS "-DCHECK_COMPONENTS=${components}" ${ARGN})
endmacro()
if(CMake_TEST_FindPython2_CPython)
@ -152,6 +156,23 @@ if(CMake_TEST_FindPython2_CPython)
OPTIONS -DPython_REQUESTED_VERSION=2)
run_python(VersionRange TYPE Python STRATEGY VERSION VARIANT Python.V2
OPTIONS -DPython_REQUESTED_VERSION=2)
run_python(CrossCompiling-CMP0190-OLD TYPE Python2 VARIANT Python2)
run_python(CrossCompiling-CMP0190-NEW TYPE Python2 VARIANT Python2 CHECK_RESULT)
run_python(CrossCompiling-CMP0190-OLD TYPE Python VARIANT Python.V2
OPTIONS -DPython_REQUESTED_VERSION=2)
run_python(CrossCompiling-CMP0190-NEW TYPE Python VARIANT Python.V2 CHECK_RESULT
OPTIONS -DPython_REQUESTED_VERSION=2)
run_python(CrossCompiling-HOST TYPE Python2 VARIANT Python2)
run_python(CrossCompiling-HOST TYPE Python VARIANT Python.V2
OPTIONS -DPython_REQUESTED_VERSION=2)
if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin" AND NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
run_python(CrossCompiling-TARGET TYPE Python2 VARIANT Python2)
run_python(CrossCompiling-TARGET TYPE Python VARIANT Python.V2
OPTIONS -DPython_REQUESTED_VERSION=2)
run_python(CrossCompiling-BOTH TYPE Python2 VARIANT Python2)
run_python(CrossCompiling-BOTH TYPE Python VARIANT Python.V2
OPTIONS -DPython_REQUESTED_VERSION=2)
endif()
endif()
if(CMake_TEST_FindPython3_CPython)
@ -189,6 +210,23 @@ if(CMake_TEST_FindPython3_CPython)
custom_failure_message_check("Include" "Development" -DPython3_INCLUDE_DIR=/not/found/include)
custom_failure_message_check("Multiple" "Interpreter:Development" -DPython3_EXECUTABLE=/not/found/interpreter
-DPython3_LIBRARY=/not/found/library)
run_python(CrossCompiling-CMP0190-OLD TYPE Python3 VARIANT Python3)
run_python(CrossCompiling-CMP0190-NEW TYPE Python3 VARIANT Python3 CHECK_RESULT)
run_python(CrossCompiling-CMP0190-OLD TYPE Python VARIANT Python.V3
OPTIONS -DPython_REQUESTED_VERSION=3)
run_python(CrossCompiling-CMP0190-NEW TYPE Python VARIANT Python.V3 CHECK_RESULT
OPTIONS -DPython_REQUESTED_VERSION=3)
run_python(CrossCompiling-HOST TYPE Python3 VARIANT Python3)
run_python(CrossCompiling-HOST TYPE Python VARIANT Python.V3
OPTIONS -DPython_REQUESTED_VERSION=3)
if(CMAKE_SYSTEM_NAME MATCHES "Linux|Darwin" AND NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
run_python(CrossCompiling-TARGET TYPE Python3 VARIANT Python3)
run_python(CrossCompiling-TARGET TYPE Python VARIANT Python.V3
OPTIONS -DPython_REQUESTED_VERSION=3)
run_python(CrossCompiling-BOTH TYPE Python3 VARIANT Python3)
run_python(CrossCompiling-BOTH TYPE Python VARIANT Python.V3
OPTIONS -DPython_REQUESTED_VERSION=3)
endif()
endif()
if(CMake_TEST_FindPython2_CPython OR CMake_TEST_FindPython3_CPython)

View File

@ -0,0 +1,5 @@
cmake_minimum_required(VERSION 3.22...4.1)
project(PseudoEmulator LANGUAGES C)
add_executable(pseudo_emulator pseudo_emulator.c)

View File

@ -0,0 +1,48 @@
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
static int execute(char* argv[])
{
pid_t my_pid;
int status, timeout;
struct timespec duration;
duration.tv_sec = 0;
duration.tv_nsec = 100000000;
if (0 == (my_pid = fork())) {
if (-1 == execve(argv[0], (char**)argv, NULL)) {
perror("child process execve failed");
return -1;
}
}
timeout = 100;
while (0 == waitpid(my_pid, &status, WNOHANG)) {
if (--timeout < 0) {
perror(argv[0]);
return -1;
}
nanosleep(&duration, NULL);
}
if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) {
return -1;
}
return 0;
}
int main(int argc, char* argv[])
{
if (argc < 2) {
fprintf(stderr, "%s: require at least one argument.\n", argv[0]);
return -1;
}
return execute(&argv[1]);
}

View File

@ -0,0 +1,2 @@
message(FATAL_ERROR "CROSSCOMPILING_EMULATOR erroneously used.")