GCC(或 Clang)在為 Arch Linux OS 編譯時是否定義了任何宏?
我需要檢查我的軟體是否限制自己在 Arch Linux 之外的任何環境下編譯(這背后的原因是題外話)。我在互聯網上找不到任何相關資源。
有誰知道如何通過 GCC 前處理器指令保證我的二進制檔案只能在 Arch Linux 下編譯?
當然我總是可以
#ifdef __linux__
...
#endif
但這還不夠精確。
編輯:這必須通過 C 源代碼而不是任何構建系統來完成,因此,例如,通過 CMake 執行此操作將被完全丟棄。
編輯 2:用戶偽造此行為不是問題,因為該軟體已分發給選定的客戶,因此,積極嘗試“濫用”我們的源代碼是“他們的決定”。
uj5u.com熱心網友回復:
GCC(或 Clang)在為 Arch Linux OS 編譯時是否定義了任何宏?
不,因為在二進制級別上 Arch Linux 沒有任何固有的特性。對于它的價值,在編譯時你/編譯器唯一需要關心的是目標架構(即它將運行什么樣的 CPU)、資料型別大小和對齊以及函式呼叫約定。
稍后,當需要將編譯后的翻譯單元物件鏈接到最終的二進制可執行檔案中時,周圍的運行時庫也很重要。如果不采取特殊的預防措施,您實際上會將自己鎖定在由聯結器拉動的特定品牌的運行時庫中(glibc 與例如 musl;libstdc 與 libc )。
可以通過靜態鏈接輕松回避后面的問題,但這限制了程式可用的系統和中級 API 的范圍。例如,在 Linux 上,純粹的靜態鏈接程式將無法使用 OpenGL-3.x 或 Vulkan 等圖形加速 API,因為它們依賴于將 GPU 驅動程式的組件加載到行程中。但是,您仍然可以使用 X11 和間接 GLX OpenGL,因為它們使用通過套接字的有線協議作業,這些協議是使用對內核的直接系統呼叫來實作的。
對于每個發行版的每個 Linux 內核,這些內核系統呼叫在二進制級別上都是完全相同的。盡管內核內部在重新定義介面時有很多余地,但當涉及到面向用戶空間的介面(即常規程式)時,有一條神圣的、教條的、鐵定的規則,你永遠不會破壞用戶空間!違反此規則的內核開發人員有意或無意地被 Linus Torvalds 在他的臭名昭著的咆哮中公開抨擊。
最重要的是,沒有“二進制級別的 Linux 發行版特定識別符號”之類的東西。歸根結底,Linux 發行版就是這樣:東西的發行版。這意味著有人或更多人決定了一組檔案,這些檔案組成了一個作業的 Linux 系統,以某種方式將其包裝起來并為其命名。就是這樣。除了被稱為“Arch”并且(暫時)依賴于pacman包管理器之外,“Arch”Linux 并沒有什么固有的特性。就是這樣。關于“Arch”或任何其他 Linux 發行版的其他一切都只是偶然的問題。
如果您真的想將不同的 Linux 發行版分類到有關二進制兼容性的某些箱中,那么您必須將以下組合歸類
所需的最小支持系統呼叫集。這轉化為所需的最低內核版本。
正在使用什么 libc 變體;并且可能是哪個版本,盡管完全有可能鏈接到一組最少支持的功能,但幾乎“永遠”存在。
分發決定的 C 標準庫的變體。這實際上也會導致可能看起來純粹是 C 的程式,因為某些系統級庫 ( *cough* Mesa *cough* ) 將在內部提取大量 C 基礎架構(甚至是編譯器),還會觸發其他“有趣”問題1
我需要檢查我的軟體是否限制自己在 Arch Linux 之外的任何環境下運行(這背后的原因是題外話)。我在互聯網上找不到任何相關資源。
您無法在 Internet 上找到資源,因為在二進制級別上沒有任何特定的東西可以制作“Arch”Arch。對于現在的價值,我可以立即創建 Arch 的一個分支,更改它對默認 XDG 骨架的選擇——以便默認情況下用戶目錄填充名為leech, flicks, beats,的子目錄pics——并將其稱為“l33tz”Linux。出于所有意圖和目的,它不再是 Arch。它的行為確實與默認的 Arch 行為有很大不同,如果你依賴任何特定的東西,這也是你所關心的,而且是最微小的。
您的雇主似乎不了解 Linux 是什么,也不了解各個發行版之間的區別。
提示:這不是二進制兼容性。事實上,只要你停留在無聊的老glibc libstdc Linux 發行版之間,就可以令人震驚地相互兼容。libc.so除了,libdl.so和之外,它們放置庫的位置可能略有不同ld-linux[-${arch}].so,但這兩個通常總是可以在/lib. ld-linux[-${arch}].so并且一旦libdl.so接管(這意味著拉入在運行時加載的所有庫),在何處找到共享物件和庫的所有細節都被動態聯結器抽象出來。
1:就像只有在執行全域建構式并且 libstdc 決定它想要成為單執行緒之后才成為多執行緒一樣,因為 libpthread 沒有鏈接到沒有自己創建單執行緒的程式中。那是我發現的一個非常奇怪的錯誤,但是yshui終于明白了https://gitlab.freedesktop.org/mesa/mesa/-/issues/3199
uj5u.com熱心網友回復:
不,它沒有。即使這樣做了,也不會阻止任何人在 Arch Linux 發行版上編譯代碼,然后在不同的 Linux 上運行它。
如果您需要阻止您的軟體“在 Arch Linux 之外的任何環境下運行”,則需要插入運行時檢查。雖然,老實說,我不知道檢查可能包括什么,因為 linux 發行版不是單一產品。實際檢查可能與您施加限制的原因有關。
uj5u.com熱心網友回復:
您可以列出預定義的前處理器宏
gcc -dM -E - /dev/null
clang -dM -E - /dev/null
這些都沒有表明編譯器在哪個作業系統下運行。所以你不僅無法判斷程式是否在 Arch Linux 下編譯,甚至無法判斷程式是否在 Linux 下編譯。宏__linux__和朋友表明該程式正在為Linux 編譯。它們是在從另一個系統交叉編譯到 Linux 時定義的,而不是在從 Linux 交叉編譯到另一個系統時定義的。
/usr/include/bits/foo.h您可以通過指定系統頭檔案的絕對路徑并依賴不可移植的頭檔案(例如),人為地使您的程式更難編譯。在不修改源代碼的情況下,這幾乎不可能對 Linux 以外的任何東西進行交叉編譯或編譯。但是,大多數 Linux 發行版都將標頭安裝在同一位置,因此您不太可能確定特定的發行版。
你很可能問錯了問題。與其問如何將編譯限制為 Arch Linux,不如從為什么要將編譯限制為 Arch Linux 開始。如果答案是“因為生成的程式在另一個發行版下不是我想要的”,那么從那里開始并確保差異導致編譯錯誤而不是錯誤執行。如果“為什么”的答案是其他問題,那么您可能正在尋找解決社會問題的技術解決方案,而這很少有好的結果。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/475423.html
