Search code examples
clinuxgccglibcchroot

Undeclared variable in a cross compiled root filesystem


So I'm cross compiling a Linux root file system basically from scratch. I was able to get all the basic software cross compiled using a very basic toolchain from scratch. Below is the list of some of the software used:

  • Binutils 2.32
  • Glibc 2.29
  • Linux 5.2.11
  • Coreutils 8.31
  • GCC 9.2.0
  • pkgconf 1.6.3
  • Make, autoconf, zlib, etc. for the root filesystem

Inside the rootfs using chroot I compile this small program using gcc:

#include <stdio.h>
#include <limits.h>

int main()
{
  printf("PATH_MAX=%u\n", PATH_MAX);
  return 0;
}

Which doesn't complete and outputs a error:

(chroot)$ gcc test.c -o test
test.c: In function 'main':
test.c:6:27: error: 'PATH_MAX' undeclared (first use in this function)
    6 |   printf("PATH_MAX=%u\n", PATH_MAX);
      |                           ^~~~~~~~
test.c:6:27: note: each undeclared identifier is reported only once for each function it appears in

However limits.h does exist in the chroot.

/usr/lib/gcc/x86_64-linux-gnu/9.2.0/install-tools/include/limits.h
/usr/lib/gcc/x86_64-linux-gnu/9.2.0/include-fixed/limits.h
/usr/include/c++/9.2.0/tr1/limits.h
/usr/include/limits.h
/usr/include/linux/limits.h

Lastly, below is the paths for gcc inside the chroot (This is not the toolchain):

COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/9.2.0/cc1 -E -quiet -v /dev/null -mtune=generic -march=x86-64
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/9.2.0/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/9.2.0/include-fixed
 /usr/include
End of search list.
# 1 "/dev/null"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "/dev/null"
COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/9.2.0/:/usr/lib/gcc/x86_64-linux-gnu/9.2.0/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/9.2.0/:/usr/lib/gcc/x86_64-linux-gnu/
LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/9.2.0/:/usr/lib/gcc/x86_64-linux-gnu/9.2.0/../../../../lib/:/lib/../lib/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/9.2.0/../../../:/lib/:/usr/lib/

So with that being said, what is going on? I've looked through my toolchain and the actual root filesystem packages multiple times and everything looks okay. What could the problem be? Also what are some debugging steps that I can take to help identify this problem and any future problems down the road?

EDIT:

To add more context about this issue, previously I've tried to compile the latest kmod but get the 'PATH_MAX' undeclared error as well:

make --no-print-directory all-recursive
Making all in .
  GEN      libkmod/libkmod.pc
  CC       tools/kmod.o
  CC       tools/lsmod.o
In file included from tools/kmod.c:26:
./shared/util.h:24:56: error: 'PATH_MAX' undeclared here (not in a function)
   24 | int alias_normalize(const char *alias, char buf[static PATH_MAX], size_t *len) _must_check_ __attribute__((nonnull(1,2)));
      |                                                        ^~~~~~~~

Going into shared/util.h has #include <limits.h> the only way to fix it is to use #include <linux/limits.h> which basically fixes the issue. However there's something bigger going on. I shouldn't have todo that. I figured to ask this question with a much simpler example as to take out as many variables as possible. I hope this brings more context to my issue.


Solution

  • <limits.h> is part of the C standard library, so you really have to have that in somewhere, somehow, if not builtin in the compiler. The PATH_MAX is a POSIX extension. If by some reason your cross compiler is not enabling necessary flags, you could try with

    #define _POSIX_C_SOURCE 1
    #include <limits.h>
    

    If it still fails then you do not have the target system headers installed.