有没有办法在编译时检测C / C ++中的ABI?我知道有OS和CPU架构的宏。 ABI是否有类似的宏(或其他方式)?
答案 0 :(得分:9)
ABI的概念不为C11或C ++ 14等标准规范所知。这是一个实现的事情。
您可以在Linux上使用feature_test_macros(7)。
您可以考虑改进构建过程(例如您的Makefile
等)。您可能会运行一些shell脚本检测功能(例如autoconf生成的configure
脚本)。请注意,某些C或C ++代码(例如头文件等)可能在构建时生成(例如:bison,moc,{{3 ,},rpcgen,...),也许是您自己的实用程序或脚本。使用足够好的swig工具(谨慎,build automation和GNU make能够处理生成的C ++或C代码并管理其生成和依赖项。)
不要将编译与ninja混淆;运行build的编译命令只是构建过程的部分。
某些平台接受多个 ABI。例如。我的带有Linux 4.13内核的Linux / Debian / Sid / x86-64桌面可以运行x86 32位compiler可执行文件,x86-64 64位ELF,可能是20世纪80年代的一些旧ELF格式,也是a.out
ABI。使用x32我可以添加更多ABI。有关几个ABI文档的列表,请参阅binfmt_misc。
在某些情况下,Glib也可能会有所帮助。
一般而言,一旦了解了自己的操作系统和架构,就可以在大部分时间内推断出ABI。
如果您真的想要您的ABI ,那么可能的Linux特定方式可能是在当前可执行文件上运行libffi。 我不建议这样做,但您可以尝试(使用file(1)获取可执行文件):
/// 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"
然后你需要解析它。您还可能希望在可执行文件,ELF解释器proc(5)等上解析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的强烈依赖可能是{{3}的症状}。)
也许给出ld-linux(8)的提示可能适用于您的情况(只是盲目猜测)。
如果您正在编写某些编译器,请考虑其中的undefined behavior,然后在生成的C代码上使用一些现有的C编译器,或者使用here或{{3}等良好的generating some C code库}}。他们会处理ABI特定方面(更重要的是低级优化和代码生成)。
如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己局限于一个或几个ABI和平台。 生命短暂。
PS。我完全不确定ABI是否具有确切含义。它更像是一个规范文档,而不是某个系统(或某些可执行文件)的定义特征。 IIUC,ABI规范确实发展了(15年前可能并非完全)。