From f6e093f7373266f764bd5fe47dbd829f31b89729 Mon Sep 17 00:00:00 2001 From: Alex Reinking Date: Tue, 3 Sep 2024 12:37:20 -0400 Subject: [PATCH] Make apps testable from pip package. --- cmake/HalideGeneratorHelpers.cmake | 16 ++++++---- python_bindings/CMakeLists.txt | 32 ++----------------- python_bindings/apps/CMakeLists.txt | 14 +++++++- python_bindings/cmake/AddPythonTest.cmake | 27 ++++++++++++++++ .../packaging/Halide_PythonConfig.cmake.in | 3 ++ python_bindings/tutorial/CMakeLists.txt | 8 ++--- test/autoschedulers/li2018/CMakeLists.txt | 6 ++-- 7 files changed, 62 insertions(+), 44 deletions(-) create mode 100644 python_bindings/cmake/AddPythonTest.cmake diff --git a/cmake/HalideGeneratorHelpers.cmake b/cmake/HalideGeneratorHelpers.cmake index d953c952e4b1..dcf802ca162f 100644 --- a/cmake/HalideGeneratorHelpers.cmake +++ b/cmake/HalideGeneratorHelpers.cmake @@ -131,7 +131,7 @@ function(add_halide_generator TARGET) set(stub_file "${CMAKE_CURRENT_BINARY_DIR}/${TARGET}.${GEN_NAME}.${MODULE_NAME}.py_stub_generated.cpp") file(CONFIGURE OUTPUT "${stub_file}" CONTENT "${stub_text}" @ONLY) - Python3_add_library(${TARGET}_pystub MODULE WITH_SOABI "${stub_file}" ${ARG_SOURCES}) + Python_add_library(${TARGET}_pystub MODULE WITH_SOABI "${stub_file}" ${ARG_SOURCES}) set_target_properties(${TARGET}_pystub PROPERTIES CXX_VISIBILITY_PRESET hidden VISIBILITY_INLINES_HIDDEN ON @@ -398,16 +398,17 @@ function(_Halide_compute_generator_cmd) # TODO: Python Generators need work to support crosscompiling (https://github.com/halide/Halide/issues/7014) if (NOT TARGET Halide::Python) - message(FATAL_ERROR "This version of Halide was built without support for Python bindings; rebuild using WITH_PYTHON_BINDINGS=ON to use this rule with Python Generators.") + message(FATAL_ERROR "Missing Halide::Python. Load the Python component " + "in find_package() or set WITH_PYTHON_BINDINGS=ON if in tree.") endif () - if (NOT TARGET Python3::Interpreter) - message(FATAL_ERROR "You must call find_package(Python3) in your CMake code in order to use this rule with Python Generators.") + if (NOT TARGET Python::Interpreter) + message(FATAL_ERROR "Missing Python::Interpreter. Missing call to find_package(Python 3)?") endif () set("${ARG_OUT_COMMAND}" - ${CMAKE_COMMAND} -E env "PYTHONPATH=$>" -- - ${Halide_PYTHON_LAUNCHER} "$" $ + ${CMAKE_COMMAND} -E env "PYTHONPATH=$/..>" -- + ${Halide_PYTHON_LAUNCHER} "$" $ PARENT_SCOPE) set("${ARG_OUT_DEPENDS}" ${ARG_FROM} Halide::Python ${py_src} PARENT_SCOPE) endfunction() @@ -794,7 +795,7 @@ function(add_halide_python_extension_library TARGET) DEPENDS Halide::GenRT VERBATIM) - Python3_add_library(${TARGET} MODULE WITH_SOABI ${pycpps} ${pyext_module_definition_src}) + Python_add_library(${TARGET} MODULE WITH_SOABI ${pycpps} ${pyext_module_definition_src}) target_link_libraries(${TARGET} PRIVATE ${ARG_HALIDE_LIBRARIES}) target_compile_definitions(${TARGET} PRIVATE # Skip the default module-definition code in each file @@ -802,6 +803,7 @@ function(add_halide_python_extension_library TARGET) # Gotta explicitly specify the module name and function(s) for this mode HALIDE_PYTHON_EXTENSION_MODULE_NAME=${ARG_MODULE_NAME} "HALIDE_PYTHON_EXTENSION_FUNCTIONS=${function_names}") + target_compile_features(${TARGET} PRIVATE cxx_std_17) set_target_properties(${TARGET} PROPERTIES OUTPUT_NAME ${ARG_MODULE_NAME}) _Halide_target_export_single_symbol(${TARGET} "PyInit_${ARG_MODULE_NAME}") endfunction() diff --git a/python_bindings/CMakeLists.txt b/python_bindings/CMakeLists.txt index 715e22fc3072..2d3a7ac77da9 100644 --- a/python_bindings/CMakeLists.txt +++ b/python_bindings/CMakeLists.txt @@ -44,7 +44,7 @@ cmake_dependent_option( # Development.Module and Development.Embed. We don't need the Embed # part, so only requesting Module avoids failures when Embed is not # available, as is the case in the manylinux Docker images. -find_package(Python3 3.8 REQUIRED Interpreter Development.Module) +find_package(Python 3.8 REQUIRED Interpreter Development.Module) if (WITH_PYTHON_BINDINGS) find_package(pybind11 2.10.4 REQUIRED) @@ -56,34 +56,8 @@ if (NOT Halide_ENABLE_RTTI OR NOT Halide_ENABLE_EXCEPTIONS) message(FATAL_ERROR "Python bindings require RTTI and exceptions to be enabled.") endif () -## -# A helper for creating tests with correct PYTHONPATH and sanitizer preloading -## - -function(add_python_test) - cmake_parse_arguments(ARG "" "FILE;LABEL" "PYTHONPATH;ENVIRONMENT;TEST_ARGS" ${ARGN}) - - list(PREPEND ARG_PYTHONPATH "$>") - list(TRANSFORM ARG_PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:") - - list(PREPEND ARG_ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}") - - cmake_path(GET ARG_FILE STEM test_name) - set(test_name "${ARG_LABEL}_${test_name}") - - add_test( - NAME "${test_name}" - COMMAND ${Halide_PYTHON_LAUNCHER} "$" "$" ${ARG_TEST_ARGS} - ) - set_tests_properties( - "${test_name}" - PROPERTIES - LABELS "python" - ENVIRONMENT "${ARG_ENVIRONMENT}" - ENVIRONMENT_MODIFICATION "${ARG_PYTHONPATH}" - ) -endfunction() - +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") +include(AddPythonTest) ## # Add our sources to this sub-tree. diff --git a/python_bindings/apps/CMakeLists.txt b/python_bindings/apps/CMakeLists.txt index e63b38e8f31e..ebaf96b0de40 100644 --- a/python_bindings/apps/CMakeLists.txt +++ b/python_bindings/apps/CMakeLists.txt @@ -1,3 +1,12 @@ +cmake_minimum_required(VERSION 3.28) +project(Halide_Python_apps) + +if (PROJECT_IS_TOP_LEVEL) + enable_testing() +endif () + +find_package(Halide REQUIRED COMPONENTS Python) + if (Halide_TARGET MATCHES "wasm") message(WARNING "Python apps are skipped under WASM.") return() @@ -13,6 +22,9 @@ if (NOT WITH_AUTOSCHEDULERS) return() endif () +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../cmake") +include(AddPythonTest) + set(TEST_TMPDIR "$") set(TEST_IMAGES_DIR "$") @@ -53,7 +65,7 @@ foreach (app IN LISTS APPS) MODULE_NAME ${G} HALIDE_LIBRARIES app_aot_${G}) list(APPEND DEPS app_ext_${G}) - endforeach() + endforeach () set(app_src "${app}_app.py") add_python_test( diff --git a/python_bindings/cmake/AddPythonTest.cmake b/python_bindings/cmake/AddPythonTest.cmake new file mode 100644 index 000000000000..4cf12fc4316e --- /dev/null +++ b/python_bindings/cmake/AddPythonTest.cmake @@ -0,0 +1,27 @@ +## +# A helper for creating tests with correct PYTHONPATH and sanitizer preloading +## + +function(add_python_test) + cmake_parse_arguments(ARG "" "FILE;LABEL" "PYTHONPATH;ENVIRONMENT;TEST_ARGS" ${ARGN}) + + list(PREPEND ARG_PYTHONPATH "$/..>") + list(TRANSFORM ARG_PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:") + + list(PREPEND ARG_ENVIRONMENT "HL_TARGET=${Halide_TARGET};HL_JIT_TARGET=${Halide_TARGET}") + + cmake_path(GET ARG_FILE STEM test_name) + set(test_name "${ARG_LABEL}_${test_name}") + + add_test( + NAME "${test_name}" + COMMAND ${Halide_PYTHON_LAUNCHER} "$" "$" ${ARG_TEST_ARGS} + ) + set_tests_properties( + "${test_name}" + PROPERTIES + LABELS "python" + ENVIRONMENT "${ARG_ENVIRONMENT}" + ENVIRONMENT_MODIFICATION "${ARG_PYTHONPATH}" + ) +endfunction() diff --git a/python_bindings/packaging/Halide_PythonConfig.cmake.in b/python_bindings/packaging/Halide_PythonConfig.cmake.in index a20007705891..12a31690805c 100644 --- a/python_bindings/packaging/Halide_PythonConfig.cmake.in +++ b/python_bindings/packaging/Halide_PythonConfig.cmake.in @@ -1,6 +1,9 @@ cmake_minimum_required(VERSION 3.28) @PACKAGE_INIT@ +include(CMakeFindDependencyMacro) +find_dependency(Python 3 COMPONENTS Interpreter Development.Module) + include("${CMAKE_CURRENT_LIST_DIR}/Halide_Python-targets.cmake") check_required_components(${CMAKE_FIND_PACKAGE_NAME}) diff --git a/python_bindings/tutorial/CMakeLists.txt b/python_bindings/tutorial/CMakeLists.txt index 33f934a154d6..285ed1ae3d08 100644 --- a/python_bindings/tutorial/CMakeLists.txt +++ b/python_bindings/tutorial/CMakeLists.txt @@ -19,7 +19,7 @@ set(tests lesson_12_using_the_gpu.py lesson_13_tuples.py lesson_14_types.py - ) +) set(PYPATH_lesson_10_aot_compilation_run "$") @@ -64,9 +64,9 @@ else () # This target allows CMake to build lesson_10_halide.so (or whatever the correct extension is) as part of the tests # later. It is excluded from ALL since it isn't valid to build outside of this context. - Python3_add_library(lesson_10_halide MODULE EXCLUDE_FROM_ALL - lesson_10_halide.py.cpp - lesson_10_halide.o) + Python_add_library(lesson_10_halide MODULE EXCLUDE_FROM_ALL + lesson_10_halide.py.cpp + lesson_10_halide.o) target_link_libraries(lesson_10_halide PRIVATE Halide::Runtime) diff --git a/test/autoschedulers/li2018/CMakeLists.txt b/test/autoschedulers/li2018/CMakeLists.txt index 3eac046f594c..2d4db3070554 100644 --- a/test/autoschedulers/li2018/CMakeLists.txt +++ b/test/autoschedulers/li2018/CMakeLists.txt @@ -26,14 +26,14 @@ if (WITH_PYTHON_BINDINGS) if (Halide_TARGET MATCHES "webgpu") message(WARNING "li2018_gradient_autoscheduler_test_py is not supported with WebGPU.") else() - find_package(Python3 REQUIRED COMPONENTS Interpreter Development.Module) + find_package(Python 3.8 REQUIRED COMPONENTS Interpreter Development.Module) add_test( NAME li2018_gradient_autoscheduler_test_py - COMMAND ${Halide_PYTHON_LAUNCHER} "$" "${CMAKE_CURRENT_SOURCE_DIR}/test.py" $ + COMMAND ${Halide_PYTHON_LAUNCHER} "$" "${CMAKE_CURRENT_SOURCE_DIR}/test.py" $ ) - set(PYTHONPATH "$>") + set(PYTHONPATH "$/..>") list(TRANSFORM PYTHONPATH PREPEND "PYTHONPATH=path_list_prepend:") set_tests_properties(li2018_gradient_autoscheduler_test_py PROPERTIES