【问题标题】:(.text+0x20): undefined reference to `main' and undefined reference to function(.text+0x20): 未定义的“main”引用和未定义的函数引用
【发布时间】:2013-12-29 03:46:42
【问题描述】:

我在让我的 makefile 正常工作时遇到问题。我遇到的第一个问题是对 main 的未定义引用。我的 producer.c 文件中有 main 作为函数。第二个问题是对 SearchCustomer() 的未定义引用。

错误:

bash-4.1$ make
gcc -Wall -c producer.c shared.h
gcc -Wall -c consumer.c shared.h
gcc -Wall -c AddRemove.c shared.h
gcc -pthread -Wall -o producer.o consumer.o AddRemove.o
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../lib64/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
AddRemove.o: In function `AddRemove':
AddRemove.c:(.text+0xb1): undefined reference to `SearchCustomer'
AddRemove.c:(.text+0x1e9): undefined reference to `SearchCustomer'
AddRemove.c:(.text+0x351): undefined reference to `SearchCustomer'
collect2: ld returned 1 exit status
make: *** [producer] Error 1

制作文件:

COMPILER = gcc
CCFLAGS = -Wall
all: main

debug:
    make DEBUG=TRUE


main: producer.o consumer.o AddRemove.o
    $(COMPILER) -pthread $(CCFLAGS) -o producer.o consumer.o AddRemove.o
producer.o: producer.c shared.h
    $(COMPILER) $(CCFLAGS) -c producer.c shared.h
consumer.o: consumer.c shared.h
    $(COMPILER) $(CCFLAGS) -c consumer.c shared.h
AddRemove.o: AddRemove.c shared.h
    $(COMPILER) $(CCFLAGS) -c AddRemove.c shared.h


ifeq ($(DEBUG), TRUE)
    CCFLAGS += -g
endif

clean:
    rm -f *.o

【问题讨论】:

  • 代码长。缩小您的问题范围并提供Short, Self Contained, Correct (Compilable), Example
  • 一些建议:在main 配方中,您可以写:$(COMPILER) -o $@ $^ $(LDFLAGS) 并将-pthread 放入LDFLAGS。在其他规则中,您可以编写 once%.o: %.c 和配方:$(COMPILER) $(CCFLAGS) -c -o $@ $<(并且 not.h 提供给编译器!)然后添加依赖项对于特殊目标,例如:producer.o: shared.h other_header.hconsumer.o: shared.h yet_another_header.h 等。
  • 其他几个建议:使用$(MAKE) 而不是仅仅make 来保留调用的make 的命令行标志。您可能还想给--no-print-directory 以防止几行无用的输出。此外,将CFLAGS 用于C(而不是CCFLAGS,这可能会被误认为C++)。
  • 以及更多:添加.PHONY: all clean debug 和其他实际上不是文件的目标,让make 知道它不应该期望从配方中出现实际文件。您还可以使用@$(MAKE) DEBUG=TRUE(添加@)来防止make 回显命令。
  • 最后,您可以从阅读手册中受益:gnu.org/software/make/manual/make.html

标签: c gcc compilation compiler-errors makefile


【解决方案1】:

这条规则

main: producer.o consumer.o AddRemove.o
   $(COMPILER) -pthread $(CCFLAGS) -o producer.o consumer.o AddRemove.o

错了。它说要创建一个名为 producer.o 的文件(使用 -o producer.o),但您想创建一个名为 main 的文件。请原谅大喊大叫,但始终使用 $@ 来引用目标

main: producer.o consumer.o AddRemove.o
   $(COMPILER) -pthread $(CCFLAGS) -o $@ producer.o consumer.o AddRemove.o

正如 Shahbaz 正确指出的那样,gmake 专业人士还将使用 $^,它扩展到规则中的所有先决条件。一般来说,如果您发现自己重复了一个字符串或名称,那么您做错了,应该使用一个变量,无论是内置的还是您创建的。

main: producer.o consumer.o AddRemove.o
   $(COMPILER) -pthread $(CCFLAGS) -o $@ $^

【讨论】:

  • 也可以使用$^来引用它的所有依赖。
【解决方案2】:

此错误意味着,在链接时,编译器无法在任何地方找到main() 函数的定义。

在您的 makefile 中,main 规则将扩展为类似这样的内容。

main: producer.o consumer.o AddRemove.o
   gcc -pthread -Wall -o producer.o consumer.o AddRemove.o

根据gccmanual page-o开关的使用如下

-o file    将输出放在文件 file 中。无论生成何种输出,无论它是可执行文件,这都适用 文件、目标文件、汇编程序文件或预处理的 C 代码。如果-o 不指定,默认是在a.out中放一个可执行文件。

这意味着,gcc 会将输出放在紧邻-o 开关的文件名中。因此,这里不是将所有.o 文件链接在一起并创建二进制文件[main,在你的情况下],而是将二进制文件创建为producer.o,链接其他.o 文件。请改正。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-29
    • 2020-03-25
    • 2014-06-07
    • 1970-01-01
    • 2021-08-28
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多