Making an embeddable libev
jsquyres at cisco.com
Tue Dec 18 16:45:04 CET 2007
On Dec 17, 2007, at 11:06 PM, Marc Lehmann wrote:
> Since there is only a single .c file for the libev core, that sound
> overkill, and I think its the wrong approach when embedding. It is
> vastly easier to just provide an #include and a single .c file
> elsewhere, or
> write your own Makefile.am.
I think that much of your verbiage is repeatedly saying that you
disagree with me on this point. :-)
> > "The goal is to enable you to just copy the neecssary files into
> > source directory without having to change even a single line in
> > so you can easily upgrade by simply copying (or having a checked-out
> > copy of libev somewhere in your source tree)."
If we have a checked-out version of libev (or an expanded tarball),
then we have your Makefile.am. I'd like to use what you provide, not
have to work around it because only some parts are suitable for
embedding and others are not.
> > In summary, the following two changes would be most helpful:
> > - an m4 macro to change the output library to be noinst
> You can already do that easily using the documented interface in
> your own
> > - an m4 macro to change (prefix?) all the public symbols in the
> > library
> Already possible, as you can easily do that yourself, too, even
I assume that you are saying that the project embedding libev can do
this (not the libev-provided .m4 / Makefile.am). And yes, of course
we (Open MPI) can. I'm just saying that it would be nice if libev
provided all of the embedding glue and didn't require additional glue
from the upper-level package.
> > Are these changes possible?
> They are not needed, it cna all be done with the existing sources.
> I really wonder if you really read the documentation, which explains
I see no mention in http://pod.tst.eu/http://cvs.schmorp.de/libev/
ev.pod of how the Makefile.am is not intended to be embedded, nor
anything about renaming all the public symbols.
No need to be nasty to a new user who is just asking some
> > that wants to embed libev: they allow us to safely link in the
> > generated libev library to our library, and keep the libev/ library
> > completely "pure" -- no modifications and no source wrappers.
> While that might be true, there are simpler and easier ways to achieve
> that. You apperetly want with your head through the wall, but that
> is not
> advisable nor really useful. A simple wrapper will give you a lot more
> flexibility and future-proofness, is easier to program and use, and
> to maintain for all sides.
We have a different bias / way of doing things that is apparently
"new" to this community. Our bias is to do something like this in the
SUBDIRS = ... libev ...
lib_LTLIBRARIES = libfoo.la
libfoo_la_LIBADD = ... libev/libev.la ...
I don't understand why you think this is so difficult or weird; it is
certainly a documented and supported way of using Automake and
Libtool. If projects that are using the AC/AM/LT model have to write
their own wrappers for their configure/build system, then the "not
modifying libev source" promise is half-empty, IMHO: yes, you don't
have to modify the libev source, but you have to provide your own
configure/build source and possibly modify it over time because the
libev configure/build stuff is not guaranteed to be a stable interface
(e.g., the list of functions to be renamed).
And that's fine if that's the path that you choose to support in
libev; we'll cope (we'll likely have to use the approaches you
mentioned, but we would prefer to use the method I mentioned above).
If you choose this route, please: a) add this point to your fine
documentation, and b) do not berate someone for asking about it. :-)
> > The gcc example I gave was also borked; what I meant was:
> > gcc my_app.c -lmpi -lev -o my_app
> > In this example, without #define's to rename all the public
> symbols in
> > libmpi, my_app.c will get the system-installed ev.h (that matches
> > API in -lev)
> > but will actually link against the ev symbols in libmpi
> > due to linker left-to-right resolution.
> Note that renaming won't help you in that case, you would still get
> wrong header file. You need to solve this, too, e.g. by renaming
> your copy
> of ev.h (which is certainly possible without patching with the current
Ah, a misunderstanding: Open MPI will not install any of libev's
header files -- they are not part of the standardized MPI interface.
By default, Open MPI only installs (for C) the one MPI-standardized C
interface header file: mpi.h. So the ev.h will come from the system-
installed libev, and I think my example is essentially correct:
renaming the symbols in libmpi would [at least partially] save us.
> But renaming is certainly possible with the current approach without
> patching the sources, if there is a need for additional complexity I
> like to hear about it.
As I understand the other projects that are using libev, they are
applications and plugins. They are not libraries themselves (that are
linked to by other applications). As such, the current embedding
applications have very little (no?) chance of having multiple-libev
conflicts -- whereas a library such as Open MPI has this as a very
real possibility (particularly when/if Linux distro's start shipping
> If you convince me that this is an unreasonable burden for openmpi, I
> can consider writing a wrapper macro that allows renaming. But you
> arguemnts for that, and I haven't heard any (you gave arguments on why
> renaming might be useful, and while I not agree with all of them, one
> sound argument is enough, and I am fully ok with openmpi requiring
> symbols. I just think its already easily possible. If you think
> you need to give arguments).
In a later e-mail, you proposed providing a text file with all the
public symbols. That's fine, but then it means that we still need to
add more glue to our configure / build system to create a .h file with
all the #define's (and be smart about generating this .h file so that
we don't cause all dependencies to be rebuilt when the list of symbols
hasn't changed, similar to how AC won't re-generate config.h if it
hasn't changed). Sure, we could do that, but it certainly would be
nice if libev were fully self-contained. Perhaps something as simple
# Open MPI's configure.ac
That would be great (that's off the top of my head; I'm sure that you
can poke holes in it -- it will likely require a little more
thought). Here's a simple patch that does the lib/noinst stuff, for
example (forgive mail formatting):
RCS file: /schmorpforge/libev/Makefile.am,v
retrieving revision 1.1
diff -u -r1.1 Makefile.am
--- Makefile.am 14 Dec 2007 21:07:13 -0000 1.1
+++ Makefile.am 18 Dec 2007 15:27:37 -0000
@@ -7,12 +7,19 @@
ev_epoll.c ev_select.c ev_poll.c ev_kqueue.c ev_port.c
-man_MANS = ev.3
-include_HEADERS = ev.h event_compat.h ev++.h event.h
+man_MANS = ev.3
+include_HEADERS = ev.h event_compat.h ev++.h event.h
lib_LTLIBRARIES = libev.la
libev_la_SOURCES = ev.c event.c
libev_la_LDFLAGS = -version-info $(VERSION_INFO)
+noinst_LTLIBRARIES = libev_noinst.la
+libev_noinst_la_SOURCES = ev.c event.c
+libev_noinst_la_LDFLAGS = -version-info $(VERSION_INFO)
RCS file: /schmorpforge/libev/libev.m4,v
retrieving revision 1.7
diff -u -r1.7 libev.m4
--- libev.m4 2 Dec 2007 00:35:26 -0000 1.7
+++ libev.m4 18 Dec 2007 15:27:37 -0000
@@ -14,6 +14,11 @@
+if test "x$LIBEV_INSTALL" = "x"; then
+AM_CONDITIONAL(LIBEV_INSTALL, test "$LIBEV_INSTALL" = "1")
With this [one possible solution], you can:
# default: installs libev.la and friends
# make an embeddable / "convenience" libtool library
shell$ ./configure LIBEV_INSTALL=0
Which also works in m4 (e.g., [not] setting LIBEV_INSTALL before
m4_including, etc.). You could easily wrap up the option in a --with
or --enable argument in the libev configure.ac if you wanted to
(separate than the embedding solution, of course -- just mentioned for
> > If all the symbols are separate (e.g., via #define's),
> > his there a reason that two libev's can't co-exist in the same
> Only because when one event loop runs, the other doesn't.
Good enough for us. The MPI spec is clear [enough] about when it will
block and when it will not block. We can't change the spec, so having
two separate event loops will be fine.
> A typcial
> example of a process-wide resource are signals: you cannot have two
> libev's coexist in the same process using signals or child watchers,
> it just
> won't work. The same is true for fork and other global things.
Yes, I can see how that would be a problem.
Aren't signals stackable such that multiple libev's could all get
invoked when a signal is invoked? (I didn't look into how libev
implements its signal handling)
Failing that, is there any way to detect that there are two libev's
running in a single process such that if both of them tried to do
something with a global resource, it could be detected? If some kind
of "collision" error code were returned by libev, the caller could
print a friendly error message (or handle it in some other way).
More information about the libev