ABI的概念不为C11或C++ 14等标准规范所知.这是一个实现的事情.
您可以在Linux上使用feature_test_macros(7).
你可以考虑改进你的构建过程(例如你的Makefile
等等......).您可能会运行一些shell脚本检测功能(如autoconf生成的configure
脚本).请注意,某些C或C++代码(例如头文件等)可能在构建时生成(例如:by bison,moc,rpcgen,swig,...),可能由您自己的实用程序或脚本生成.使用足够好的构建自动化工具(小心,GNU make和ninja能够处理生成的C++或C代码并管理它们的生成和依赖).
不要将编译与构建混淆; 运行编译命令编译器都只是部分的构建过程中.
一些平台接受几个 ABI.例如,我的带有Linux 4.13内核的Linux/Debian/Sid/x86-64桌面可以运行x86 32位 ELF可执行文件,x86-64 64位ELF,可能a.out
是20世纪80年代的一些旧格式,还有x32 ABI.使用binfmt_misc,我可以添加更多的ABI.有关几个ABI文档的列表,请参阅x86 psABI.
顺便说一句,目前的趋势是尝试编写可移植代码.也许使用像Qt或POCO或Glib(以及许多其他)这样的框架可以将ABI细节隐藏到您的应用程序中.
在某些情况下,libffi也可能有所帮助.
一般而言,一旦了解了您的操作系统和架构,您几乎可以在大部分时间内推断出ABI.
如果您真的想要ABI,那么可能的Linux特定方式可能是在当前可执行文件上运行file(1).我不建议这样做,但你可以尝试(使用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
Run Code Online (Sandbox Code Playgroud)
你可以得到一个字符串:
"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"
Run Code Online (Sandbox Code Playgroud)
然后你需要解析它.您还可能想要在可执行文件,ELF解释器ld-linux(8)等上解析ldd(1)或objdump(1)的输出(或者使用一些ELF解析库).
我不知道这个getmyabi
功能有多大用处.我不知道精确的输出是什么file
(在各种ABI的所有奇怪的情况下).我离开你进行测试(请确保使用安装在系统上的所有的ABI编译你的测试程序,因此gcc -m32
,gcc -m64
,gcc -mx32
等...); 如果可能的话,测试一些非x86 Linux系统.
如果您只需要在构建时获取ABI,请考虑编译一些hello-world可执行文件,然后在其上运行file
(和ldd
).有适当的构建规则(Makefile
规则),并解析这些file
和ldd
命令的输出.
(我对你的问题感到惊讶;什么样的应用需要知道ABI;大多数需要编译器的软件......;对精确ABI的强烈依赖可能是未定义行为的症状.)
也许这里给出的提示可能适用于你的情况(只是一个盲目的猜测).
如果您正在编写一些编译器,请考虑在其中生成一些C代码,然后在生成的C代码上使用一些现有的C编译器,或使用一个好的JIT编译库,如LIBGCCJIT或LLVM.他们将负责ABI特定方面(更重要的是低级优化和代码生成).
如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己局限于一个或几个ABI和平台.生命短暂.
PS.我完全不确定ABI是否具有确切含义.它更像是一个规范文档,而不是某个系统(或某些可执行文件)的定义特征.IIUC,ABI规范确实在发展(15年前可能并不完全相同).