第三方为我提供了一个静态库(.a)以与solaris站连接。 我尝试使用sunpro编译,但在链接步骤失败。
我认为问题来自我使用的编译器(gcc代替?)或仅仅是它的版本(因为编译器提供的std lib可能会从库AFAIK预期的版本改变,它可能导致链接步骤出错)。
我怎么知道用哪个编译器来生成这个lib?有没有一些工具呢? sunpro / gcc或其他什么选项?
作为提示: 我前段时间读过编译器在生成目标文件时使用不同的修改约定(是吗?)。不过,“nm --demangle”命令行会打印出来自此静态库中调试符号的所有函数名称。它是如何工作的 ?如果我的假设没问题, nm 确实有办法解决静态库中正在使用的约定,不是吗?或者它只是意味着lib是由GNU gcc生成的,因为nm是GNU binutils的一部分?
我不靠近我的工作站,所以我不能复制&从链接器粘贴错误输出(目前不是,但我可以在进一步编辑中复制它们)
答案 0 :(得分:5)
从存档中提取目标文件,然后在其中一些上运行strings
命令(首先是较小的,因为筛选的噪音较少)。许多编译器在目标文件中插入ASCII签名。
例如,以下无意义的源文件foo.c
:
extern void blah();
在我的Fedora 10机器上通过gcc -c -o foo.o foo.c
编译到foo.o时会产生一个647字节foo.o
目标文件。在strings
上运行foo.o
会导致
GCC: (GNU) 4.3.2 20081105 (Red Hat 4.3.2-7) .symtab .strtab .shstrtab .text .data .bss .comment .note.GNU-stack foo.c
这表明编译器是GCC。即使我用-fno-ident
编译它,.GNU-stack note ELF部分仍然存在。
您可以使用ar
实用程序或Midnight Commander(集成了ar)提取目标文件,或者只需在存档上运行strings
(这可能会给您带来更多噪音,并且不太相关,但仍然有帮助。)
答案 1 :(得分:2)
库应该是C还是C ++库?
如果它是一个C库,那么名称重整可能不是问题,因为C中没有。但它可能是错误的格式。 Unices曾经使用a.out格式的库,但几乎所有新版本都转换为更强大的格式,如ELF。
如果它是C ++库,则名称重整可能是一个问题。大多数编译器都会在代码中嵌入一些特定于编译器的符号,所以如果你有一个像nm这样的工具来列出符号,你可以从它的编译器中推断出它。
例如,g ++创建一个符号
__ gxx_personality_v0
在它的库中
答案 2 :(得分:2)
我倾向于使用strings
程序(使用“-a
”选项,或者我自己的变体,其中“-a
”行为是标准的)并查找告诉迹象。例如,在我自己的一个库中,我发现:
/work1/gcc/v4.2.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.2.3/include
/work1/gcc/v4.3.0/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.0/include
/work1/gcc/v4.3.1/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.1/include
/work1/gcc/v4.3.3/bin/../lib/gcc/sparc-sun-solaris2.10/4.3.3/include
这表明库中的代码已经在几年内用各种版本的GCC编译(实际上,我很惊讶在单个库中找到这么多版本)。
另一个图书馆包含:
cg: Sun Compiler Common 11 Patch 120760-06 2006/05/26
acomp: Sun C 5.8 Patch 121015-02 2006/03/29
iropt: Sun Compiler Common 11 Patch 120760-06 2006/05/26
/compilers/v11/SUNWspro/prod/bin/cc -O -v -Xa -xarch=v9 ...
因此,目标文件中通常有指纹指示使用了哪个编译器。但你必须知道如何寻找它们。
答案 3 :(得分:-1)
您可以尝试使用unix实用程序文件:
file foo.a