首页 > 解决方案 > 使用不同的 Makefile 编译和链接子文件夹

问题描述

我在 C 中有一个客户端/服务器应用程序。服务器有自己的文件夹dserver,客户端也是如此dclient。使用它们两个包含实用程序函数的文件,我在之前的目录的同一级别创建了另一个目录,名为common.

我的想法是在每个子文件夹中创建每个Makefile子文件夹(一个 in dserver,一个 indclient和另一个 in 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 $@

标签: cmakefilecompilation

解决方案


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

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

您想在此之前设置一条规则,以使其构建对象,可能类似于以下内容:

all: $(OBJDIR) $(OBJECTS)

它必须在原始规则之前,就好像您没有指定要构建的内容一样,make 将执行它找到的第一条规则。

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

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

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

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

或者将它们内置到库中,这样您就不需要知道有哪些目标文件。

另外值得注意的$(CXX)是,用于存储 C++ 编译器的变量 - 用于使用您要使用的 C 编译器进行构建,$(CC)并且$(CFLAGS).


推荐阅读