Comment 16 for bug 868550

Revision history for this message
Dave Martin (dave-martin-arm) wrote : Re: [Bug 868550] Re: __linux__ is not getting defined in android-build

I don't disupte that your suggestion can work, and there is
precedent.

(Question: does android support any of the arches force-define
__linux__? Part of the problem here is the existence of
multiple possible userspace environments on top of the same
kernel, which breaks the normal assumptions.)

The problem is that __linux__ existed before us, and we can't
therefore dictate what it means while being guaranteed not to
get into trouble.

When building the kernel, we have more control over the
namespace, so to a large extent we can get away with having
this meaning for __linux__. But for code shared with userspace,
we don't have that luxury.

> Also, we currently have to use android specific patches already when
> building a kernel for android, so adding yet another patch in there to
> add -D__linux__ for the andrdoid toolchain sounds reasonable. For the
> exported header files, let's first see if the unifdef approach works.
> AFAIU, the real issue here is that you cannot build android user space
> with the header files exported from a regular kernel, and that should
> really be possible and not rely on any patches at all.

The problem with __linux__ in exportable headers is that is
used to mean three independent things:

a) The code is applicable when building the Linux kernel only
   (and should not be exported to userspace)

b) The code is applicable to interfacing with the Linux kernel
   (as opposed to, say, BSD)

c) The code is applicable to conventional Linux userspace (as
   opposed to, say, android)

(c) is used to adapt to system dependent things such as what is
expected to appear in the standard headers. This may be
different between Linux and android userspace.

Now, we could say that:
 (a) == defined(__linux__) && defined(__KERNEL__)
 (b) == defined(__linux__)

But we can't then say
 (c) == defined(__linux__)

... beacuse meaning (b) appears different from meaning (c). It
could be argued that (b) is necessary for (c), but (b) is not
sufficient for (c).

Unfortunatekly, (c) == defined(__linux__) is the de facto
meaning as defined by the toolchain and used all over userspace.
Therefore the condition for (b) has to be something less
specific. Because the definition given above is already
atomic, a less specific definition would have to look something
like:

 (b) == defined(__linux__) || defined(__something_else__)

If we have to invent __something_else__ in order to define (b),
then we may as well use it in the definition of (a) too,
instead of relying on __linux__. This would also improve
consistency, since it allows for a single, consistent meaning
both for __linux__ and for __something_else__, avoiding the
problem of having different meanings in different places.

That's the essence of why I think a new macro is needed to solve
the problem properly. If we must change stuff, I prefer to
improve the overall level of correctness and so reduce the
chance of having to revisit this in the future.

Mans' proposed __linux_kernel__ satisfies the requirements for
__something_else__ in this logic if we modify it not to imply
__KERNEL__, leading to:

 (a) == defined(__linux_kernel__) && defined(__KERNEL__)
 (b) == defined(__linux_kernel__)
 (c) == defined(__linux__)

However, I'm no logician -- the above argument is probably
riddled with flaws. If someone can point out what they are,
then we may be able to justify the more pragmatic solution.

If we can't figure out why this argument is wrong but also
can't agree that it is correct; or if we think that this issue
isn't important enough to deserve the required kernel changes,
then it may be better that we don't change the kernel tree at
all and just put the appropriate bodge in the android team's
toolchain or kernel build scripts as Arnd has suggested.

Cheers
---Dave