天天看點

gcc limits.h的bug定位看include_next和預設搜尋路徑

手編的交叉編譯工具鍊經常報一堆宏未定義,例如下面是編譯gtest的時候報_POSIX_PATH_MAX宏未定義,有時還會上報SSIZE_MAX等宏未定義:

googletest/src/gtest-filepath.cc: In static member function ‘static testing::internal::FilePath testing::internal::FilePath::GetCurrentDir()’:

googletest/src/gtest-filepath.cc:61:26: error: ‘_POSIX_PATH_MAX’ was not declared in this scope

# define GTEST_PATH_MAX_ _POSIX_PATH_MAX

^

googletest/src/gtest-filepath.cc:111:12: note: in expansion of macro ‘GTEST_PATH_MAX_’

char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };

googletest/src/gtest-filepath.cc:112:25: error: ‘cwd’ was not declared in this scope

char* result = getcwd(cwd, sizeof(cwd));

經查,SSIZE_MAX和_POSIX_PATH_MAX都定義在include/bits/posix1_lim.h,理論上會有include/limits.h檔案會包含,而但實際未生效。下面是gtest-filepath.cc裡面的頭檔案包含定義,可以看出對普通linux而已做47行增加了limits.h的包含。

gcc limits.h的bug定位看include_next和預設搜尋路徑

搜尋了一下交叉編譯工具鍊的目錄,有7處limits.h的定義,其中/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/include/limits.h和/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/limits.h裡面還有include_next的用法來二次包含limits.h檔案

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/lib/gcc/x86_64-linux-gnu/5.5.0/include-fixed/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/lib/gcc/x86_64-linux-gnu/5.5.0/install-tools/include/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/include/linux/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/include/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/c++/5.5.0/tr1/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/linux/limits.h

/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/limits.h

下面是/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/include/limits.h和/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/limits.h檔案裡面的摘錄,原來123行是沒有注釋的。

gcc limits.h的bug定位看include_next和預設搜尋路徑

通過在上面這2個頭檔案裡面打點(增加 #error 編譯宏)發現上面這2個頭檔案實際上預設都沒用,但如果修改include-fixed目錄下面的limits.h檔案的名稱,編譯過程中才會實際引用到include/limits.h,但include_next都二次搜尋又會報找不到limits.h的錯誤。

從這個現象推斷,交叉編譯工具鍊優先包含的時候include-fixed下面的頭檔案,include_next是對頭檔案搜尋路徑的二次搜尋。

通過注釋掉/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/include/limits.h和/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/x86_64-linux-gnu/include/limits.h裡面的include_next定義,并在/opt/efb/efb_x86_64_gcc-5.5.0_glibc-2.17_linux/lib/gcc/x86_64-linux-gnu/5.5.0/include-fixed/limits.h中增加include_next定義之後故障解決。