我的程序包括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!
经过查找,我尝试了多种方法均无果。请帮我解决这个问题
最佳答案
正如 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 预定义了一些规则,这些规则通常只是做正确的事™;我们可以让他们完成我们的大部分工作。事实上,您可以用来构建程序的最短 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)
使用模式替换从 .c
文件列表生成 .o
文件列表,并从 生成
。我们将使用 .d
.o.d
文件进行依赖项跟踪。
依赖跟踪
这可能是最复杂的部分,但还不错。
最小 Makefile 的一个实际问题是它不知道 #include
。如果 sumprime.c
包含 semaphore.h
并且 semaphore.h
被更改,我们真的很喜欢 sumprime.c
重建。幸运的是,gcc 有一种机制可以促进我们调用
CPPFLAGS = -MD
当给定此选项时,预处理器会生成一个 .d
文件,对应于给定的输入 .c
(即,如果 sumprime.c
被编译,sumprime.d
被生成),其中包含源文件依赖项的 make-compatible 列表。例如,我希望 sumprime.d
看起来像
sumprime.c: semaphore.h sharedmemory.h
然后,用
-include $(DEPFILES)
make 被指示将这些文件包含到它的代码中(如果它们存在)。这意味着 make 总是知道源文件的依赖关系,就像它们在上次构建(!)期间一样。它落后一个不是问题,因为依赖项的更改需要更改目标上次依赖的文件之一,并且第一次没有依赖项被拉出不是问题,因为第一次一切无论如何都必须 build 。
因此我们可以毫不费力地进行依赖项跟踪。
用 GNU tar 打包
pack: dist
dist: $(HANDIN)
$(HANDIN): $(DISTFILES)
@echo [DIST] Preparing for distaging...
@rm -f $@
@tar cjf $@ --transform 's,^,$(DISTFOLDER)/,' $+
@echo [DIST] Done!
rule 需要 GNU tar,但如果它可用,它的 --transform
选项会生成一个更好的 dist
规则,如您所见。我冒昧地将其更改为那个。当然,如果你愿意,你仍然可以使用你原来的方式。
旁注:更常见的做法是将您所说的pack
规则称为dist
。这没有技术上的原因,这只是一个约定;人们期望 make dist
。使用此代码,两个名称都有效。
关于linux - 我怎样才能用这个制作文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29714720/