如何在 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 -dumpmachine
或gcc --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。
我想在 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 -dumpmachine
或gcc --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。