如何在 Makefile 中找到基础架构?

How to find a base architecture inside Makefile?

我想在 Makefile 中查找,无论我是 运行 在 32 位还是 64 位机器上。

是否有可以从 Makefile 中简单访问的宏或环境变量?

我在网上找到了这个相关答案:

LBITS := $(shell getconf LONG_BIT)
ifeq ($(LBITS),64)
   # do 64 bit stuff here, like set some CFLAGS
else
   # do 32 bit stuff here
endif

但是,我怀疑在所有系统中 getconf 工具是否可用。

getconf 是一个 POSIX 工具,它应该在所有类 unix 系统上可用。但是 uname -m 将是更便携和更传统的查找系统类型的方法。

否则,您很有可能看错了方向:主机系统的位数不一定与工具链的位数相匹配。工具链(编译器、链接器)定义了结果的位数。用户可以自定义工具链以满足本地需求(例如在 64 位上编译为 32 位OS),甚至交叉编译。

要在您的工具链中查找 GCC(或 clang)的位数,您可以使用:

LBITS := $(shell $(CC) $(CFLAGS) -dM -E - </dev/null | grep -q "__LP64__" && echo 64 || echo 32)

实际上,它查询应用程序将使用什么位来编译,而不进行实际编译,但查看编译器定义的 LP parameter,表示 "data model"体系结构(LP64 表示 "long and pointer are 64-bit"(并且,通过省略,int 是 32 位);ILP32 表示 "int, long and pointer are 32-bit")。

只要您留在 Linux,就可以了。 (您需要在编译器调用中使用 CFLAGS,因为被用户覆盖的 CFLAGS 可以使用 -m32-m64 选项来更改输出的位数代码。)

tl;dr;

如果你只需要以可移植的方式在C中输入long中的位数,那么使用getconf LONG_BIT.

就可以了

否则:

  • 检测主机架构,使用config.guess shell脚本
  • 检测目标架构,使用gcc -dumpmachinegcc --help=target

正在检测主机架构

1) getconf

如@Dummy00001 所述,getconf 是 POSIX 的一部分并且广泛可用,但它没有提供足够的信息。

请注意,getconf LONG_BIT只是C中long类型的位数。例如,在16位或64位机器上可能是32位。它对确定主机体系结构毫无用处。

2) uname

uname 也是 POSIX 的一部分,它也没有提供足够的信息。

例如,在Linux上不区分硬浮点和软浮点ARM。此外,它的架构命名并不是真正可移植的。

3) /proc

您可以使用 /proc 来收集架构信息,例如/proc/cpuinfo 在 Linux 上。但是,它不可移植且难以解析。

4) config.guess

最后推荐GNUconfig.guess script (source code)。它是一个独立的脚本,您可以将其复制到您的项目中。它是用可移植的 shell 编写的,应该可以在任何 UNIX 上运行。

$ sh config.guess
x86_64-pc-linux-gnu

这个脚本是 used in autotools,但你也可以在没有 autotools 的情况下使用它。


正在检测工具链的默认目标架构

检测正在使用的工具链的目标架构通常是有意义的。交叉编译时与主机架构不同

1) gcc -E

您可以解析 gcc -E 输出以获取 gcc 目标体系结构的工具链元组:

$ gcc -v -E - </dev/null |& grep Target:
Target: x86_64-linux-gnu

如果您使用 GCC 或 clang,这应该适用于任何 UNIX。

备注:

  • 它打印在构建 GCC 时传递给 configure 脚本的 --target 选项的值。它不受传递给 GCC 的当前编译标志的影响,例如 -m32-march.
  • config.guess 不同,此工具链元组是特定于发行版的。例如,在 Debian and Gentoo.
  • 中的预构建工具链中使用了不同的方案

2) gcc -dumpmachine

似乎 gcc -dumpmachine prints the same 值与以前的配方相同:

$ gcc -dumpmachine
x86_64-linux-gnu

它适用于 GCC 和 clang。

3) gcc -print-multiarch

另一种获取工具链元组的方法:

$ gcc -print-multiarch
x86_64-linux-gnu

它适用于 GCC,但不适用于 clang。此外,已知此选项在各种情况下不起作用:

  • 在 Debian 上,如果禁用了 multilib,则为空
  • 在 Gentoo 上,它总是空的
  • 如@Dummy00001所述,交叉编译工具链可能为空(我想这取决于工具链的构建方式)

根据当前标志检测目标架构

一些 GCC 选项,如 -m32-march 会影响目标架构。

1) gcc --help=target

这将打印从默认目标体系结构(在构建 GCC 时配置)和当前编译选项推导出的 -march 选项的值。

$ gcc -Q --help=target |& grep -e -march | awk '{print }'
x86-64

$ gcc -m32 -Q --help=target |& grep -e -march | awk '{print }'
i686

$ gcc -march=i386 -Q --help=target |& grep -e -march | awk '{print }'
i386

它不适用于 clang。