Commit dd7d123a authored by Jason Madden's avatar Jason Madden

Get libev-cffi building and using a non-embedded libev.so

parent 64ce33e5
...@@ -143,6 +143,10 @@ jobs: ...@@ -143,6 +143,10 @@ jobs:
- rm -rf $BUILD_LIBS/share/man/ - rm -rf $BUILD_LIBS/share/man/
- ls -l $BUILD_LIBS $BUILD_LIBS/lib - ls -l $BUILD_LIBS $BUILD_LIBS/lib
- pip install --no-build-isolation .[test] - pip install --no-build-isolation .[test]
- objdump -p src/gevent/libev/*so
script:
# Verify that we got non-embedded builds
- python -c 'import gevent.libev.corecffi as CF; assert not CF.LIBEV_EMBED'
# Ok, now we switch to the test stage. These are all in addition # Ok, now we switch to the test stage. These are all in addition
# to the jobs created by the matrix (and should override the `script` command). # to the jobs created by the matrix (and should override the `script` command).
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" """
setup helpers for libev. setup helpers for libev.
Importing this module should have no side-effects; in particular,
it shouldn't attempt to cythonize anything.
""" """
from __future__ import print_function, absolute_import, division from __future__ import print_function, absolute_import, division
...@@ -60,7 +63,11 @@ def configure_libev(bext, ext): ...@@ -60,7 +63,11 @@ def configure_libev(bext, ext):
finally: finally:
os.chdir(cwd) os.chdir(cwd)
CORE = Extension(name='gevent.libev.corecext', def build_extension():
# Return the un-cythonized extension.
# This can be used to access things like `libraries` and `include_dirs`
# and `define_macros` so we DRY.
CORE = Extension(name='gevent.libev.corecext',
sources=[ sources=[
'src/gevent/libev/corecext.pyx', 'src/gevent/libev/corecext.pyx',
'src/gevent/libev/callbacks.c', 'src/gevent/libev/callbacks.c',
...@@ -72,11 +79,11 @@ CORE = Extension(name='gevent.libev.corecext', ...@@ -72,11 +79,11 @@ CORE = Extension(name='gevent.libev.corecext',
'src/gevent/libev/stathelper.c', 'src/gevent/libev/stathelper.c',
'src/gevent/libev/libev*.h', 'src/gevent/libev/libev*.h',
'deps/libev/*.[ch]')) 'deps/libev/*.[ch]'))
if WIN: if WIN:
CORE.define_macros.append(('EV_STANDALONE', '1')) CORE.define_macros.append(('EV_STANDALONE', '1'))
# QQQ libev can also use -lm, however it seems to be added implicitly # QQQ libev can also use -lm, however it seems to be added implicitly
if LIBEV_EMBED: if LIBEV_EMBED:
CORE.define_macros += [('LIBEV_EMBED', '1'), CORE.define_macros += [('LIBEV_EMBED', '1'),
('EV_COMMON', ''), # we don't use void* data ('EV_COMMON', ''), # we don't use void* data
# libev watchers that we don't use currently: # libev watchers that we don't use currently:
...@@ -88,7 +95,8 @@ if LIBEV_EMBED: ...@@ -88,7 +95,8 @@ if LIBEV_EMBED:
os.environ["CPPFLAGS"] = ("%s %s" % (os.environ.get("CPPFLAGS", ""), "-U__llvm__")).lstrip() os.environ["CPPFLAGS"] = ("%s %s" % (os.environ.get("CPPFLAGS", ""), "-U__llvm__")).lstrip()
if os.environ.get('GEVENTSETUP_EV_VERIFY') is not None: if os.environ.get('GEVENTSETUP_EV_VERIFY') is not None:
CORE.define_macros.append(('EV_VERIFY', os.environ['GEVENTSETUP_EV_VERIFY'])) CORE.define_macros.append(('EV_VERIFY', os.environ['GEVENTSETUP_EV_VERIFY']))
else: else:
CORE.define_macros += [('LIBEV_EMBED', '0')]
CORE.libraries.append('ev') CORE.libraries.append('ev')
CORE = cythonize1(CORE) return CORE
...@@ -46,10 +46,11 @@ __version__ = read_version() ...@@ -46,10 +46,11 @@ __version__ = read_version()
from _setuplibev import libev_configure_command from _setuplibev import libev_configure_command
from _setuplibev import LIBEV_EMBED from _setuplibev import LIBEV_EMBED
from _setuplibev import CORE from _setuplibev import build_extension as build_libev_extension
from _setupares import ARES from _setupares import ARES
CORE = cythonize1(build_libev_extension())
# Get access to the greenlet header file. # Get access to the greenlet header file.
# The sysconfig dir is not enough if we're in a virtualenv # The sysconfig dir is not enough if we're in a virtualenv
# See https://github.com/pypa/pip/issues/4610 # See https://github.com/pypa/pip/issues/4610
......
...@@ -10,21 +10,28 @@ from __future__ import absolute_import, print_function ...@@ -10,21 +10,28 @@ from __future__ import absolute_import, print_function
import sys import sys
import os import os
import os.path # pylint:disable=no-name-in-module import os.path # pylint:disable=no-name-in-module
from cffi import FFI
# We must be run from the directory containing setup.py.
import _setuplibev
thisdir = os.path.dirname(os.path.abspath(__file__))
setup_dir = os.path.abspath(os.path.join(thisdir, '..', '..', '..'))
__all__ = [] __all__ = []
from cffi import FFI
ffi = FFI() ffi = FFI()
thisdir = os.path.dirname(os.path.abspath(__file__))
def read_source(name): def read_source(name):
with open(os.path.join(thisdir, name), 'r') as f: with open(os.path.join(thisdir, name), 'r') as f:
return f.read() return f.read()
# cdef goes to the cffi library and determines what can be used in
# Python.
_cdef = read_source('_corecffi_cdef.c') _cdef = read_source('_corecffi_cdef.c')
_source = read_source('_corecffi_source.c')
# These defines and uses help keep the C file readable and lintable by # These defines and uses help keep the C file readable and lintable by
# C tools. # C tools.
...@@ -35,6 +42,14 @@ _cdef = _cdef.replace('#define GEVENT_ST_NLINK_T int', ...@@ -35,6 +42,14 @@ _cdef = _cdef.replace('#define GEVENT_ST_NLINK_T int',
'typedef int... nlink_t;') 'typedef int... nlink_t;')
_cdef = _cdef.replace('GEVENT_ST_NLINK_T', 'nlink_t') _cdef = _cdef.replace('GEVENT_ST_NLINK_T', 'nlink_t')
if _setuplibev.LIBEV_EMBED:
_cdef += """
struct ev_loop {
int backend_fd;
int activecnt;
...;
};
"""
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
# We must have the vfd_open, etc, functions on # We must have the vfd_open, etc, functions on
...@@ -49,14 +64,20 @@ vfd_socket_t vfd_get(int); ...@@ -49,14 +64,20 @@ vfd_socket_t vfd_get(int);
void vfd_free(int); void vfd_free(int);
""" """
# source goes to the C compiler
_source = read_source('_corecffi_source.c')
distutils_ext = _setuplibev.build_extension()
include_dirs = [
thisdir, # libev_vfd.h
os.path.abspath(os.path.join(thisdir, '..', '..', '..', 'deps', 'libev')),
]
ffi.cdef(_cdef) ffi.cdef(_cdef)
ffi.set_source('gevent.libev._corecffi', _source, include_dirs=include_dirs) ffi.set_source(
'gevent.libev._corecffi',
_source,
include_dirs=distutils_ext.include_dirs,
define_macros=distutils_ext.define_macros,
libraries=distutils_ext.libraries,
)
if __name__ == '__main__': if __name__ == '__main__':
# XXX: Note, on Windows, we would need to specify the external libraries # XXX: Note, on Windows, we would need to specify the external libraries
...@@ -64,4 +85,17 @@ if __name__ == '__main__': ...@@ -64,4 +85,17 @@ if __name__ == '__main__':
# Python.h calls) the proper Python library---at least for PyPy. I never got # Python.h calls) the proper Python library---at least for PyPy. I never got
# that to work though, and calling python functions is strongly discouraged # that to work though, and calling python functions is strongly discouraged
# from CFFI code. # from CFFI code.
ffi.compile()
# On macOS to make the non-embedded case work correctly, against
# our local copy of libev:
#
# 1) configure and make libev
# 2) CPPFLAGS=-Ideps/libev/ LDFLAGS=-Ldeps/libev/.libs GEVENTSETUP_EMBED_LIBEV=0 \
# python setup.py build_ext -i
# 3) export DYLD_LIBRARY_PATH=`pwd`/deps/libev/.libs
#
# XXX: The DYLD_LIBRARY_PATH is because the linker hard-codes
# /usr/local/lib/libev.4.dylib in the corecffi.so dylib, because
# that's the "install name" of the libev dylib that was built.
# Adding a -rpath to the LDFLAGS doesn't change things.
ffi.compile(verbose=True)
/* access whether we built embedded or not */
#define LIBEV_EMBED ...
/* libev interface */ /* libev interface */
#define EV_MINPRI ... #define EV_MINPRI ...
...@@ -55,11 +59,9 @@ ...@@ -55,11 +59,9 @@
#define GEVENT_STRUCT_DONE int #define GEVENT_STRUCT_DONE int
#define GEVENT_ST_NLINK_T int #define GEVENT_ST_NLINK_T int
struct ev_loop { /* Note that we don't declare the ev_loop struct and fields here. */
int backend_fd; /* If we don't embed libev, we can't access those fields, libev */
int activecnt; /* keeps it opaque. */
GEVENT_STRUCT_DONE _;
};
// Watcher types // Watcher types
// base for all watchers // base for all watchers
......
// passed to the real C compiler /* passed to the real C compiler */
#ifndef LIBEV_EMBED
/* We're normally used to embed libev, assume that */
/* When this is defined, libev.h includes ev.c */
#define LIBEV_EMBED 1 #define LIBEV_EMBED 1
#endif
#ifdef _WIN32 #ifdef _WIN32
#define EV_STANDALONE 1 #define EV_STANDALONE 1
......
...@@ -389,7 +389,9 @@ class loop(AbstractLoop): ...@@ -389,7 +389,9 @@ class loop(AbstractLoop):
libev.gevent_reset_sigchld_handler() libev.gevent_reset_sigchld_handler()
def fileno(self): def fileno(self):
if self._ptr: if self._ptr and LIBEV_EMBED:
# If we don't embed, we can't access these fields,
# the type is opaque
fd = self._ptr.backend_fd fd = self._ptr.backend_fd
if fd >= 0: if fd >= 0:
return fd return fd
...@@ -398,7 +400,9 @@ class loop(AbstractLoop): ...@@ -398,7 +400,9 @@ class loop(AbstractLoop):
def activecnt(self): def activecnt(self):
if not self._ptr: if not self._ptr:
raise ValueError('operation on destroyed loop') raise ValueError('operation on destroyed loop')
if LIBEV_EMBED:
return self._ptr.activecnt return self._ptr.activecnt
return -1
@ffi.def_extern() @ffi.def_extern()
...@@ -424,4 +428,4 @@ def set_syserr_cb(callback): ...@@ -424,4 +428,4 @@ def set_syserr_cb(callback):
__SYSERR_CALLBACK = None __SYSERR_CALLBACK = None
LIBEV_EMBED = True LIBEV_EMBED = libev.LIBEV_EMBED
#if defined(LIBEV_EMBED) #if defined(LIBEV_EMBED) && LIBEV_EMBED
#include "ev.c" #include "ev.c"
#undef LIBEV_EMBED #undef LIBEV_EMBED
#define LIBEV_EMBED 1 #define LIBEV_EMBED 1
#define gevent_ev_loop_origflags(loop) ((loop)->origflags) #define gevent_ev_loop_origflags(loop) ((loop)->origflags)
#define gevent_ev_loop_sig_pending(loop) ((loop))->sig_pending #define gevent_ev_loop_sig_pending(loop) ((loop))->sig_pending
#define gevent_ev_loop_backend_fd(loop) ((loop))->backend_fd #define gevent_ev_loop_backend_fd(loop) ((loop))->backend_fd
#define gevent_ev_loop_activecnt(loop) ((loop))->activecnt #define gevent_ev_loop_activecnt(loop) ((loop))->activecnt
#if EV_USE_SIGNALFD #if EV_USE_SIGNALFD
#define gevent_ev_loop_sigfd(loop) ((loop))->sigfd #define gevent_ev_loop_sigfd(loop) ((loop))->sigfd
#else #else
#define gevent_ev_loop_sigfd(loop) -1 #define gevent_ev_loop_sigfd(loop) -1
#endif /* !EV_USE_SIGNALFD */ #endif /* !EV_USE_SIGNALFD */
#else /* !LIBEV_EMBED */ #else /* !LIBEV_EMBED */
#include "ev.h" #include "ev.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment