Question

I'm trying to build uClibc 0.9.27 [1] on x86_64 with the linux kernel 3.10-2-amd64. I can verify that it builds on Ubuntu 12.04.3 with the 3.2.0-49-generic kernel. When running make, it manages to build a lot of object files but eventually reaches CC libc/inet/if_index.os, complaining with

In file included from /usr/include/linux/kernel.h:4,
                 from /usr/include/linux/netlink.h:4,
                 from /usr/include/linux/rtnetlink.h:5,
                 from libc/inet/netlinkaccess.h:32,
                 from libc/inet/if_index.c:36:
/usr/include/linux/sysinfo.h:8: error: expected specifier-qualifier-list before '__kernel_long_t'
In file included from /usr/include/linux/rtnetlink.h:6,
                 from libc/inet/netlinkaccess.h:32,
                 from libc/inet/if_index.c:36:
/usr/include/linux/if_link.h:317: error: expected specifier-qualifier-list before '__be16'

I verified that the types exist in files that I gather should have been sucked in. In the case of __kernel_long_t, the include files look like this:

/usr/include/linux/sysinfo.h includes <linux/types.h>
/usr/include/linux/types.h includes <linux/posix_types.h>
/usr/include/linux/posix_types.h includes <asm/posix_types.h>
/usr/include/x86_64-linux-gnu/asm/posix_types.h includes <asm/posix_types_64.h>
/usr/include/x86_64-linux-gnu/asm/posix_types_64.h includes <asm-generic/posix_types.h>
/usr/include/asm-generic/posix_types.h typedefs __kernel_long_t

So, where does that error come from, and how can I fix it?


[1] Yes, I know the newest version is 0.9.33.2, but I need that particular version.

Was it helpful?

Solution

The solution seems to be to backport a newer version of libc/inet/netlinkacces.h to the older version. The __kernel_long_t problem goes away by avoiding an include (if necessary, that would have to be patched in kernel_types.h, because the defines intentionally shadow the include guards of the headers in /usr/include) and the other type(s) can be properly included by the following patch:

index 417d83a..1b9c857 100644
--- a/libc/inet/netlinkaccess.h
+++ b/libc/inet/netlinkaccess.h
@@ -21,16 +21,7 @@

 #include <features.h>
 #include <stdint.h>
-#include <sys/types.h>
-
-#define _LINUX_TYPES_H
-typedef uint8_t __u8;
-typedef uint16_t __u16;
-typedef uint32_t __u32;
-typedef uint64_t __u64;
-typedef int32_t __s32;
-#include <linux/rtnetlink.h>
-#include <linux/netlink.h>
+#include <unistd.h>

 /* Should prob be a configure option or something */
 #ifndef __ASSUME_NETLINK_SUPPORT

This is basically the change between the old netlinkaccess.h and the one in the newer version (diffing of the preprocessed files suggested by ash hinted me to this).

OTHER TIPS

It's hard to say where the error comes from without looking carefully at the code in question. Most likely is a case that the package itself is not compatible with the environment within which you are attempting to build the software. With that said, it's possible to track it down, if you are willing to do so. From there, the solution is likely either changing settings at the start of the build process, or modifying the code to correct a mistake.

This problem is tricky to track down since it's a third-party package performing the includes. And, if it's written to build on multiple architectures, it will likely contain a lot of preprocessor directives that make it hard to even know which code is actually being used.

I recommend capturing the command that generates the error (looks like that may be CC libc/inet/if_index.os although CC of an os file seems odd), then modify the cc command to capture the preprocessed output.

For example, to get preprocessed output from this:

cc -c prog.c -o prog.o

Use this intead:

cc -E prog.c >prog.i

Then search though prog.i for the line in question. It's tricky to locate specific line numbers, so it's best to search for text - although that can be tricky too since some words will be replaced by the preprocessor. The good news here is that the output will tell you exactly what the compiler is trying to compile - after all includes have been processed and macros applied. Just "pure C" code.

Do this on the version that works and the one that does not, and see where __kernel_long_t gets pulled into the build on the good one, and then try to find why that's not happening on the failing one.

Note the lines that look like this:

# 443 "/usr/include/stdio.h"

mean "line 443" of "/usr/include/stdio.h" is the next line in the output file.

To see where a definition comes into the sources, search up from the line that contains the definition, probably a typedef as indicated in the question, and search up for the first line above that with a filename - that's the file from which it was obtained. Walk up more to see where that file was pulled in. Note that it won't necessarily be the next file above, so verify against the original sources. Doing this, eventually you'll find the part of the packaged sources that included a file with that definition. Then it should be possible to figure out why either that line isn't used in the other build, or that the same include doesn't lead to the definition of the type.

Note that I'm assuming that the error messages posted mean the problem is the missing definition for __kernel_long_t. The error could mean something just before the use of that type is a problem.

I hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top