linux - 我怎样才能用这个制作文件

标签 linux compilation makefile semaphore

我的程序包括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/

相关文章:

python - 我如何从 python 程序而不是代理中找到面向公众的 ip

linux - Makefile:649: *** 缺少分隔符。停止

mono - 在树莓派上编译 Mono 3.x

linux - 更改多个文件的名称 Linux

c++ - 如何检查显示器是否已插入? (Linux)

c - 在 Linux 上以非阻塞模式读取文件

gcc - 无法建立glibc

windows - 使用 VC++ Express 2010 编译 libdwarf 无法运行 Demo 应用程序

gcc - 在 Automake 中没有链接的情况下如何编译?

c - 独立于源文件名的通用 makefile