<machine/stdarg.h> is a kernel-only header. The standard header for
userland is <stdarg.h>. Using the standard header in userland avoids
weird build errors when building with external compilers that include
their own stdarg.h header.
Details
- build with external GCC patched by D14627 and a world then patched to only use --sysroot (so no -nostdinc, etc.)
- I'm guessing the same issue affects building with external llvm since it also ships its own stdarg.h.
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
I don't like ifdefs like this, but cannot recommend anything less distasteful and it fixes a real problem.
LGTM. Hopefully this means I no longer need D14248.
I wonder if machine/stdarg.h should have an #error if _KERNEL is not defined to avoid strange error messages?
btw, do we still need this after r329163 where we start to use _stdarg.h which is the standardized version of this stuff?
Yes, that commit didn't change anything in this problem space. The problem is that the compiler's own <stdarg.h> might not be compatible with our <sys/_stdarg.h> and trying to teach the N compiler versions of <stdarg.h> to try to avoid declaring anything if our <machine/stdarg.h> has been included and vice versa is not really feasible long-term. (And by compatible I mean that they have some mutual agreement to avoid redefining symbols or types already defined, they are already using the same meaning for the symbols and types even when they clash.) In practice, it is the compiler that actually defines the layout of a va_list, so it's header is the one we should normally be using. The kernel only declares one because it wants to be freestanding. (E.g. GCC's stdarg.h unconditionally defines va_list and only has conditional checks for the va_start, etc. macros and we'd have to patch GCC's stdarg.h as well as clangs if we want to mix the two headers). The C standard says that the include for va_list is <stdarg.h>. We can get by with using a different one in a freestanding environment (the kernel), but in userland we should be conformant. The same is probably true of any other std* headers that in the kernel we use <sys/stdfoo.h> but in userland we need to use <stdfoo.h> (e.g. stdint.h).
Actually, I don't think it is as otherwise I would have had more build failures. I think that sort of #error probably wouldn't fail after this commit. Most headers that are shared between the kernel and userland aren't also using va_list. Very few places actually try to share function prototypes between kernel and userland (cam and sbuf are two that do) and it is only those that are at a risk of using va_list.