簡體   English   中英

Arch Linux 的 GCC 預處理器指令

[英]GCC preprocessor directives for Arch Linux

GCC(或 Clang)在為 Arch Linux OS 編譯時是否定義了任何宏?

我需要檢查我的軟件是否限制自己在 Arch Linux 之外的任何環境下編譯(這背后的原因是題外話)。 我在互聯網上找不到任何相關資源。

有誰知道如何通過 GCC 預處理器指令保證我的二進制文件只能在 Arch Linux 下編譯?

當然我總是可以

#ifdef __linux__
  ...
#endif

但這還不夠精確。

編輯:這必須通過 C 源代碼而不是任何構建系統來完成,因此,例如,通過 CMake 執行此操作將被完全丟棄。

編輯 2:用戶偽造此行為不是問題,因為該軟件已分發給選定的客戶,因此,積極嘗試“濫用”我們的源代碼是“他們的決定”。

您可以列出預定義的預處理器宏

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 開始。 如果答案是“因為生成的程序在另一個發行版下不是我想要的”,那么從那里開始並確保差異導致編譯錯誤而不是錯誤執行。 如果“為什么”的答案是其他問題,那么您可能正在尋找解決社會問題的技術解決方案,而這很少有好的結果。

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++ 基礎架構(甚至是編譯器),還會觸發其他“有趣”的問題¹

我需要檢查我的軟件是否限制自己在 Arch Linux 之外的任何環境下運行(這背后的原因是題外話)。 我在互聯網上找不到任何相關資源。

您無法在 Internet 上找到資源,因為在二進制級別上沒有任何特定的東西可以制作“Arch”Arch。 對於現在的價值,我可以立即創建一個 Arch 的分支,更改其默認 XDG 骨架的選擇——這樣默認情況下用戶目錄會填充名為leechflicksbeatspics的子目錄——並將其命名為“l33tz “Linux。 出於所有意圖和目的,它不再是 Arch。 它的行為確實與默認的 Arch 行為有很大不同,如果你依賴任何特定的東西,這也是你所關心的,而且是最微小的。

您的雇主似乎不了解 Linux 是什么,也不了解各個發行版之間的區別。

提示:這不是二進制兼容性。 事實上,只要你停留在無聊的老glibc + libstdc++ Linux 發行版之間,就可以令人震驚地相互兼容。 除了libc.solibdl.sold-linux[-${arch}].so之外,它們放置庫的位置可能略有不同,但這兩個通常總是可以在/lib下找到。 一旦ld-linux[-${arch}].solibdl.so接管(這意味着拉入在運行時加載的所有庫),找到共享對象和庫的所有細節都被動態抽象掉了鏈接器。


1:就像只有在執行全局構造函數並且 libstdc++ 決定它想要成為單線程之后才成為多線程一樣,因為 libpthread 沒有鏈接到沒有自己創建單線程的程序中。 那是我發現的一個非常奇怪的錯誤,但是yshui終於明白了https://gitlab.freedesktop.org/mesa/mesa/-/issues/3199

不,它沒有。 即使這樣做了,它也不會阻止任何人在 Arch Linux 發行版上編譯代碼,然后在不同的 Linux 上運行它。

如果您需要阻止您的軟件“在 Arch Linux 之外的任何環境下運行”,則需要插入運行時檢查。 雖然,老實說,我不知道檢查可能包含什么,因為 linux 發行版不是單一產品。 實際檢查可能與您施加限制的原因有關。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM