Makefile:C中的“ld:无法与主可执行文件链接”

时间:2016-02-15 00:37:35

标签: c makefile

我正在尝试将两个c文件calutil.ccalutil.h编译成一个可执行文件。这是我的makefile:

CC = gcc
CFLAGS = -Wall -std=c11 -DNDEBUG

all: caltool

caltool: calutil.o caltool.o
    $(CC) $(CFLAGS) calutil.o caltool.o

caltool.o: caltool.c
    $(CC) $(CFLAGS) caltool.c -o caltool.o

calutil.o: calutil.c
    $(CC) $(CFLAGS) -c calutil.c -o calutil.o
clean:
    rm -rf *.o *.out

calutil.c没有main,而caltool.cmain.我收到了错误

当我ld: can't link with a main executable file时,

make。造成这种情况的原因是什么?

2 个答案:

答案 0 :(得分:1)

我刚刚从目录中删除了.o文件,并编辑了我的makefile以将-c添加到caltool.o行。

答案 1 :(得分:0)

主要问题是你的连锁配方缺少输出文件,而且你的编辑遗失-c

如果您使用的是GNU make,以下Makefile就可以完成您想要的操作:

CFLAGS:=-Wall -std=c11
CPPFLAGS:=-DNDEBUG

.PHONY: all
all: caltool

caltool: caltool.o calutil.o

.PHONY: clean
clean::
        $(RM) *.o

说明:

  • 如果您没有使用特定于目标的变量,则应使用:=代替=来分配变量,以便在分配时进行扩展,而不是在评估时进行扩展。
  • 当您的Makefile增长并将其拆分时,您可能希望拥有多个名为clean的目标,这些目标都将被执行。在这种情况下,请使用clean::代替clean:
  • 有一个预定义的变量可以调用rm,它是$(RM)并且它包含-f标志,以防止Makefile在一个或多个文件中失败首先不存在被删除。
  • clean的模式应该是*.[adios](这很容易记住,adios是西班牙语的再见),以便在构建自己的静态库时删除中间存档(.a ),依赖文件(.d),预处理器输出(.i)和汇编程序文件(.s),以防您使用-save-temps查看编译器正在执行的操作。
  • GNU make有内置的编译和链接规则,请参阅http://git.savannah.gnu.org/cgit/make.git/tree/default.c?id=3.81
    • 编译的内置规则调用$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<,因此您无需编写自己的规则。
    • 链接的内置规则调用$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
  • 当用户创建具有相同名称的文件(例如.PHONYall时)时,应声明非文件本身的目标clean以防止混淆。
  • 我没有看到你的命令如何创建与glob模式*.out匹配的文件,所以我删除了clean规则的那一部分。
  • 预处理器的标志应该进入CPPFLAGS而不是CFLAGS。预处理程序标志通常都是那些-D-I标志,并且还会传递给在同一项目中使用C预处理程序的其他工具,例如splintPC-Lint。< / LI>

Makefile运行时,它正在查看如何制作all,并且发现对于all,它必须生成caltool。对于caltool,它发现必须首先制作calutil.ocaltool.o。当它尝试制作calutil.ocaltool.o时,它会发现它可以从calutil.ccaltool.c制作,并且会这样做。然后,它会将caltool.ocalutil.o关联到caltool

根据您的命名,我猜测它包含caltool.c函数main()。一旦使用静态链接库,首先放置包含main()的对象会很有帮助。

编辑:这里有一些神奇的东西给你。我假设您有一个标头文件calutil.hcaltool.c包含该标头文件以访问calutil.c提供的外部符号。您希望重建依赖于这些头文件的所有对象。在这种情况下,请将以下行添加到Makefile:

CPPFLAGS+=-MMD
-include caltool.d calutil.d

为了不多次拥有对象列表,您可以像这样添加变量objects

objects:=caltool.o calutil.o

然后,您将使用此规则构建应用程序:

caltool: $(objects)

并包含这样的依赖项文件:

-include $(objects:.o=.d)

如果您保持工作树“干净”,即不要用“外来”代码“污染”它,即您总是希望在项目中包含所有.c个文件,您可以更改objects如下:

sources:=$(wildcard *.c)
objects:=$(sources:.c=.o)

如果您想知道为什么它是CPPFLAGS(大写)而objects(小写):对于配置规则配方并控制内置行为的所有变量,通常使用大写make,基于它构建的工具,经典环境变量,以及其他所有变量的小写变量。