如何在编译时检测 ABI?
How to detect ABI at compile time?
有没有办法在编译时检测 C/C++ 中的 ABI?我知道有 OS 和 CPU 架构的宏。 ABI 是否有类似的宏(或其他方式)?
ABI 的概念不为 C11 或 C++14 等标准规范所知。这是一个实现的事情。
您可以在 Linux 上使用 feature_test_macros(7)。
您可以考虑改进您的构建过程(例如,您的 Makefile
, etc...). You might run some shell script detecting features (like autoconf generated configure
scripts do). Notice that some C or C++ code (e.g. header files, etc...) might be generated at build time (for examples: by bison, moc, rpcgen, swig, ...), perhaps by your own utilities or scripts. Use a good enough build automation tool (with care, GNU make and ninja 能够处理生成的 C++ 或 C 代码并管理它们的生成和依赖项)。
不要将编译与 build; the compilation commands running a compiler 混淆,它们只是构建过程的 部分 。
一些平台接受几个 ABI。例如。我的 Linux/Debian/Sid/x86-64 带有 Linux 4.13 内核的桌面可以 运行 x86 32 位 ELF executable, x86-64 64 bits ELF, probably some old a.out
format from the 1980s, and also x32 ABI. With binfmt_misc I can add even more ABIs. See x86 psABI 用于几个 ABI 文档的列表。
顺便说一句,目前的趋势是尝试编写 portable code. Perhaps using frameworks like Qt or POCO or Glib(和许多其他)可以隐藏应用程序的 ABI 详细信息。
在某些情况下,libffi 也可能有帮助。
一般来说,一旦您了解了您的 OS 和您的架构,您几乎可以 - 大多数时候 - 推断出 ABI。
如果你真的想要你的 ABI, 那么一个可能的 Linux 具体方法可能是 运行 file(1) on the current executable. I don't recommend doing that, but you could try (using proc(5) 来获取可执行文件) :
/// return a heap allocated string describing the ABI of current executable
//// I don't recommend using this
const char*getmyabi(void) {
char mycmdname[80];
int sz = snprintf(mycmdname, sizeof(mycmdname),
"/usr/bin/file -L /proc/%d/exe",
getpid());
assert (sz < (int) sizeof(mycmdname));
FILE*f = popen(mycmdname, "r");
if (!f) {
perror(mycmdname); exit(EXIT_FAILURE);
};
char* restr = NULL;
size_t siz = 0;
getline(&restr, &siz, f);
if (pclose(f)) { perror("pclose"); exit(EXIT_FAILURE); };
return restr;
} // end of getmyabi
/// the code above in untested
您可以获得如下字符串:
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,"
" interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32,"
"BuildID[sha1]=deca50aa4d3df4d57bacc464aa1e8790449ebf8e, stripped"
然后你需要解析它。您可能还想解析 ldd(1) or of objdump(1) on your executable, your ELF interpreter ld-linux(8) 等的输出……(或为此使用一些 ELF 解析库)。
我不知道 getmyabi
功能有多大用处。我不知道 file
给出的精确输出是什么(在各种 ABI 的所有奇怪情况下)。我让你去测试它(一定要用你系统上安装的所有 ABI 编译你的测试程序,所以 gcc -m32
、gcc -m64
、gcc -mx32
,等等......);如果可能,请在某些非 x86 Linux 系统上进行测试。
如果您只需要在构建时获取 ABI,请考虑编译一些 hello-world 可执行文件,然后 运行 file
(和 ldd
)。有适当的构建规则(Makefile
规则)执行此操作并解析那些 file
和 ldd
命令的输出。
(我对你的问题感到惊讶;什么样的应用程序需要知道 ABI;大多数需要 ABI 的软件都是编译器……;对精确 ABI 的强烈依赖可能是undefined behavior.)
也许给出的提示 here 可能适用于您的情况(只是盲目猜测)。
如果您正在编写一些编译器,请考虑 generating some C code in it then use some existing C compiler on that generated C code, or use a good JIT compilation library like LIBGCCJIT or LLVM。他们会处理 ABI 的特定方面(更重要的是低级优化和代码生成)。
如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己限制在一个或几个 ABI 和平台上。 人生苦短
PS。我完全不确定 ABI 是否有确切的含义。它更像是一个规范文档,而不是某些系统(或某些可执行文件)的定义功能。 IIUC,ABI 规范确实有所发展(可能 完全 与 15 年前不一样)。
有没有办法在编译时检测 C/C++ 中的 ABI?我知道有 OS 和 CPU 架构的宏。 ABI 是否有类似的宏(或其他方式)?
ABI 的概念不为 C11 或 C++14 等标准规范所知。这是一个实现的事情。
您可以在 Linux 上使用 feature_test_macros(7)。
您可以考虑改进您的构建过程(例如,您的 Makefile
, etc...). You might run some shell script detecting features (like autoconf generated configure
scripts do). Notice that some C or C++ code (e.g. header files, etc...) might be generated at build time (for examples: by bison, moc, rpcgen, swig, ...), perhaps by your own utilities or scripts. Use a good enough build automation tool (with care, GNU make and ninja 能够处理生成的 C++ 或 C 代码并管理它们的生成和依赖项)。
不要将编译与 build; the compilation commands running a compiler 混淆,它们只是构建过程的 部分 。
一些平台接受几个 ABI。例如。我的 Linux/Debian/Sid/x86-64 带有 Linux 4.13 内核的桌面可以 运行 x86 32 位 ELF executable, x86-64 64 bits ELF, probably some old a.out
format from the 1980s, and also x32 ABI. With binfmt_misc I can add even more ABIs. See x86 psABI 用于几个 ABI 文档的列表。
顺便说一句,目前的趋势是尝试编写 portable code. Perhaps using frameworks like Qt or POCO or Glib(和许多其他)可以隐藏应用程序的 ABI 详细信息。
在某些情况下,libffi 也可能有帮助。
一般来说,一旦您了解了您的 OS 和您的架构,您几乎可以 - 大多数时候 - 推断出 ABI。
如果你真的想要你的 ABI, 那么一个可能的 Linux 具体方法可能是 运行 file(1) on the current executable. I don't recommend doing that, but you could try (using proc(5) 来获取可执行文件) :
/// return a heap allocated string describing the ABI of current executable
//// I don't recommend using this
const char*getmyabi(void) {
char mycmdname[80];
int sz = snprintf(mycmdname, sizeof(mycmdname),
"/usr/bin/file -L /proc/%d/exe",
getpid());
assert (sz < (int) sizeof(mycmdname));
FILE*f = popen(mycmdname, "r");
if (!f) {
perror(mycmdname); exit(EXIT_FAILURE);
};
char* restr = NULL;
size_t siz = 0;
getline(&restr, &siz, f);
if (pclose(f)) { perror("pclose"); exit(EXIT_FAILURE); };
return restr;
} // end of getmyabi
/// the code above in untested
您可以获得如下字符串:
"ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked,"
" interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32,"
"BuildID[sha1]=deca50aa4d3df4d57bacc464aa1e8790449ebf8e, stripped"
然后你需要解析它。您可能还想解析 ldd(1) or of objdump(1) on your executable, your ELF interpreter ld-linux(8) 等的输出……(或为此使用一些 ELF 解析库)。
我不知道 getmyabi
功能有多大用处。我不知道 file
给出的精确输出是什么(在各种 ABI 的所有奇怪情况下)。我让你去测试它(一定要用你系统上安装的所有 ABI 编译你的测试程序,所以 gcc -m32
、gcc -m64
、gcc -mx32
,等等......);如果可能,请在某些非 x86 Linux 系统上进行测试。
如果您只需要在构建时获取 ABI,请考虑编译一些 hello-world 可执行文件,然后 运行 file
(和 ldd
)。有适当的构建规则(Makefile
规则)执行此操作并解析那些 file
和 ldd
命令的输出。
(我对你的问题感到惊讶;什么样的应用程序需要知道 ABI;大多数需要 ABI 的软件都是编译器……;对精确 ABI 的强烈依赖可能是undefined behavior.)
也许给出的提示 here 可能适用于您的情况(只是盲目猜测)。
如果您正在编写一些编译器,请考虑 generating some C code in it then use some existing C compiler on that generated C code, or use a good JIT compilation library like LIBGCCJIT or LLVM。他们会处理 ABI 的特定方面(更重要的是低级优化和代码生成)。
如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己限制在一个或几个 ABI 和平台上。 人生苦短
PS。我完全不确定 ABI 是否有确切的含义。它更像是一个规范文档,而不是某些系统(或某些可执行文件)的定义功能。 IIUC,ABI 规范确实有所发展(可能 完全 与 15 年前不一样)。