使用不同的Makefile编译和链接子文件夹

时间:2019-01-02 15:18:11

标签: c makefile compilation

我在C中有一个客户端/服务器应用程序。服务器具有自己的文件夹dserver,与客户端dclient相同。使用这两个文件中的一些包含实用程序功能的文件,我在先前目录的同一级别上创建了另一个目录,名为common

我的想法是在每个子文件夹中创建一个Makefile(一个在dserver中,一个在dclient中,另一个在common中),然后创建一个Makefile在主目录中,该目录将运行另一个Makefiles,如下所示:

all:
    +$(MAKE) -C common
    +$(MAKE) -C dserver
    +$(MAKE) -C dclient

第一个问题是common/Makefile不应创建可执行文件,而只能创建为客户端和服务器创建可执行文件所需的目标文件。以我为例:

CXX = gcc

SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=$(SOURCEDIR)/obj

OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))

# ADD MORE WARNINGS!
WARNING := -Wall -Wextra

$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
    $(CXX) $(WARNING) -MMD -MP -c $< -o $@

$(OBJDIR):
    mkdir -p $(OBJDIR)

我的问题是它正在创建OBJDIR指定的对象目录,而不是对象文件*.o指定的:

第二,在客户端和服务器Makefile中,我都应在common中包括文件的路径,然后在编译common的结果中引用目标文件以构建目标文件。可执行文件。因此,以dserver/Makefile为例,我添加了行INC_PATH = -I../common/,并在编译中将其引用为$(CXX) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@。但是,在代码中,我不得不做#include "../common/utilities.h"

是否可以在Makefile中包含路径,以便在代码中仅允许执行#include "utilities.h"

而且,假设common有自己的对象目录,其中包含客户机和服务器都需要的目标文件,如何构建,例如服务器可执行文件同时引用common中的目标文件目录以及server目录中包含的特定目录?

dserver/Makefile类似(dclient/Makefile具有相同的结构):

CXX = gcc

INC_PATH = -I../common/

SOURCEDIR := ./
SOURCES := $(wildcard $(SOURCEDIR)/*.c)
OBJDIR=./obj

OBJECTS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.o, $(SOURCES))
DEPENDS := $(patsubst $(SOURCEDIR)/%.c,$(OBJDIR)/%.d, $(SOURCES))

# ADD MORE WARNINGS!
WARNING := -Wall -Wextra

# .PHONY means these rules get executed even if
# files of those names exist.
.PHONY: all clean

# The first rule is the default, ie. "make",
# "make all" and "make parking" mean the same
all: server

clean:
    $(RM) $(OBJECTS) $(DEPENDS) server

# Linking the executable from the object files
# $^   # "src.c src.h" (all prerequisites)
../server: $(OBJECTS)
    $(CXX) $(WARNING) $(INC_PATH) $^ -o $@
    #$(CXX) $(WARNING) $(CXXFLAGS) $(INC_PATH) $^ -o $@ $(LIBS)

-include $(DEPENDS)

$(OBJDIR):
    mkdir -p $(OBJDIR)

$(OBJDIR)/%.o: $(SOURCEDIR)/%.c Makefile | $(OBJDIR)
    $(CXX) $(WARNING) -MMD -MP -c $(INC_PATH) $< -o $@

1 个答案:

答案 0 :(得分:0)

您没有在“通用” Makefile中指定用于构建对象的任何规则-这是您唯一的规则。

$(OBJDIR):
    mkdir -p $(OBJDIR)

您想在此之前放置一条规则,以使所有规则都可以构建对象,也许类似于:

all: $(OBJDIR) $(OBJECTS)

它必须走在原始规则之前,就像您没有指定要构建的内容一样,make会执行发现的第一个规则。

通过使用-I../common/,在其他目录中包含来自“ common”的头文件应该可以正常工作。

使用“ common”中的对象只是将它们添加到对象列表中的一种情况,即:

COMMON_OBJECTS=../common/obj/utilities.o

../server: $(OBJECTS) $(COMMON_OBJECTS)

或者将它们内置到库中,这样您就不必知道对象文件了。

另外,值得注意的是$(CXX)是用于存储C ++编译器的变量-用于与要使用$(CC)$(CFLAGS)的C编译器一起构建。