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:
- rm -rf $BUILD_LIBS/share/man/
- ls -l $BUILD_LIBS $BUILD_LIBS/lib
- 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
# to the jobs created by the matrix (and should override the `script` command).
......
# -*- coding: utf-8 -*-
"""
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
......@@ -60,35 +63,40 @@ def configure_libev(bext, ext):
finally:
os.chdir(cwd)
CORE = Extension(name='gevent.libev.corecext',
sources=[
'src/gevent/libev/corecext.pyx',
'src/gevent/libev/callbacks.c',
],
include_dirs=['src/gevent/libev'] + [dep_abspath('libev')] if LIBEV_EMBED else [],
libraries=list(LIBRARIES),
define_macros=list(DEFINE_MACROS),
depends=glob_many('src/gevent/libev/callbacks.*',
'src/gevent/libev/stathelper.c',
'src/gevent/libev/libev*.h',
'deps/libev/*.[ch]'))
if WIN:
CORE.define_macros.append(('EV_STANDALONE', '1'))
# QQQ libev can also use -lm, however it seems to be added implicitly
if LIBEV_EMBED:
CORE.define_macros += [('LIBEV_EMBED', '1'),
('EV_COMMON', ''), # we don't use void* data
# libev watchers that we don't use currently:
('EV_CLEANUP_ENABLE', '0'),
('EV_EMBED_ENABLE', '0'),
("EV_PERIODIC_ENABLE", '0')]
CORE.configure = configure_libev
if sys.platform == "darwin":
os.environ["CPPFLAGS"] = ("%s %s" % (os.environ.get("CPPFLAGS", ""), "-U__llvm__")).lstrip()
if os.environ.get('GEVENTSETUP_EV_VERIFY') is not None:
CORE.define_macros.append(('EV_VERIFY', os.environ['GEVENTSETUP_EV_VERIFY']))
else:
CORE.libraries.append('ev')
CORE = cythonize1(CORE)
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=[
'src/gevent/libev/corecext.pyx',
'src/gevent/libev/callbacks.c',
],
include_dirs=['src/gevent/libev'] + [dep_abspath('libev')] if LIBEV_EMBED else [],
libraries=list(LIBRARIES),
define_macros=list(DEFINE_MACROS),
depends=glob_many('src/gevent/libev/callbacks.*',
'src/gevent/libev/stathelper.c',
'src/gevent/libev/libev*.h',
'deps/libev/*.[ch]'))
if WIN:
CORE.define_macros.append(('EV_STANDALONE', '1'))
# QQQ libev can also use -lm, however it seems to be added implicitly
if LIBEV_EMBED:
CORE.define_macros += [('LIBEV_EMBED', '1'),
('EV_COMMON', ''), # we don't use void* data
# libev watchers that we don't use currently:
('EV_CLEANUP_ENABLE', '0'),
('EV_EMBED_ENABLE', '0'),
("EV_PERIODIC_ENABLE", '0')]
CORE.configure = configure_libev
if sys.platform == "darwin":
os.environ["CPPFLAGS"] = ("%s %s" % (os.environ.get("CPPFLAGS", ""), "-U__llvm__")).lstrip()
if os.environ.get('GEVENTSETUP_EV_VERIFY') is not None:
CORE.define_macros.append(('EV_VERIFY', os.environ['GEVENTSETUP_EV_VERIFY']))
else:
CORE.define_macros += [('LIBEV_EMBED', '0')]
CORE.libraries.append('ev')
return CORE
......@@ -46,10 +46,11 @@ __version__ = read_version()
from _setuplibev import libev_configure_command
from _setuplibev import LIBEV_EMBED
from _setuplibev import CORE
from _setuplibev import build_extension as build_libev_extension
from _setupares import ARES
CORE = cythonize1(build_libev_extension())
# Get access to the greenlet header file.
# The sysconfig dir is not enough if we're in a virtualenv
# See https://github.com/pypa/pip/issues/4610
......
......@@ -10,21 +10,28 @@ from __future__ import absolute_import, print_function
import sys
import os
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__ = []
from cffi import FFI
ffi = FFI()
thisdir = os.path.dirname(os.path.abspath(__file__))
def read_source(name):
with open(os.path.join(thisdir, name), 'r') as f:
return f.read()
# cdef goes to the cffi library and determines what can be used in
# Python.
_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
# C tools.
......@@ -35,6 +42,14 @@ _cdef = _cdef.replace('#define GEVENT_ST_NLINK_T int',
'typedef int... 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'):
# We must have the vfd_open, etc, functions on
......@@ -49,14 +64,20 @@ vfd_socket_t vfd_get(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.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__':
# XXX: Note, on Windows, we would need to specify the external libraries
......@@ -64,4 +85,17 @@ if __name__ == '__main__':
# 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
# 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 */
#define EV_MINPRI ...
......@@ -55,11 +59,9 @@
#define GEVENT_STRUCT_DONE int
#define GEVENT_ST_NLINK_T int
struct ev_loop {
int backend_fd;
int activecnt;
GEVENT_STRUCT_DONE _;
};
/* Note that we don't declare the ev_loop struct and fields here. */
/* If we don't embed libev, we can't access those fields, libev */
/* keeps it opaque. */
// Watcher types
// 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
#endif
#ifdef _WIN32
#define EV_STANDALONE 1
......
......@@ -389,7 +389,9 @@ class loop(AbstractLoop):
libev.gevent_reset_sigchld_handler()
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
if fd >= 0:
return fd
......@@ -398,7 +400,9 @@ class loop(AbstractLoop):
def activecnt(self):
if not self._ptr:
raise ValueError('operation on destroyed loop')
return self._ptr.activecnt
if LIBEV_EMBED:
return self._ptr.activecnt
return -1
@ffi.def_extern()
......@@ -424,4 +428,4 @@ def set_syserr_cb(callback):
__SYSERR_CALLBACK = None
LIBEV_EMBED = True
LIBEV_EMBED = libev.LIBEV_EMBED
#if defined(LIBEV_EMBED)
#include "ev.c"
#undef LIBEV_EMBED
#define LIBEV_EMBED 1
#define gevent_ev_loop_origflags(loop) ((loop)->origflags)
#define gevent_ev_loop_sig_pending(loop) ((loop))->sig_pending
#define gevent_ev_loop_backend_fd(loop) ((loop))->backend_fd
#define gevent_ev_loop_activecnt(loop) ((loop))->activecnt
#if EV_USE_SIGNALFD
#define gevent_ev_loop_sigfd(loop) ((loop))->sigfd
#else
#define gevent_ev_loop_sigfd(loop) -1
#endif /* !EV_USE_SIGNALFD */
#if defined(LIBEV_EMBED) && LIBEV_EMBED
#include "ev.c"
#undef LIBEV_EMBED
#define LIBEV_EMBED 1
#define gevent_ev_loop_origflags(loop) ((loop)->origflags)
#define gevent_ev_loop_sig_pending(loop) ((loop))->sig_pending
#define gevent_ev_loop_backend_fd(loop) ((loop))->backend_fd
#define gevent_ev_loop_activecnt(loop) ((loop))->activecnt
#if EV_USE_SIGNALFD
#define gevent_ev_loop_sigfd(loop) ((loop))->sigfd
#else
#define gevent_ev_loop_sigfd(loop) -1
#endif /* !EV_USE_SIGNALFD */
#else /* !LIBEV_EMBED */
#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