From b4963834f4599d5c5d560da1a6034d92477cb5e1 Mon Sep 17 00:00:00 2001 From: Daniel Jones Date: Sun, 12 Nov 2023 17:33:49 +0000 Subject: [PATCH] Windows support: Update setup.py and CMake config for Windows build --- CMakeLists.txt | 30 ++++++++++----------- auxiliary/libs/signalflow/__init__.py | 7 +++++ setup.py | 38 ++++++++++++++++++++++----- 3 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 auxiliary/libs/signalflow/__init__.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 46e7218e..57b9b8d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,14 +50,12 @@ set(CMAKE_MACOSX_RPATH 1) #------------------------------------------------------------------------------- # Shared compiler flags. #------------------------------------------------------------------------------- -add_compile_options( - -pedantic - -fPIC - ) if (NOT MSVC) add_compile_options( - -Wall + -pedantic + -fPIC + -Wall ) endif() @@ -108,6 +106,8 @@ if (CMAKE_BUILD_PYTHON) if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") add_link_options(-w -undefined dynamic_lookup) + elseif (CMAKE_SYSTEM_NAME STREQUAL "Windows") + set(CMAKE_SHARED_LIBRARY_SUFFIX ".pyd") endif() endif() @@ -127,10 +127,11 @@ add_compile_definitions(SIGNALFLOW_VERSION="${SIGNALFLOW_VERSION}") #------------------------------------------------------------------------------- set(SOUNDIO_BUILD_DIR "" CACHE PATH "Path to built SoundIO library (will use find_library if blank)") + if (SOUNDIO_BUILD_DIR) set(SOUNDIO_INCLUDE_DIR "${SOUNDIO_BUILD_DIR}/.." CACHE PATH "Path to SoundIO include directory (ignored if SOUNDIO_BUILD_DIR is blank") add_definitions(-DHAVE_SOUNDIO) - target_link_libraries(signalflow "${SOUNDIO_BUILD_DIR}/$/soundio.lib") + target_link_libraries(signalflow "${SOUNDIO_BUILD_DIR}/x64-Debug/soundio.lib") include_directories(signalflow "${SOUNDIO_BUILD_DIR}/$/") include_directories(signalflow "${SOUNDIO_INCLUDE_DIR}/") else() @@ -146,10 +147,11 @@ endif() set(SNDFILE_BUILD_DIR "" CACHE PATH "Path to build sndfile library (will use find_library if blank)") + if (SNDFILE_BUILD_DIR) set(SNDFILE_INCLUDE_DIR "${SNDFILE_BUILD_DIR}/../include" CACHE PATH "Path to sndfile include directory (ignored if SNDFILE_BUILD_DIR is blank") add_definitions(-DHAVE_SNDFILE) - target_link_libraries(signalflow "${SNDFILE_BUILD_DIR}/$/sndfile.lib") + target_link_libraries(signalflow "${SNDFILE_BUILD_DIR}/sndfile") include_directories(signalflow "${SNDFILE_BUILD_DIR}/include/") include_directories(signalflow "${SNDFILE_INCLUDE_DIR}/") else() @@ -168,10 +170,10 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") if (FFTW_BUILD_DIR) include_directories("${FFTW_BUILD_DIR}") add_definitions(-DFFT_FFTW) - target_link_libraries(signalflow - "${FFTW_BUILD_DIR}/libfftw3-3.lib" - "${FFTW_BUILD_DIR}/libfftw3f-3.lib" - "${FFTW_BUILD_DIR}/libfftw3l-3.lib" + target_link_libraries(signalflow + "${FFTW_BUILD_DIR}/libfftw3-3" + "${FFTW_BUILD_DIR}/libfftw3f-3" + "${FFTW_BUILD_DIR}/libfftw3l-3" ) else() find_library(FFTW3F fftw3f) @@ -179,10 +181,8 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") message("Found fftw3f") target_link_libraries(signalflow ${FFTW3F}) add_definitions(-DFFT_FFTW) - else() - # if (CMAKE_SYSTEM_NAME STREQUAL "Linux") - message(FATAL_ERROR "Couldn't find fftw3f") - # endif() + else() + message(FATAL_ERROR "Couldn't find fftw3f") endif() endif() endif(NOT CMAKE_SYSTEM_NAME STREQUAL "Darwin") diff --git a/auxiliary/libs/signalflow/__init__.py b/auxiliary/libs/signalflow/__init__.py new file mode 100644 index 00000000..fbfa7386 --- /dev/null +++ b/auxiliary/libs/signalflow/__init__.py @@ -0,0 +1,7 @@ +""" +This package is used on Windows only, as a container for the .pyd file and +platform-specific DLLs. + +On Linux and macOS, the bare .so file is copied. +""" +from .signalflow import * diff --git a/setup.py b/setup.py index 2c34ebcb..e15beff1 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ import os +import sys +import shutil import subprocess from setuptools import setup, Extension @@ -10,6 +12,7 @@ def __init__(self, name, sourcedir=''): Extension.__init__(self, name, sources=[]) self.sourcedir = os.path.abspath(sourcedir) + class CMakeBuild(build_ext): def run(self): for ext in self.extensions: @@ -23,6 +26,7 @@ def build_extension(self, ext): build_args = ['--config', cfg, '-j', str(cpu_count)] print("Building signalflow version " + self.distribution.get_version()) + print("Detected %d CPUs" % os.cpu_count()) cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, '-DCMAKE_BUILD_PYTHON=1', '-DCMAKE_BUILD_TYPE=' + cfg, @@ -36,24 +40,46 @@ def build_extension(self, ext): subprocess.check_call(['cmake', ext.sourcedir] + cmake_args, cwd=self.build_temp, env=env) subprocess.check_call(['cmake', '--build', '.'] + build_args, cwd=self.build_temp) + # -------------------------------------------------------------------------------- + # On Windows, bundle the .pyd into a package. + # This will also contain the .dlls after repairing the wheel with delvewheel. + # -------------------------------------------------------------------------------- + if os.name == "nt": + libname = "signalflow.pyd" + shutil.copy(os.path.join(self.build_temp, cfg, libname), "auxiliary/libs/signalflow") + + +signalflow_packages = ['signalflow_midi', 'signalflow-stubs', 'signalflow_examples'] +signalflow_package_data = [] +if sys.platform == 'win32': + # -------------------------------------------------------------------------------- + # On Linux and macOS, the bare .so file is packaged directly via ext_modules. + # On Windows, a separate package is created, into which the .pyd file and DLLs + # are copied. + # -------------------------------------------------------------------------------- + signalflow_packages = ['signalflow'] + signalflow_packages + signalflow_package_data = ['*.pyd'] + setup( name='signalflow', version='0.4.2', author='Daniel Jones', author_email='dan@erase.net', description='signalflow', - long_description = open("README.md", "r").read(), - long_description_content_type = "text/markdown", + long_description=open("README.md", "r").read(), + long_description_content_type="text/markdown", ext_modules=[CMakeExtension('signalflow')], cmdclass=dict(build_ext=CMakeBuild), setup_requires=['pytest-runner', 'pybind11-stubgen'], install_requires=['numpy'], tests_require=['pytest', 'numpy', 'scipy'], - package_dir={ '': 'auxiliary/libs' }, - packages=['signalflow_midi', 'signalflow-stubs', 'signalflow_examples'], + package_dir={'': 'auxiliary/libs'}, + packages=signalflow_packages, include_package_data=True, # signalflow-stubs contains type hint data in a .pyi file, per PEP 561 - package_data={"signalflow-stubs": ["*.pyi"]}, + package_data={ + "signalflow-stubs": ["*.pyi"], + "signalflow": signalflow_package_data + }, scripts=['source/bin/signalflow'] ) -