Here is a solution to the problem I posted in January. The problem was that
I was getting errors when trying to compile some Mobile IP implementations
under Red Hat Lnux 5.2. Errors were of the form that certain variables,
macros, etc. were defined twice, once in an include file under the
/usr/include/linux directory and once in an include file uner /usr/include.
An example was:
> file included from /usr/include/linux/if.h:23,
> from /usr/include/linux/route.h:23,
> from includes_mn.h:23,
> from mymnode.c:18:
>/usr/include/linux/socket.h:38: warning: `SCM_RIGHTS' redefined
>/usr/include/socketbits.h:222: warning: this is the location of the
previous
>definition
>/usr/include/linux/socket.h:41: warning: `SOCK_STREAM' redefined
>/usr/include/socketbits.h:40: warning: this is the location of the previous
>definition
>/usr/include/linux/socket.h:42: warning: `SOCK_DGRAM' redefined
>/usr/include/socketbits.h:43: warning: this is the location of the previous
>definition
>/usr/include/linux/socket.h:43: warning: `SOCK_RAW' redefined
>/usr/include/socketbits.h:45: warning: this is the location of the previous
>definition
>/usr/include/linux/socket.h:44: warning: `SOCK_RDM' redefined
>/usr/include/socketbits.h:47: warning: this is the location of the previous
>definition
>/usr/include/linux/socket.h:45: warning: `SOCK_SEQPACKET' redefined
>/usr/include/socketbits.h:50: warning: this is the location of the previous
>definition
>/usr/include/linux/socket.h:46: warning: `SOCK_PACKET' redefined
>Here is the solution:
files, and add some user space #include files that are the equivalent of the
kernel space #include files, plus a few odds and ends.
In more detail:
1) There is a concept in Red Hat Linux 5.1 and above of user space and
kernel space. I'll explain this concept as best I can later on, but in the
mean time, please realise that this is an important concept.
2) In your makefile, look for programs and object files compiled in user
space.
How do you tell? Look in the command line. Executables and object files
which are compiled for Kernel space have the following macro defined:
__KERNEL__. This either appears in a file, e.g. #define __KERNEL__, or in
the command lines that call the compiler, e.g.. -D__KERNEL__.
Object files and executables compiled for kernel space are also likely to
have the following in their compile command
-I/usr/src/linux/include
The remaining executable and object files are compiled for user space.
Note that it is possible for the same .h file to be compiled in either
kernel space or user space, depending on which .c file #includes it, and
whether the compile command defines __KERNEL__ or not.
3) Start compiling user space source code into object files.
If you get any errors of the form that a particular macro or struct or
typedef etc. is defined twice, you will notice that one definition is in a
file whose name contains linux, e.g. linux/xxx.h, and the other is in a non
linux file, e.g. sys/xxx.h.
To fix the problem, do the following:
4) Open up the .c file and look for #include lines with a linux directory in
the name of the file, e.g.
#include <linux/if_arp.h>
There may be several of these in a block, and there may be more than one
place where they appear.
5) Put the following before each such line or block of such lines.
#ifdef __KERNEL__
and the following lines after each such block of #include lines:
#else
#endif
so that you might have a block that looks somehting like this:
#ifdef __KERNEL__
#include <linux/xxxx.h>
#include <linux/yyyy.h>
#else
#endif
6) Between each of the #else and #endif's that you've just created, add some
#include files that are the user space equivalent of the <linux/xxx.h>
#include lines between the #ifdef __KERNEL__ and #else pairs.
For example, if there is an '#include <linux/if_arp.h>', add '#include
<net/if_arp.h> between #else and #endif. If there is an '#include
<linux/if_ether.h>', add '#include <netinet/if_ether.h> etc.
So you might end up with:
#ifdef __KERNEL__
#include <linux/if_arp.h>
#include <linux/if_ether.h>
#else
#include <net/if_arp.h>
#include <netinet/if_ether.h>
#endif
To find the equivalent user space #include file for, say <linux/if_arp.h> do
the following:
a) cd /usr/include
b) ls if_arp.h */if_arp.h
c) Ignore results like linux/if_arp.h, or anything in the asm or scsi
directory. Everything else is a user space file.
Note: You may not always find a user space #include file that has the same
name as a kernel space #include file. For example, there is no user space
equivalent to <linux/module.h>. In this case, don't worry about it for now.
You may get by without one. If you have problems later see step xxx below.
Note: Sometimes you may find two files, e.g. abc.h and sys/abc.h. In this
case, try one and see what you get.
7) If you get compiler error messages saying that types such as "__u8",
"__u16" etc. are undefined, then add the following to any such .c file, near
the top of the file.
#ifndef __KERNEL__
#include <asm/types.h>
#endif
8) Repeat step 5 & 6 for .h files that contain lines like '#include
<linux/xxx.h>'.
9) Compile the user space C files into object files and then try and link
them into executables.
10) Eliminate compilation errors:
a) If you get an error that certain macros, types, structs, etc. are
undefined, this is probably because in step 5 and 6, you found some kernel
space #include files that didn't have an equivalent user space #include file
with the same name, and it matters.
In this case, you will have to look for a user space #include file with a
different name, that defines or declares the missing thing. You'll have to
do a grep of /usr/include and /usr/include/* to find it. Once again, ignore
results in /usr/include/linux, /usr/include/asm or /usr/include/scsi.
b) If you get messages saying that certain types, such as "__u8", "__u16",
etc. are not defined, follow step 7 above.
c) If you get error messages like:
x.c:123: warning: assignment makes pointer from integer without a cast
or something like it, it means that the compiler has seen a function such
as malloc(), but does not know it's declaration, so it treats it as an
integer function.
To fix this problem, look for the #ifndef __KERNEL__ #include <asm/types.h>
#endif block as defined in step 7), and add the following line to that
block:
#include <stdlib.h>
d) If you still get error messages saying that macros, types, structs, etc.
are defined twice, look for the first #include file with this problem that's
not part of your source code, and that's not inside an #ifdef __KERNEL__ ...
#else ... #endif block. You could try putting it between the #else and
#endif in an #ifdef __KERNEL__ ... #else ... #endif block.
11) Repeat step 10 until the file compiles.
12) Move onto the next user space .c file and repeat steps above
13) Try compiling some Kernel space .c files and see how you go. You should
have no errors here.
A more detailed explanation
In Red Hat Linux 5.1 and 5.2 and other recent versions of Linux (but not
Slackware I believe) they use a new C library called GlibC version 6.0.
This library has the concept of two different spaces, a kernel space and a
user space. The idea of the different spaces is that you can have different
definitions for various constants in each of these spaces. For example,
there is a type called size_t in UNIX which is used as a variable type in
manny operating system function calls. Under user space, size_t could be one
size (e.g. 4 bytes) whereas under kernel space, size_t could be another
(e.g. 8 bytes).
The idea is that programs written by users for normal usage would use user
space, whereas programs written to be used by the kernel, are written in
Kernel space. As to programs which use both, I don't know, I'm not a Linux
expert.
The result is that there are differernt definitions for various types,
structs, etc. for user space and for kernel space, and there are two sets of
#include files. The kernel space set is in /usr/src/linux/include, whereas
the user space files are in
/usr/include.
The following directories are also for kernel space files:
/usr/include/asm - which is a symbolic link to /usr/src/linux/include/asm
/usr/include/scsi - which is a symbolic link to /usr/src/linux/include
/usr/include/linux - which is a symbolic link to
/usr/src/linux/include/linux
When you compile a program in user space that also interacts with the kernel
in some way, and therefore includes <linux/*.h> files, problems resulting
from two different sets of definitions of macros, types, structs, etc. may
arise.
The above solution has fixed the problem for me when it has cropped up.
Hope this helps.
Liron Lightwood