接上篇centos6.10 編譯gcc11.5 x64到aarch64交叉工具鏈 -CSDN博客
PATH_MAX找不到,不僅在編譯gcc的過程中遇到,而且臨時改gcc源碼添加#define PATH_MAX 4096 宏定義后勉強通過gcc全量編譯。這個新的gcc編譯使用了PATH_MAX宏的代碼還是會找不到。這個問題看來不弄清楚不行。
PATH_MAX在哪定義的
進入到交叉gcc的include目錄查找PATH_MAX,發現是在linux/limits.h這個頭文件定義的,這是內核頭文件,同時我在用我的交叉gcc編譯protobuf時,查看報錯PATH_MAX找不到的文件,protobuf提示包含#include <limits.h>是為了提供PATH_MAX。那么說明glibc最終會引用linux/limits.h。順藤摸瓜驗證了這一猜想。
分析
于是我寫了個測試代碼,用我的gcc編譯,報錯。然后嘗試各種宏定義,也不行。
#include <stdio.h>
//#define _GNU_SOURCE 1
//##define _GCC_LIMITS_H_
//#define _POSIX_C_SOURCE 200809L
//#define _LIMITS_H___#include <limits.h>int main()
{char buf[PATH_MAX]={0};printf("hello");
}
嘗試預處理階段宏展開aarch64-linux-gnu-gcc -E hello.c | less,發現他用是下面這個limites.h
另外構建的一個本地gcc11.5.0是正常的,宏展開是這樣的,看樣子是這個incude-fixed搞得鬼
研究了半天,查找fixincludes
?的文檔這么說
當?fixincludes
?由 GCC 的 Makefile 運行時,這個?README
?文件會被復制到僅包含 GCC 頭文件的目錄中。
此目錄中的許多文件是通過?fixincludes
?過程從標準系統頭文件自動編輯而來的。它們是特定于系統的,無法在其他類型的系統上使用。它們也不是 GCC 的一部分。我們之所以需要這樣做,是因為 GCC 需要符合 ANSI C 標準的頭文件,而許多供應商提供的頭文件與 ANSI 不兼容。
由于這是一個自動化過程,有時一些嚴格來說不需要“修復”的頭文件也會被“修復”。只要這個過程沒有破壞任何東西,這只是一個不幸的附帶不便。如果“不太麻煩”,我們希望能夠糾正這種情況。
總之這個東西就是為了解決gcc與使用glibc頭不兼容,自動自行修正include頭文件的,那么是不是我編譯的gcc配置錯誤,導致修正不對。
嘗試對比能用的和不能用的incude-fixed/limits.h,差別不大,前后包了一層宏定義,替換一下能用的這個頭,他媽的果然行了。但是還沒找到是什么導致這個差異
嘗試在源碼目錄查找_GCC_LIMITS_H_ 找到了limitx.h 和limity.h 這兩個文件的內容就是前后包的代碼段
繼續找limitx.h文件名,能用和不能用的limits.h 區別在一個條件判斷,關鍵在于LIMITS_H_TEST這個變量
這個LIMITS_H_TEST的值取決于SYSTEM_HEAD_DIR
?到構建目錄找最后的Makefile,這是變量展開后的內容,$(gcc_tooldir)/sys-include。到安裝目錄下去找,確實沒有這個目錄,gcc_tooldir是上層傳入的變量,
libsubdir = $(libdir)/gcc/$(target_noncanonical)/$(version)
gcc_tooldir='$(libsubdir)/$(libsubdir_to_prefix)$(target_noncanonical)'?
libsubdir_to_prefix這個東西的意思是把libsubdir轉換成prefix需要的../..這種。那么其實libsubdir是啥不重要,gcc_tooldir 就是$(prefix)/$(target_noncanonical)
在我這里應該是安裝目錄的aarch64-linux-gnu/sys-include目錄 沒有這個目錄。
解決
配置編譯gcc時產生這個目錄,用--with-headers,會把你的glibc頭copy過去產生,或者你自己把glibc頭安裝到這個目錄。原來官方文檔說了,fixinclude會在這些文件上運行,產生兼容gcc的glibc頭,答案早就在這里啊,只是不經歷這么一遭根本理解不了