简体   繁体   English

Arch Linux 的 GCC 预处理器指令

[英]GCC preprocessor directives for Arch Linux

Does GCC (or alternatively Clang) defines any macro when it is compiled for the Arch Linux OS? GCC(或 Clang)在为 Arch Linux OS 编译时是否定义了任何宏?

I need to check that my software restricts itself from compiling under anything but Arch Linux (the reason behind this is off-topic).我需要检查我的软件是否限制自己在 Arch Linux 之外的任何环境下编译(这背后的原因是题外话)。 I couldn't find any relevant resources on the internet.我在互联网上找不到任何相关资源。

Does anyone know how to guarantee through GCC preprocessor directives that my binaries are only compilable under Arch Linux?有谁知道如何通过 GCC 预处理器指令保证我的二进制文件只能在 Arch Linux 下编译?

Of course I can always当然我总是可以

#ifdef __linux__
  ...
#endif

But this is not precise enough.但这还不够精确。

Edit: This must be done through C source code and not by any building systems, so, for example, doing this through CMake is completely discarded.编辑:这必须通过 C 源代码而不是任何构建系统来完成,因此,例如,通过 CMake 执行此操作将被完全丢弃。

Edit 2: Users faking this behaviour is not a problem since the software is distributed to selected clients and thus, actively trying to "misuse" our source code is "their decision".编辑 2:用户伪造此行为不是问题,因为该软件已分发给选定的客户,因此,积极尝试“滥用”我们的源代码是“他们的决定”。

You can list the predefined preprocessor macros with您可以列出预定义的预处理器宏

gcc -dM -E - /dev/null
clang -dM -E - /dev/null

None of those indicate what operating system the compiler is running under.这些都没有表明编译器在哪个操作系统下运行。 So not only you can't tell whether the program is compiled under Arch Linux, you can't even tell whether the program is compiled under Linux.所以你不仅无法判断程序是否在 Arch Linux 下编译,甚至无法判断程序是否在 Linux 下编译。 The macros __linux__ and friends indicate that the program is being compiler for Linux.__linux__和朋友表明该程序正在Linux 编译。 They are defined when cross-compiling from another system to Linux, and not defined when cross-compiling from Linux to another system.它们是在从另一个系统交叉编译到 Linux 时定义的,而不是在从 Linux 交叉编译到另一个系统时定义的。

You can artificially make your program more difficult to compile by specifying absolute paths for system headers and relying on non-portable headers (eg /usr/include/bits/foo.h ).您可以通过指定系统头文件的绝对路径并依赖不可移植的头文件(例如/usr/include/bits/foo.h )人为地使您的程序更难编译。 That can make cross-compilation or compilation for anything other than Linux practically impossible without modifying the source code.在不修改源代码的情况下,这几乎不可能对 Linux 以外的任何东西进行交叉编译或编译。 However, most Linux distributions install headers in the same location, so you're unlikely to pinpoint a specific distribution.但是,大多数 Linux 发行版都将标头安装在同一位置,因此您不太可能确定特定的发行版。

You're very likely asking the wrong question .你很可能问错了问题 Instead of asking how to restrict compilation to Arch Linux, start from why you want to restrict compilation to Arch Linux.与其问如何将编译限制为 Arch Linux,不如从为什么要将编译限制为 Arch Linux 开始。 If the answer is “because the resulting program wouldn't be what I want under another distribution”, then start from there and make sure that the difference results in a compilation error rather than incorrect execution.如果答案是“因为生成的程序在另一个发行版下不是我想要的”,那么从那里开始并确保差异导致编译错误而不是错误执行。 If the answer to “why” is something else, then you're probably looking for a technical solution to a social problem, and that rarely ends well.如果“为什么”的答案是其他问题,那么您可能正在寻找解决社会问题的技术解决方案,而这很少有好的结果。

Does GCC (or alternatively Clang) defines any macro when it is compiled for the Arch Linux OS? GCC(或 Clang)在为 Arch Linux OS 编译时是否定义了任何宏?

No. Because there's nothing inherently specific to Arch Linux on the binary level.不,因为在二进制级别上 Arch Linux 没有任何固有的特性。 For what it's worth, when compiling the only things you/the compiler has to care about is the target architecture (ie what kind of CPU it's going to run with), data type sizes and alignments and function calling conventions.对于它的价值,在编译时你/编译器唯一需要关心的是目标架构(即它将运行什么样的 CPU)、数据类型大小和对齐以及函数调用约定。

Then later on, when it's time to link the compiled translation unit objects into the final binary executable, the runtime libraries around are also of concern.稍后,当需要将编译后的翻译单元对象链接到最终的二进制可执行文件中时,周围的运行时库也很重要。 Without taking special precautions you're essentially locking yourself into the specific brand of runtime libraries (glibc vs. eg musl; libstdc++ vs. libc++) pulled by the linker.如果不采取特殊的预防措施,您实际上会将自己锁定在由链接器拉动的特定品牌的运行时库中(glibc 与例如 musl;libstdc++ 与 libc++)。

One can easily sidestep the later problem by linking statically, but that limits the range of system and midlevel APIs available to the program.可以通过静态链接轻松回避后面的问题,但这限制了程序可用的系统和中级 API 的范围。 For example on Linux a purely naively statically linked program wouldn't be able to use graphics acceleration APIs like OpenGL-3.x or Vulkan, since those rely on loading components of the GPU drivers into the process.例如,在 Linux 上,纯粹的静态链接程序无法使用 OpenGL-3.x 或 Vulkan 等图形加速 API,因为它们依赖于将 GPU 驱动程序的组件加载到进程中。 You can however still use X11 and indirect GLX OpenGL, since those work using wire protocols going over sockets, which are implemented using direct syscalls to the kernel.但是,您仍然可以使用 X11 和间接 GLX OpenGL,因为它们使用通过套接字的有线协议工作,这些协议是使用对内核的直接系统调用来实现的。

And these kernel syscalls are exactly the same on the binary level for each and every Linux kernel of every distribution out there.对于每个发行版的每个 Linux 内核,这些内核系统调用在二进制级别上都是完全相同的 Although inside of the kernel there's a lot of leeway when it comes to redefining interfaces, when it comes to the interfaces toward the userland (ie regular programs) there's this holy, dogmatic, ironclad rule that YOU NEVER BREAK USERLAND!尽管内核内部在重新定义接口方面有很多余地,但在涉及面向用户空间的接口(即常规程序)时,有一条神圣的、教条的、铁定的规则,你永远不会破坏用户空间! Kernel developers breaking this rule, intentionally or not are chewed out publicly by Linus Torvalds in his in-/famous rants.违反此规则的内核开发人员有意或无意地被 Linus Torvalds 在他的臭名昭著的咆哮中公开抨击。

The bottom line to this is, that there is no such thing as a " Linux distribution specific identifier on the binary level ".最重要的是,没有“二进制级别的 Linux 发行版特定标识符”之类的东西。 At the end of the day, a Linux distribution is just that: A distribution of stuff.归根结底,Linux 发行版就是这样:东西的发行版。 That means someone or more decided on a set of files that make up a working Linux system, wrap it up somehow and slap a name on it.这意味着有人或更多人决定了一组文件,这些文件组成了一个工作的 Linux 系统,以某种方式将其包装起来并为其命名。 That's it.而已。 There's nothing inherently specific to "Arch" Linux other than it's called "Arch" and (for the time being) relies on the pacman package manager.除了被称为“Arch”并且(暂时)依赖于pacman包管理器之外,“Arch”Linux 并没有什么固有的特性。 That's it.而已。 Everything else about "Arch", or any other Linux distribution, is just a matter of happenstance.关于“Arch”或任何其他 Linux 发行版的其他一切都只是偶然的问题。

If you really want to sort different Linux distributions into certain bins regarding binary compatibility, then you'd have to pigeonhole the combinations of如果您真的想将不同的 Linux 发行版分类到有关二进制兼容性的某些箱中,那么您必须将以下组合归类

  • Minimum required set of supported syscalls.所需的最小支持系统调用集。 This translates into minimum required kernel version.这转化为所需的最低内核版本。

  • What libc variant is being used;正在使用什么 libc 变体; and potentially which version, although it's perfectly possible to link against a minimally supported set of functions, that has been around for almost "forever".并且可能是哪个版本,尽管完全有可能链接到一组最少支持的功能,但几乎“永远”存在。

  • What variant of the C++ standard library the distribution decided upon.分发决定的 C++ 标准库的变体。 This actually also inflicts programs that might appear to be purely C, because certain system level libraries ( *cough* Mesa *cough* ) will internally pull a lot of C++ infrastructure (even compilers), also triggering other "fun" problems¹这实际上也会导致可能看起来纯粹是 C 的程序,因为某些系统级库 ( *cough* Mesa *cough* ) 会在内部拉取大量 C++ 基础架构(甚至是编译器),还会触发其他“有趣”的问题¹

I need to check that my software restricts itself from running under anything but Arch Linux (the reason behind this is off-topic).我需要检查我的软件是否限制自己在 Arch Linux 之外的任何环境下运行(这背后的原因是题外话)。 I couldn't find any relevant resources on the internet.我在互联网上找不到任何相关资源。

You couldn't find resources on the Internet, because there's nothing specific on the binary level that makes "Arch" Arch.您无法在 Internet 上找到资源,因为在二进制级别上没有任何特定的东西可以制作“Arch”Arch。 For what it's worth right now, this instant I could create a fork of Arch, change out its choice of default XDG skeleton – so that by default user directories are populated with subdirs called leech , flicks , beats , pics – and call it "l33tz" Linux.对于现在的价值,我可以立即创建一个 Arch 的分支,更改其默认 XDG 骨架的选择——这样默认情况下用户目录会填充名为leechflicksbeatspics的子目录——并将其命名为“l33tz “Linux。 For all intents and purposes it's no longer Arch.出于所有意图和目的,它不再是 Arch。 It does behave significantly different from the default Arch behavior, which would also be of concern to you, if you'd relied on any specific thing, and be it most minute.它的行为确实与默认的 Arch 行为有很大不同,如果你依赖任何特定的东西,这也是你所关心的,而且是最微小的。

Your employer doesn't seem to understand what Linux is or what distinguished distributions from each other.您的雇主似乎不了解 Linux 是什么,也不了解各个发行版之间的区别。

Hint: It's not the binary compatibility.提示:这不是二进制兼容性。 As a matter of fact, as long as you stay within the boring old realm of boring old glibc + libstdc++ Linux distributions are shockingly compatible with each other.事实上,只要你停留在无聊的老glibc + libstdc++ Linux 发行版之间,就可以令人震惊地相互兼容。 There might be slight differences in where they put libraries other than libc.so , libdl.so and ld-linux[-${arch}].so , but those two usually always can be found under /lib .除了libc.solibdl.sold-linux[-${arch}].so之外,它们放置库的位置可能略有不同,但这两个通常总是可以在/lib下找到。 And once ld-linux[-${arch}].so and libdl.so take over (that means pulling in all libraries loaded at runtime) all the specifics of where shared objects and libraries are to be found are abstracted away by the dynamic linker.一旦ld-linux[-${arch}].solibdl.so接管(这意味着拉入在运行时加载的所有库),找到共享对象和库的所有细节都被动态抽象掉了链接器。


1: like becoming multithreaded only after global constructors were executed and libstdc++ deciding it wants to be singlethreaded, because libpthread wasn't linked into a program that didn't create a single thread on its own. 1:就像只有在执行全局构造函数并且 libstdc++ 决定它想要成为单线程之后才成为多线程一样,因为 libpthread 没有链接到没有自己创建单线程的程序中。 That was a really weird bug I unearthed, but yshui finally understood https://gitlab.freedesktop.org/mesa/mesa/-/issues/3199那是我发现的一个非常奇怪的错误,但是yshui终于明白了https://gitlab.freedesktop.org/mesa/mesa/-/issues/3199

No, it doesn't.不,它没有。 And even if it did, it wouldn't stop anyone from compiling the code on an Arch Linux distro and then running it on a different Linux.即使这样做了,它也不会阻止任何人在 Arch Linux 发行版上编译代码,然后在不同的 Linux 上运行它。

If you need to prevent your software from "from running under anything but Arch Linux", you'll need to insert a run-time check.如果您需要阻止您的软件“在 Arch Linux 之外的任何环境下运行”,则需要插入运行时检查。 Although, to be honest, I have no idea what that check might consist of, since linux distros are not monolithic products.虽然,老实说,我不知道检查可能包含什么,因为 linux 发行版不是单一产品。 The actual check would probably have to do with your reasons for imposing the restriction.实际检查可能与您施加限制的原因有关。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM