如何在编译时检测ABI?

fre*_*ish -3 c c++ abi

有没有办法在编译时检测C/C++中的ABI?我知道有OS和CPU架构的宏.ABI是否有类似的宏(或其他方式)?

Bas*_*tch 9

ABI的概念不为C11或C++ 14等标准规范所知.这是一个实现的事情.

您可以在Linux上使用feature_test_macros(7).

你可以考虑改进你的构建过程(例如你的Makefile等等......).您可能会运行一些shell脚本检测功能(如autoconf生成的configure脚本).请注意,某些C或C++代码(例如头文件等)可能在构建时生成(例如:by bison,moc,rpcgen,swig,...),可能由您自己的实用程序或脚本生成.使用足够好的构建自动化工具(小心,GNU makeninja能够处理生成的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.

顺便说一句,目前的趋势是尝试编写可移植代码.也许使用像QtPOCOGlib(以及许多其他)这样的框架可以将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规则),并解析这些fileldd命令的输出.

(我对你的问题感到惊讶;什么样的应用需要知道ABI;大多数需要编译器的软件......;对精确ABI的强烈依赖可能是未定义行为的症状.)

也许这里给出的提示可能适用于你的情况(只是一个盲目的猜测).

如果您正在编写一些编译器,请考虑在其中生成一些C代码,然后在生成的C代码上使用一些现有的C编译器,或使用一个好的JIT编译库,如LIBGCCJITLLVM.他们将负责ABI特定方面(更重要的是低级优化和代码生成).

如果您单独编写编译器并且不想使用外部工具,那么实际上您应该将自己局限于一个或几个ABI和平台.生命短暂.

PS.我完全不确定ABI是否具有确切含义.它更像是一个规范文档,而不是某个系统(或某些可执行文件)的定义特征.IIUC,ABI规范确实在发展(15年前可能并不完全相同).