我正在尝试将两个c文件calutil.c
和calutil.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.c
有main.
我收到了错误
ld: can't link with a main executable file
时, make
。造成这种情况的原因是什么?
答案 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
查看编译器正在执行的操作。$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -o $@ $<
,因此您无需编写自己的规则。$(CC) $(LDFLAGS) $(TARGET_ARCH) $^ $(LOADLIBES) $(LDLIBS) -o $@
.PHONY
或all
时)时,应声明非文件本身的目标clean
以防止混淆。*.out
匹配的文件,所以我删除了clean
规则的那一部分。CPPFLAGS
而不是CFLAGS
。预处理程序标志通常都是那些-D
和-I
标志,并且还会传递给在同一项目中使用C预处理程序的其他工具,例如splint
或PC-Lint
。< / LI>
当Makefile
运行时,它正在查看如何制作all
,并且发现对于all
,它必须生成caltool
。对于caltool
,它发现必须首先制作calutil.o
和caltool.o
。当它尝试制作calutil.o
和caltool.o
时,它会发现它可以从calutil.c
和caltool.c
制作,并且会这样做。然后,它会将caltool.o
和calutil.o
关联到caltool
。
根据您的命名,我猜测它包含caltool.c
函数main()
。一旦使用静态链接库,首先放置包含main()
的对象会很有帮助。
编辑:这里有一些神奇的东西给你。我假设您有一个标头文件calutil.h
,caltool.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
,基于它构建的工具,经典环境变量,以及其他所有变量的小写变量。