blob: f0a1c51747321818d5c57d3cd12e74946decc3c1 [file] [log] [blame] [view]
# Libevent
## BCR Maintainer Notes
The [Libevent book](https://libevent.org/libevent-book/) is a handy reference.
### Known Issues
* The latest OpenSSL in BCR (3.3.1.bcr.1 at the time of this writing) does not
support Windows, so the `@libevent//:event_openssl` target is not usable on
Windows.
* OpenSSL 3.3.1.bcr.1 also seems to be missing some symbols on macOS. Attempting
to build `@libevent//sample:https-client` fails because of this.
### Libraries
For better or worse, I kept the same library targets as the official
release. These targets are described in the [preliminaries
chapter](https://libevent.org/libevent-book/Ref0_meta.html) in the book.
* `@libevent//:event_core` - All core event and buffer functionality. This
library contains all the event_base, evbuffer, bufferevent, and utility
functions.
* `@libevent//:event_extra` - This library defines protocol-specific
functionality that you may or may not want for your application, including
HTTP, DNS, and RPC.
* `@libevent//:event` - This library exists for historical reasons; it contains
the contents of both libevent_core and libevent_extra. You shouldnt use it;
it may go away in a future version of Libevent.
* `@libevent//:event_pthreads` - This library adds threading and locking
implementations based on the pthreads portable threading library. It is
separated from libevent_core so that you dont need to link against pthreads
to use Libevent unless you are actually using Libevent in a multithreaded way.
* `@libevent//:event_openssl` - This library provides support for encrypted
communications using bufferevents and the OpenSSL library. It is separated
from libevent_core so that you dont need to link against OpenSSL to use
Libevent unless you are actually using encrypted connections.
### Notes on creating the BCR build
Upstream releases can be found at https://github.com/libevent/libevent/releases
#### Configuration Headers
The official build uses CMake to generate two files, `evconfig-private.h` and
`event2/event-config.h`. The general strategy is to generate them ourselves and
then modify them for portability. Ordinarily CMake detects the capabilities of
the target platform and writes these files accordingly, but this workflow doesn't
happen on Bazel, so we will have to edit these files and provide our own feature
detection.
Run `cmake` to generate `evconfig-private.h` and `event2/event-config.h` in
`build/include`.
```shell
mkdir build && cd build
cmake ..
```
From here I used the generated files as a starting point and decided to make the
config files platform specific for better organization. So for example, I
renamed `evconfig-private.h` to `evconfig-private_linux.h` and then made
`evconfig-private.h` into a platform selector file. I did the same with
`event2/event-config.h`. When you rename these files, be sure to fix the strings
used by the `#include` guards as well. These files get overlayed onto the tree
in the Bazel Central Registry.
I also factored out the version constants like `EVENT__PACKAGE_VERSION` into a
seperate file, `event2-config_common.h`, which *may* allow the platform specific
files to be reused between versions since only the version constants in
`event2-config_common.h` may need to be updated. Use caution with this
strategy. If new feature detection macros are introduced, the platform specific
configuration files will also need to be updated.
Since we cannot guarantee that the user is running a Bazel build targeting an
identical platform as the CMake target, some feature test macros will have to be
updated for portability. For example, `strlcpy` was introduced in glibc
2.38. The generated value of `EVENT__HAVE_STRLCPY` will depend entirely on the
platform (or in this case, the version of glibc on the platform) that CMake ran
on. In this case, I changed the macro to
```c
/* Define to 1 if you have the `strlcpy' function. */
#if EVENT__GLIBC_PREREQ(2, 38)
#define EVENT__HAVE_STRLCPY 1
#endif
```
so that it is correct regardless of the platform CMake ran on.
Figuring out which macros need to be fixed requires some testing. One thing you
could try is running CMake on the oldest platform you would like to support, and
running it on the newest platform you would like to support, and looking at the
diff between the generated files. From there it may require some research to
figure out what the correct feature test is.
Another class of macros that may need to be fixed for portability are the
`SIZEOF` constants in the config files, for example `EVENT__SIZEOF_LONG`, since
this may differ between 32-bit and 64-bit platforms. Note that `sizeof(type)`
cannot be used by the preprocessor. Normally CMake computes the values that will
be used on the target platform. We have to manually get these right. For `gcc`
and `clang`, some of these constants are provided by the compiler. You can see
some of the predefined symbols that may be useful with the following command:
```shell
${CC:-gcc} -dM -E - $@ < /dev/null
```
I added a test `@libevent//test:test-config` to check that the some of the
values in the configuration headers are correct.
#### `BUILD.bazel`
Next you will have to create the `BUILD.bazel` file. Commands like
```shell
ls -1 include/*.h | sort | awk '{ print "\""$0"\","}'
```
are helpful for getting the list of files in a format that can be copy-pasted.
Two files are handled non-intuitively:
* `arc4random.c` is textually included by evutil_rand.c when arc4random() is not
available. It is not compiled by itself. Put this file in `textual_hdrs`.
* `epoll_sub.c` appears to only be needed when using an ancient version of
glibc, and will conflict with glibc when a modern version is in use. For
simplicity this file can be omitted from the build.