Public header preprocessor directives
lgrahl opened this issue · comments
In May 2014, Alfred mentioned that you don't want a configuration file to detect which features have been enabled in re at compile time and would rather have the application do runtime checks (see this mail). And I'm mostly fine with that. However, there are quite a couple of issues with that approach when including the public headers of re in an application as I will explain in the following.
HAVE_INTTYPES_H
As an application depending on re, it makes sense to include re_types.h
pretty much everywhere instead of inttypes.h
because it is a useful abstraction. However, at the moment the application needs to define HAVE_INTTYPES_H
itself or it will trigger unintended behaviour/compile errors in most of the cases (e.g. defining all of those types instead of simply including inttypes.h
).
Suggested solution: -DHAVE_INTTYPES_H
could be added to the Cflags
of libre.pc
depending on whether inttypes.h
has been detected on the system. I'm not sure if we would also have to include -D__ssize_t_defined
for Windows but it does fall into the same category.
RELEASE
The RELEASE
definition triggers different behaviour when using re_mbuf
. The application will most likely use mbuf
structures but its build system may or may not define RELEASE
.
Suggested solution: Same as for HAVE_INTTYPES_H
but expose -DMBUF_DEBUG=1
(if RELEASE
was set) in the Cflags
.
WIN32
-related
There a lot of WIN32
-related definition checks in headers. This results in...
- different definitions for
MOD_PRE
,MOD_EXT
andEXPORT_SYM
inre_mod.h
, - different includes in
re_net.h
andre_sa.h
, and - different type definitions in
re_types.h
.
IIRC, an application building on Windows pretty much has to define WIN32
to get anything working.
Suggested solution: Expose -DWIN32
in the Cflags
if set. That might clash with other projects, though.
USE_ZLIB
crc32
would be redefined if USE_ZLIB
is not set and zlib is being used.
Suggested solution: Expose -DUSE_ZLIB
if set.
HAVE_GAI_STRERROR
While it will work fine for the library itself, gai_strerror
will be overridden with a stub function when including re_net.h
after having included all the necessary headers for working with gai_strerror
.
Suggested solution: Adding -DHAVE_GAI_STRERROR
(if set) to Cflags
should do.
HAVE_INET6
The NET_ADDRSTRLEN
definition depends on HAVE_INET6
. It would be incorrect for the application if HAVE_INET6
is not set.
Suggested solution: Expose -DHAVE_INET6
if set.
USE_OPENSSL
A couple of OpenSSL functions and structs will be redefined when including re_sha.h
without setting USE_OPENSSL
.
In addition, tls_openssl_context
is not defined if USE_OPENSSL
is not defined.
Suggested solution: Expose -DUSE_OPENSSL
if set.
VERSION
, ARCH
and OS
All of those will be redefined if not set. However, it doesn't really matter much since the sys_*
functions exists. As such it doesn't make much sense to leave them in the public header.
Suggested solution: Move them into a private header file.
SOLARIS
and HAVE_STDBOOL_H
SOLARIS
and HAVE_STDBOOL_H
trigger different behaviour in re_types.h
.
Suggested solution: Expose them if they are set.
If we go with the suggested solutions, then we are really not far away from a (much more convenient) configuration header. So, it might make sense to reconsider it.
the idea was that the application should include re.mk
in its Makefile
.
then the application will get the same flags as re. is this possible in your app ?
my goal is to reduce the number of #ifdef
s.
for example the following defines might be subject to removal:
HAVE_INTTYPES_H
HAVE_INET6
HAVE_GAI_STRERROR
what do you think about remove these ?
the goal should be that the re API is source and binary compatible,
independently of which flags are set/unset.
is this possible in your app ?
I'm currently including it via CMake via the use of the pkgconfig file, so I don't think so. But perhaps CMake has a Makefile compatibility layer? No idea tbh. In any case, since re has a pkgconfig file, IMHO it should be striven for that the library can be used with pkg-config
alone, essentially
cc foo.c `pkg-config --cflags --libs libre` -o foo
should work fine and not require foo.c
to define HAVE_INTTYPES_H
& co.
what do you think about remove these ?
That will probably resolve 90% of the issues but not all of them (like USE_ZLIB
). I would also like an approach that resolves this issue 100% without generating any headers but at this point I'm uncertain whether that's possible. The alternative is of course to expose the defines directly in the pkgconfig file but that is a bit messy. Edit: This is actually what I've done in my Meson support branch for now (should I create a PR for that? 😉).
the pkg-config file is generated in Makefile:
libre.pc:
@echo 'prefix='$(PREFIX) > libre.pc
@echo 'exec_prefix=$${prefix}' >> libre.pc
@echo 'libdir=$${prefix}/lib' >> libre.pc
@echo 'includedir=$${prefix}/include/re' >> libre.pc
@echo '' >> libre.pc
@echo 'Name: libre' >> libre.pc
@echo 'Description: ' >> libre.pc
@echo 'Version: '$(VERSION) >> libre.pc
@echo 'URL: http://creytiv.com/re.html' >> libre.pc
@echo 'Libs: -L$${libdir} -lre' >> libre.pc
@echo 'Libs.private: -L$${libdir} -lre ${LIBS}' >> libre.pc
@echo 'Cflags: -I$${includedir}' >> libre.pc
so you could add all the mentioned flags to the Cflags section, would that work ?
Could do but the defines are not prefixed so they might clash. I guess it would be an adequate compromise for now.
@lgrahl are you planning to do any work on this ?
I have added the item to the roadmap: