【问题标题】:How can I makefile with this我怎样才能用这个生成文件
【发布时间】:2015-04-18 08:15:08
【问题描述】:

我的程序包含sharedmemory.csharedmemory.hsemaphore.csemaphore.hsumprime.c,现在我想在Linux中编译一个名为sumprime的可执行文件

sumprime.c代码调用了一些在sharedmemory.hsemaphore.h中声明并在sharedmemory.csemaphore.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!

我在搜索后尝试了多种方法都徒劳无功。请帮我解决这个问题

【问题讨论】:

    标签: linux compilation makefile semaphore


    【解决方案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 The Right 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)
    

    使用模式替换从.c 文件列表生成.o 文件列表,并从.o 生成.d。我们将使用.d 文件进行依赖跟踪。

    依赖跟踪

    这可能是最复杂的部分,但也没有那么糟糕。

    最小 Makefile 的一个实际问题是它不知道#includes。如果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 总是知道源文件的依赖关系,就像它们在上次构建期间一样(!)。它落后一个不是问题,因为依赖项的更改需要更改目标上次依赖的文件之一,并且第一次没有提取任何依赖项不是问题,因为第一次一切无论如何都必须建造。

    因此,我们可以轻松地进行依赖跟踪。

    使用 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。使用此代码,两个名称都可以使用。

    【讨论】:

    • 谢谢,但是使用你的makefile构造后,其实完全复制了,还是遇到同样的问题:In function 'main' /home/kuro/Desktop/Lab5/sumprime.c:60: undefined reference to 'v' /home/kuro/Desktop/Lab5/sumprime.c:52: undefined reference to 'p' /home/kuro/Desktop/Lab5/sumprime.c:55: undefined reference to 'v' collect2: error: ld returned 1 exit status make: *** [sumprime] Error 1
    • vp 定义在哪里?也许您忘记了列表中的源文件。
    • 它们在semaphore.h中定义并在semaphore.c中实现
    • 我怀疑你的问题不完全是 Makefile 问题,这个错误的原因在于 C 代码。你能用pv的声明和定义更新问题吗(不包括函数体,如果它们是函数和长的)?
    猜你喜欢
    • 1970-01-01
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多