From c4d15ec1d32fb472ae2b5332088883ec4003c6e0 Mon Sep 17 00:00:00 2001 From: Jean-Christophe Fillion-Robin Date: Tue, 25 Apr 2023 21:00:51 -0400 Subject: [PATCH] ENH: Enable build of macOS arm64 wheels for Python >= 3.9 Update setup.py so that these variables are passed: - CMAKE_CROSSCOMPILING - CMAKE_SYSTEM_NAME - VTKCompileTools_DIR Add support for building VTKCompileTools for x86_64 (the one provided in the wheel sdk are for arm64): - Update setup.py adding "auto_build_vtk_compile_tools()" - Add BUILDVTKCompileTools CMake module and associated test ensuring the tool can be executed on the GitHub runner --- .github/workflows/build_wheels.yml | 7 +- BuildVTKCompileTools.cmake | 92 ++++++++++++++++++++++++++ Testing/VTKCompileTools/CMakeLists.txt | 31 +++++++++ setup.py | 33 ++++++++- 4 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 BuildVTKCompileTools.cmake create mode 100644 Testing/VTKCompileTools/CMakeLists.txt diff --git a/.github/workflows/build_wheels.yml b/.github/workflows/build_wheels.yml index 002bf68..e62d6e9 100644 --- a/.github/workflows/build_wheels.yml +++ b/.github/workflows/build_wheels.yml @@ -18,7 +18,7 @@ concurrency: env: # Only support 64-bit CPython >= 3.7 - # VTK does not currently build python 3.8 arm64 wheels, so skip it too + # Only support macOS ARM 64-bit CPython >= 3.9 (older VTK wheels and SDKs not available) CIBW_SKIP: "cp27-* cp35-* cp36-* cp37-* pp* *-manylinux_i686 *-musllinux_* *-win32 cp38-macosx_arm64" # Need to match the version used by VTK @@ -27,11 +27,8 @@ env: # In the Linux docker container, install the wheel SDKs to this location CIBW_ENVIRONMENT_LINUX: VTK_WHEEL_SDK_INSTALL_PATH=/vtk-wheel-sdk - # NOTE: cross-compilation is not currently working for us for arm64. - # We are going to turn it off and build them manually until GitHub Actions - # makes arm64 runners available. # Build both x86_64 and arm64 (through cross-compilation) wheels on Mac - # CIBW_ARCHS_MACOS: x86_64 arm64 + CIBW_ARCHS_MACOS: x86_64 arm64 # VTK already fixes the rpaths, so we can skip this step for MacOS CIBW_REPAIR_WHEEL_COMMAND_MACOS: diff --git a/BuildVTKCompileTools.cmake b/BuildVTKCompileTools.cmake new file mode 100644 index 0000000..8ba684d --- /dev/null +++ b/BuildVTKCompileTools.cmake @@ -0,0 +1,92 @@ +cmake_minimum_required(VERSION 3.15) + +function(display_status msg) + message(STATUS "") + message(STATUS "${msg}") + message(STATUS "") +endfunction() + +# +# Download and build VTKCompileTools +# + +if(NOT DEFINED VTKCompileTools_DIR) + message(FATAL_ERROR "Variable VTKCompileTools_DIR is not defined") +endif() + +if(NOT DEFINED VTKCompileTools_POPULATE_DIR) + message(FATAL_ERROR "Variable VTKCompileTools_POPULATE_DIR is not defined") +endif() + +set(proj "vtk-compile-tools") + +display_status("${proj} - VTKCompileTools_DIR:${VTKCompileTools_DIR}") + +if(NOT DEFINED VTK_SOURCE_DIR) + + set(VTK_SOURCE_DIR ${VTKCompileTools_POPULATE_DIR}/VTK) + + if(NOT DEFINED VTK_WHEEL_SDK_VERSION) + message(FATAL_ERROR "Variable VTK_WHEEL_SDK_VERSION is not defined") + endif() + display_status("${proj} - VTK_WHEEL_SDK_VERSION:${VTK_WHEEL_SDK_VERSION}") + + include(FetchContent) + FetchContent_Populate(${proj} + SOURCE_DIR ${VTK_SOURCE_DIR} + BINARY_DIR ${VTKCompileTools_POPULATE_DIR}/${proj}-build + SUBBUILD_DIR ${VTKCompileTools_POPULATE_DIR}/${proj}-subbuild + GIT_REPOSITORY "https://github.com/Kitware/VTK.git" + GIT_TAG v${VTK_WHEEL_SDK_VERSION} + GIT_SHALLOW 1 + GIT_PROGRESS 1 + ) +else() + display_status("${proj} - Skipping VTK download (VTK_SOURCE_DIR is defined)") +endif() + +display_status("${proj} - VTK_SOURCE_DIR:${VTK_SOURCE_DIR}") + +display_status("${proj} - Configuring ${VTKCompileTools_DIR}") +execute_process( + COMMAND + ${CMAKE_COMMAND} + -DVTK_BUILD_COMPILE_TOOLS_ONLY:BOOL=ON + -DCMAKE_BUILD_TYPE:STRING=Release + -DVTK_BUILD_ALL_MODULES:BOOL=OFF + -DBUILD_SHARED_LIBS:BOOL=ON + -DVTK_BUILD_EXAMPLES:BOOL=OFF + -DVTK_BUILD_TESTING:BOOL=OFF + -DVTK_ENABLE_LOGGING:BOOL=OFF + -S ${VTK_SOURCE_DIR} + -B ${VTKCompileTools_DIR} + ) + +include(ProcessorCount) +ProcessorCount(nproc) + +display_status("${proj} - Building ${VTKCompileTools_DIR} [--parallel ${nproc}]") +execute_process( + COMMAND + ${CMAKE_COMMAND} + --build ${VTKCompileTools_DIR} + --config Release + --parallel ${nproc} + ) + +# +# Build VTKCompileToolsTest +# + +display_status("${proj} - Testing ${VTKCompileTools_DIR}") + +set(test_proj_src_dir ${CMAKE_CURRENT_LIST_DIR}/Testing/VTKCompileTools) +set(test_proj_bld_dir ${VTKCompileTools_POPULATE_DIR}/VTKCompileToolsTest-build) + +execute_process( + COMMAND + ${CMAKE_COMMAND} + -DVTKCompileTools_DIR:PATH=${VTKCompileTools_DIR} + -S ${test_proj_src_dir} + -B ${test_proj_bld_dir} + ) \ No newline at end of file diff --git a/Testing/VTKCompileTools/CMakeLists.txt b/Testing/VTKCompileTools/CMakeLists.txt new file mode 100644 index 0000000..9ca8782 --- /dev/null +++ b/Testing/VTKCompileTools/CMakeLists.txt @@ -0,0 +1,31 @@ +cmake_minimum_required(VERSION 3.12...3.16 FATAL_ERROR) + +project(VTKCompileToolsTest) + +find_package(VTKCompileTools REQUIRED) + +function(display_status msg) + message(STATUS "") + message(STATUS "${msg}") + message(STATUS "") +endfunction() + +function(check_compiletools_exectuable target_name) + display_status("Setting ${target_name}_EXECUTABLE") + get_target_property(${target_name}_EXECUTABLE VTKCompileTools::${target_name} IMPORTED_LOCATION_RELEASE) + if(NOT EXISTS ${${target_name}_EXECUTABLE}) + message(FATAL_ERROR "${target_name}_EXECUTABLE set to an nonexistent path: ${${target_name}_EXECUTABLE}") + endif() + + display_status("Running ${${target_name}_EXECUTABLE}") + execute_process( + COMMAND ${${target_name}_EXECUTABLE} --help + RESULT_VARIABLE result + ) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Failed to run ${${target_name}_EXECUTABLE}") + endif() +endfunction() + +check_compiletools_exectuable("WrapHierarchy") +check_compiletools_exectuable("WrapPython") \ No newline at end of file diff --git a/setup.py b/setup.py index 5a0a3bf..5e5f943 100644 --- a/setup.py +++ b/setup.py @@ -119,6 +119,32 @@ def auto_download_vtk_external_module(): return external_module_path.as_posix() +def auto_build_vtk_compile_tools(): + """Automatically download the VTK sources and build the compile tools. + + Returns the path to the VTKCompileTools build direcory. + """ + + sdk_version = vtk_wheel_sdk_version() + + wheel_sdk_name = vtk_wheel_sdk_name(sdk_version=sdk_version) + + populate_path = Path("..").resolve() / f"{wheel_sdk_name}-deps/VTKCompileTools" + compile_tools_path = Path("..").resolve() / f"{wheel_sdk_name}-deps/VTKCompileTools-build" + + script_path = str(vtk_module_source_dir / "BuildVTKCompileTools.cmake") + + cmd = [ + "cmake", + f"-DVTKCompileTools_POPULATE_DIR:PATH={populate_path}", + f"-DVTK_WHEEL_SDK_VERSION:STRING={sdk_version}", + f"-DVTKCompileTools_DIR:PATH={compile_tools_path}", + "-P", script_path, + ] + subprocess.check_call(cmd) + return compile_tools_path.as_posix() + + vtk_wheel_sdk_path = os.getenv("VTK_WHEEL_SDK_PATH") if vtk_wheel_sdk_path is None: vtk_wheel_sdk_path = auto_download_vtk_wheel_sdk() @@ -173,10 +199,15 @@ def auto_download_vtk_external_module(): cmake_args.append("-DVTK_USE_COCOA:BOOL=ON") if os.getenv("ARCHFLAGS") == "-arch arm64": + cmake_args.append("-DCMAKE_CROSSCOMPILING:BOOL=ON") + # We are cross-compiling and need to set CMAKE_SYSTEM_NAME as well. - # NOTE: we haven"t actually succeeded in cross-compiling this module. cmake_args.append("-DCMAKE_SYSTEM_NAME=Darwin") + vtk_compile_tools_dir = auto_build_vtk_compile_tools() + cmake_args.append(f"-DVTKCompileTools_DIR:PATH={vtk_compile_tools_dir}") + + long_description = (vtk_module_source_dir / "README.md").read_text(encoding="utf-8") setup(