我有个问题。我在C文件read-line.c中定义了一个函数print,如下所示:
void history_print(void)
{
/* some stuff */
}在一个名为command.cc的C++文件中,我有以下内容:
extern "C" void history_print(void);然后我简单地调用history_print()。
#Use GNU compiler
cc = gcc -g
CC = g++ -g
all: shell
tty-raw-mode.o: tty-raw-mode.c
gcc -c tty-raw-mode.c
read-line.o: read-line.c
gcc -c read-line.c
lex.yy.o: shell.l
lex shell.l
$(cc) -c lex.yy.c
y.tab.o: shell.y
yacc -d shell.y
$(CC) -c y.tab.c
command.o: command.cc
$(CC) -c command.cc
shell: y.tab.o lex.yy.o tty-raw-mode.o read-line.o command.o
$(CC) -o shell lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen当我在Makefile中链接规则输出时,我遇到了一个问题:
Undefined first referenced
symbol in file
history_print command.o
ld: fatal: Symbol referencing errors. No output written to shell
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `shell'make的-v选项标志的输出:
yacc -d shell.y
g++ -g -v -c y.tab.c
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/cc1plus -quiet -v y.tab.c -quiet -dumpbase y.tab.c -mcpu=v7 -auxbase y.tab -g -version -o /var/tmp//ccCi8vXj.s
ignoring nonexistent directory "/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../.. /../../sparc-sun-solaris2.8/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/sparc- sun-solaris2.8
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/backward
/opt/csw/include
/opt/csw/gcc3/include
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/include
/usr/include
End of search list.
GNU C++ version 3.4.6 (sparc-sun-solaris2.8)
compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o y.tab.o /var/tmp//ccCi8vXj.s
/usr/ccs/bin/as: SunOS 5.10 118683-05 Patch 04/30/2010
lex shell.l
gcc -g -c lex.yy.c
gcc -c tty-raw-mode.c
gcc -c read-line.c
g++ -g -v -c command.cc
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/cc1plus -quiet -v command.cc -quiet -dumpbase command.cc -mcpu=v7 -auxbase command -g -version -o /var/tmp//cckVWlC7.s
ignoring nonexistent directory "/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../sparc-sun-solaris2.8/include"
#include "..." search starts here:
#include <...> search starts here:
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/sparc-sun-solaris2.8
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../../../include/c++/3.4.6/backward
/opt/csw/include
/opt/csw/gcc3/include
/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/include
/usr/include
End of search list.
GNU C++ version 3.4.6 (sparc-sun-solaris2.8)
compiled by GNU C version 3.4.6.
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
/usr/ccs/bin/as -V -Qy -s -xarch=v8 -o command.o /var/tmp//cckVWlC7.s
/usr/ccs/bin/as: SunOS 5.10 118683-05 Patch 04/30/2010
g++ -g -v -o shell lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen
Reading specs from /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/specs
Configured with: ../sources/gcc-3.4.6/configure --prefix=/opt/csw/gcc3 --with-local- prefix=/opt/csw --without-gnu-as --with-as=/usr/ccs/bin/as --without-gnu-ld --with-ld=/usr/ccs/bin/ld --enable-threads=posix --enable-shared --enable-multilib --enable-nls --with-included-gettext --with-libiconv-prefix=/opt/csw --with-x --enable- java-awt=xlib --enable-languages=all
Thread model: posix
gcc version 3.4.6
/opt/csw/gcc3/libexec/gcc/sparc-sun-solaris2.8/3.4.6/collect2 -V -R /opt/csw/lib -Y P,/opt/csw/lib:/usr/ccs/lib:/usr/lib -Qy -o shell /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crt1.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crti.o /usr/ccs/lib/values-Xa.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtbegin.o -L/opt /csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6 -L/usr/ccs/bin -L/usr/ccs/lib -L/opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/../../.. lex.yy.o y.tab.o tty-raw-mode.o read-line.o command.o -ll -lgen -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc -lc /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtend.o /opt/csw/gcc3/lib/gcc/sparc-sun-solaris2.8/3.4.6/crtn.o
ld: Software Generation Utilities - Solaris Link Editors: 5.10-1.497
Undefined first referenced
symbol in file
history_print command.o
ld: fatal: Symbol referencing errors. No output written to shell
collect2: ld returned 1 exit status
*** Error code 1
make: Fatal error: Command failed for target `shell'我猜这个问题是由于链接造成的,它与Makefile有关,但我不确定如何修复。有谁能帮帮我吗?
非常感谢,我真的很感谢你的帮助。
加里
发布于 2010-09-16 13:11:41
makefile需要一个链接规则,而不是单独的编译规则:
CC = gcc -g
CPP = g++ -g
program: a.o b.o
${CPP} -o $@ a.o b.oMake已经知道如何将源文件转换为目标文件-您不需要重新训练它。
发布于 2010-09-16 13:08:33
这是因为您正在使用g++重新编译a.c文件,而函数定义周围没有extern C包装器。因此,该名称将经历C++损坏,并且在a.o对象文件中将不会有print。
但是,b.cc会认为print是一个C名称(因为它有extern C),所以它会去寻找未损坏的版本。
要么将extern C放在a.c中的定义周围(这可能使常规C编译器无法使用,所以请记住这一点),或者将您的g++命令更改为使用a.o (由于它是用C编译器完成的,因此具有完整的名称)而不是a.c。
实际上,这是行不通的,因为您没有在g++命令中调用链接器。我甚至不确定您为什么要在b.o中包含a.o。最好的时机可能是在链接时创建一个ab可执行文件,而不是编译时,例如:
CC = g++ -g
a.o: a.c
gcc -o a.o -c a.c
b.o: b.cc
$(CC) -o b.o -c b.cc
ab: a.o b.o
$(CC) -o ab a.o b.o更新:把它分解成最简单的测试用例,这样你就能明白我的意思了:
a.c:
#include <stdio.h>
void print(void) {
printf ("7\n");
}
b.cc:
extern "C" void print(void);
int main(void) {
print();
return 0;
}
Makefile:
output: a.o b.o Makefile
g++ -o output a.o b.o
a.o: a.c Makefile
gcc -o a.o -c a.c
b.o: b.cc Makefile
g++ -o b.o -c b.cc然后运行make和程序:
pax> make
gcc -o a.o -c a.c
g++ -o b.o -c b.cc
g++ -o output a.o b.o
pax> ./output
7如果您将a.c的编译更改为使用g++,则会在无法找到print的位置生成原始错误
pax> make
g++ -o a.o -c a.c
g++ -o b.o -c b.cc
g++ -o output a.o b.o
b.o:b.cc:(.text+0x2b): undefined reference to `_print'
collect2: ld returned 1 exit status
make: *** [output] Error 1现在看来,您最终的Makefile是正确的。它使用C编译器编译a.c,这样就不会发生名称损坏。我的建议是清除所有内容(删除所有*.o文件),然后再次运行make,然后将输出发布到问题的底部。
这可能是一些文件是旧的,这就是为什么您应该在运行make之前删除所有目标文件。
https://stackoverflow.com/questions/3723863
复制相似问题