From 8a4387ae3f36522cc10841c607abb8182c6f8286 Mon Sep 17 00:00:00 2001 From: Israel Fruchter Date: Sun, 9 Jun 2024 22:35:29 +0300 Subject: [PATCH] CI: download libev via conan, for windows builds to have it windows builds so far was running with having libev available and until this sync the fallback for python 3.12 was asyncio eventloop, but now we fail and not fall back to asyncio. so all unittest on windows are failing on any import from cassandra.connection. in this change we use conan to download libev, and using it to compile the driver with libev Ref: https://conan.io/center/recipes/libev --- .github/workflows/build-push.yml | 12 ++++++- MANIFEST.in | 1 + cassandra/io/libevwrapper.c | 2 ++ conanfile.py | 57 ++++++++++++++++++++++++++++++++ setup.py | 18 +++++++++- 5 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 conanfile.py diff --git a/.github/workflows/build-push.yml b/.github/workflows/build-push.yml index aad522a449..53be975be1 100644 --- a/.github/workflows/build-push.yml +++ b/.github/workflows/build-push.yml @@ -10,7 +10,7 @@ env: CIBW_BEFORE_TEST: "pip install -r {project}/test-requirements.txt" CIBW_BEFORE_BUILD_LINUX: "rm -rf ~/.pyxbld && rpm --import https://repo.almalinux.org/almalinux/RPM-GPG-KEY-AlmaLinux && yum install -y libffi-devel libev libev-devel openssl openssl-devel" CIBW_ENVIRONMENT: "CASS_DRIVER_BUILD_CONCURRENCY=2 CFLAGS='-g0 -O3'" - CIBW_SKIP: cp35* cp36* pp*i686 *musllinux* + CIBW_SKIP: cp35* cp36* cp37* pp*i686 *musllinux* CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 CIBW_MANYLINUX_PYPY_X86_64_IMAGE: manylinux_2_28 CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 @@ -63,6 +63,16 @@ jobs: run: | choco install openssl --version=3.3.1 -f -y + - name: Install Conan + if: runner.os == 'Windows' + uses: turtlebrowser/get-conan@main + + - name: configure libev for Windows + if: runner.os == 'Windows' + run: | + conan profile detect + conan install conanfile.py + - name: Install OpenSSL for MacOS if: runner.os == 'MacOs' run: | diff --git a/MANIFEST.in b/MANIFEST.in index 660db719b0..6bb26b0e5c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,3 +4,4 @@ include cassandra/io/libevwrapper.c include cassandra/*.pyx include cassandra/*.pxd include cassandra/*.h +graft build-release \ No newline at end of file diff --git a/cassandra/io/libevwrapper.c b/cassandra/io/libevwrapper.c index 99e1df30f7..bbb902b757 100644 --- a/cassandra/io/libevwrapper.c +++ b/cassandra/io/libevwrapper.c @@ -1,3 +1,5 @@ +#pragma comment(lib, "Ws2_32.Lib") + #include #include diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 0000000000..bc2b27c1c6 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,57 @@ +import json +from pathlib import Path + +from conan import ConanFile +from conan.tools.layout import basic_layout +from conan.internal import check_duplicated_generator +from conan.tools.files import save + + +CONAN_COMMANDLINE_FILENAME = "conandeps.env" + +class CommandlineDeps: + def __init__(self, conanfile): + """ + :param conanfile: ``< ConanFile object >`` The current recipe object. Always use ``self``. + """ + self._conanfile = conanfile + + def generate(self) -> None: + """ + Collects all dependencies and components, then, generating a Makefile + """ + check_duplicated_generator(self, self._conanfile) + + host_req = self._conanfile.dependencies.host + build_req = self._conanfile.dependencies.build # tool_requires + test_req = self._conanfile.dependencies.test + + content_buffer = "" + + # Filter the build_requires not activated for any requirement + dependencies = [tup for tup in list(host_req.items()) + list(build_req.items()) + list(test_req.items()) if not tup[0].build] + + for require, dep in dependencies: + # Require is not used at the moment, but its information could be used, and will be used in Conan 2.0 + if require.build: + continue + include_dir = Path(dep.package_folder) / 'include' + package_dir = Path(dep.package_folder) / 'lib' + content_buffer += json.dumps(dict(include_dirs=str(include_dir), library_dirs=str(package_dir))) + + save(self._conanfile, CONAN_COMMANDLINE_FILENAME, content_buffer) + self._conanfile.output.info(f"Generated {CONAN_COMMANDLINE_FILENAME}") + + +class python_driverConan(ConanFile): + win_bash = False + + settings = "os", "compiler", "build_type", "arch" + requires = "libev/4.33" + + def layout(self): + basic_layout(self) + + def generate(self): + pc = CommandlineDeps(self) + pc.generate() diff --git a/setup.py b/setup.py index 4a525221eb..791c8923da 100644 --- a/setup.py +++ b/setup.py @@ -15,7 +15,9 @@ from __future__ import print_function import os import sys +import json import warnings +from pathlib import Path if __name__ == '__main__' and sys.argv[1] == "gevent_nosetests": print("Running gevent tests") @@ -142,6 +144,20 @@ def __init__(self, ext): murmur3_ext = Extension('cassandra.cmurmur3', sources=['cassandra/cmurmur3.c']) +is_macos = sys.platform.startswith('darwin') + +libev_includes = ['/usr/include/libev', '/usr/local/include', '/opt/local/include', '/usr/include'] +libev_libdirs = ['/usr/local/lib', '/opt/local/lib', '/usr/lib64'] +if is_macos: + libev_includes.extend(['/opt/homebrew/include', os.path.expanduser('~/homebrew/include')]) + libev_libdirs.extend(['/opt/homebrew/lib']) + +conan_envfile = Path(__file__).parent / 'build-release/conan/conandeps.env' +if conan_envfile.exists(): + conan_paths = json.loads(conan_envfile.read_text()) + libev_includes.extend([conan_paths.get('include_dirs')]) + libev_libdirs.extend([conan_paths.get('library_dirs')]) + libev_ext = Extension('cassandra.io.libevwrapper', sources=['cassandra/io/libevwrapper.c'], include_dirs=['/usr/include/libev', '/usr/local/include', '/opt/local/include'], @@ -184,7 +200,7 @@ def __init__(self, ext): try_extensions = "--no-extensions" not in sys.argv and is_supported_platform and is_supported_arch and not os.environ.get('CASS_DRIVER_NO_EXTENSIONS') try_murmur3 = try_extensions and "--no-murmur3" not in sys.argv -try_libev = try_extensions and "--no-libev" not in sys.argv and not is_pypy and not is_windows +try_libev = try_extensions and "--no-libev" not in sys.argv and not is_pypy try_cython = try_extensions and "--no-cython" not in sys.argv and not is_pypy and not os.environ.get('CASS_DRIVER_NO_CYTHON') try_cython &= 'egg_info' not in sys.argv # bypass setup_requires for pip egg_info calls, which will never have --install-option"--no-cython" coming fomr pip