我的计划包含sharedmemory.c
sharedmemory.h
semaphore.c
semaphore.h
sumprime.c
,现在我想在Linux中编译一个名为sumprime
的可执行文件
sumprime.c
代码调用sharedmemory.h
semaphore.h
中声明并在sharedmemory.c
semaphore.c
我的makefile
是这样的:
HEADERFILES = semaphore.h sharedmemory.h
SOURCEFILES = sumprime.c semaphore.c sharedmemory.c
OBJFILES = sumprime.o semaphore.o sharedmemory.o
DISTFILES = $(HEADERFILES) $(SOURCEFILES) Makefile
DISTFOLDER = lab5
HANDIN = ${DISTFOLDER}.tar.bz2
DEST=sumprime
CCFLAG=
.PHONY: all clean pack
all: $(DEST)
$(DEST): sumprime.o
gcc sumprime.o -o $(DEST)
sumprime.o: $(HEADERFILES) $(SOURCEFILES)
gcc -c $(HEADERFILES) $(SOURCEFILES) -o sumprime.o
clean:
pack:
@echo [PACK] Preparing for packaging...
@rm -fr ${DISTFOLDER} ${HANDIN}
@mkdir ${DISTFOLDER}
@echo [PACK] Copying solution files
@for file in ${DISTFILES}; do\
cp -f $$file ${DISTFOLDER};\
echo \>\>\> $$file;\
done;
@echo [PACK] Creating ${HANDIN}...
@tar cjf ${HANDIN} ${DISTFOLDER}
@rm -fr ${DISTFOLDER}
@echo [PACK] Done!
搜索后我尝试了多种方法。请帮帮我这个
答案 0 :(得分:1)
正如gcc
告诉您的那样,您不能将-c
与多个输入文件一起使用,所以
gcc -c $(HEADERFILES) $(SOURCEFILES) -o sumprime.o
不起作用。
幸运的是,这也是不必要的;事实上,您不需要.o
文件的特殊规则,因为built-in rules工作得很好。特别是这种情况,因为输出二进制文件的名称对应于一个目标文件(sumprime.o
;请参阅"链接单个目标文件"链接后面。)
我会使用像
这样的东西#!/usr/bin/make -f
CC = gcc
CPPFLAGS = -MD
CFLAGS = -O2 -g
LDFLAGS =
LDLIBS =
TARGET = sumprime
HEADERFILES = semaphore.h sharedmemory.h
SOURCEFILES = sumprime.c semaphore.c sharedmemory.c
DISTFOLDER = lab5
DISTFILES = $(HEADERFILES) $(SOURCEFILES) Makefile
HANDIN = $(DISTFOLDER).tar.bz2
OBJFILES = $(SOURCEFILES:.c=.o)
DEPFILES = $(OBJFILES:.o=.d)
all: $(TARGET)
$(TARGET): $(OBJFILES)
clean:
rm -f $(TARGET) $(OBJFILES)
distclean: clean
rm -f $(DEPFILES) $(HANDIN)
pack: dist
dist: $(HANDIN)
$(HANDIN): $(DISTFILES)
@echo [DIST] Preparing for packaging...
@rm -f $@
@tar cjf $@ --transform 's,^,$(DISTFOLDER)/,' $+
@echo [DIST] Done!
.PHONY: all clean distclean dist pack
-include $(DEPFILES)
显然,这需要一些解释。
我在上面提到了这些:make预先定义了许多通常只做Do Thing™的规则;我们可以让他们完成我们的大部分工作。实际上,您可以用来构建程序的最短Makefile是
sumprime: sumprime.o semaphore.o sharedmemory.o
这使用隐式规则来构建.o
文件以及构建sumprime
的隐式配方。请注意,有些变量会影响隐式规则的行为;上面链接的后面是包含其配方的此类规则的列表,以及它们使用的变量的名称。由于我们正在编译C代码,我们感兴趣的是:
CPPFLAGS = -MD # C preprocessor flags, such as -Ipath -DMACRO=definition
CFLAGS = -O2 -g # C compiler flags
LDFLAGS = # linker flags, such as -Lpath
LDLIBS = # linked libraries, such as -lpthread (Alternatively:
# LOADLIBES, but this is less usual)
行
OBJFILES = $(SOURCEFILES:.c=.o)
DEPFILES = $(OBJFILES:.o=.d)
使用模式替换从.o
文件列表中生成.c
文件列表,并从.d
生成.o
。我们将.d
个文件用于依赖关系跟踪。
这可能是最复杂的部分,但 。
最小Makefile的一个实际问题是它不了解#include
s。如果sumprime.c
包含semaphore.h
并且semaphore.h
已更改,我们真的希望重建sumprime.c
。幸运的是,gcc有一个机制来促进我们用
CPPFLAGS = -MD
当给出此选项时,预处理器会生成与其给出的输入.d
对应的.c
文件(即,如果编译sumprime.c
,则生成sumprime.d
)包含与源文件的依赖关系的make兼容列表。例如,我希望sumprime.d
看起来像
sumprime.c: semaphore.h sharedmemory.h
然后,用
-include $(DEPFILES)
make被指示将这些文件包含在其代码中(如果存在)。这意味着make始终知道源文件的依赖关系,就像它们在上一次构建期间一样(!)。它落后于后面不是问题,因为依赖项的更改需要更改目标依赖于上次的一个文件,并且第一次没有依赖项被拉动不是问题因为第一次一切无论如何必须建造。
因此我们可以轻松获得依赖性跟踪。
在
pack: dist
dist: $(HANDIN)
$(HANDIN): $(DISTFILES)
@echo [DIST] Preparing for distaging...
@rm -f $@
@tar cjf $@ --transform 's,^,$(DISTFOLDER)/,' $+
@echo [DIST] Done!
规则需要GNU tar,但是如果它可用,它的--transform
选项会产生更好的dist
规则,如您所见。我冒昧地改变它。当然,如果您愿意,您仍然可以使用旧方式。
旁注:通常会调用您所谓的pack
规则dist
。这没有技术上的原因,它只是一个惯例;人们期待make dist
。使用此代码,两个名称都有效。