如何为更大的项目正确准备 makefile?

How to properly prepare makefile for bigger project?

我在编译项目并将其与目录组织链接时遇到问题,如下所示。

/project
|
|____/Components        (header files and source codes of all components)
|    |
|    |____/X            (header files and source codes of component)
|         |
|         |____/src     (source codes)
|         |
|         |____/include (header files)
|
|
|____/make              
|    | 
|    |____-Makefile     (Makefile)
|    |____-source.inc   (list of directories with header files)
|    |____-source.list  (list of every source file, .c and .cpp)
|
|____-main.c            (main source file)

当我 运行 在 cmd 中创建时,出现此错误:

make: *** No rule to make target '../build/obj/main.o', needed by '../build/bin/app'.  Stop.

保留这个目录组织对我来说很重要。

这是我的 Makefile

OUTDIR = ../build/
OBJDIR = $(OUTDIR)obj/
BINDIR = $(OUTDIR)bin/

LD = g++

APP = app

INC_DIRS = $(shell cat source.inc)

CFLAGS = -g0
CXXFLAGS = -g0 -Wall
LDFLAGS = -g0

COMPILE.c = $(BUILD_VERBOSE)$(CXX) $(CFLAGS) $(addprefix -I, $(INC_DIRS)) -c $< -o $@
COMPILE.cc = $(BUILD_VERBOSE)$(CXX) $(CXXFLAGS) $(addprefix -I, $(INC_DIRS)) -c $< -o $@

SRCS = $(shell egrep .[ccpp]$$ source.list)
OBJS = $(patsubst %,$(OBJDIR)%.o,$(basename $(notdir $(SRCS))))

$(BINDIR)$(APP): prep_dirs $(OBJS)
    @printf "\nBuilding Project $@\n"
    $(LD) $(LDFLAGS) $(OBJS) -o $@

$(OBJDIR)%.o: %.c
    @printf "\nCompiling: $<\n"
    $(COMPILE.c)
    $(POSTCOMPILE)

$(OBJDIR)%.o: %.cpp
    @printf "\nCompiling: $<\n"
    $(COMPILE.cc)
    $(POSTCOMPILE)

prep_dirs:
    $(BUILD_VERBOSE)mkdir -p $(OUTDIR)
    $(BUILD_VERBOSE)mkdir -p $(OBJDIR)
    $(BUILD_VERBOSE)mkdir -p $(BINDIR)

.PHONY: clean
clean:
    @printf "Cleaning executables...\n"
    $(BUILD_VERBOSE)rm -rf $(BINDIR)*.exe

.PHONY: cleanall
cleanall:
    @printf "Cleaning all objects...\n"
    $(BUILD_VERBOSE)rm -rf $(OUTDIR)

source.inc 和 source.list

source.inc
../Components/X/include

source.list
../Components/X/src/some_source.c
../main.c

你能告诉我我做错了什么吗?我怎样才能修复它并将 main.c 留在同一个地方?

总的来说: 不确定你的问题到底是什么,但这就是我所做的。该项目有一个全局对象目录 (OBJDIR)。每个源目录都有自己的 Makefile,如下所示:

# list of sources in *this* directory
CCSRC = a.cc b.cc etc 
OBJS := $(addsuffix .o,  $(CCSRC))
VPATH = $(OBJDIR)
 .SUFFIXES: .cc .o
 .cc.o:
    $(CXX) $(CFLAGS) $< -o $(OBJDIR)/$@

项目顶层有一个Makefile,它只是切换到每个src目录并在该目录中运行make:

include $(PROJ_HOME)/top.mk

# this allows sub-makes to find out if they have been invoked from this
# top-level make, or from a local make (from emacs in a source file directory,
# for example).
CALLED_FROM_TOP = true
export CALLED_FROM_TOP
    
all :
        cd dir1/src;          $(MAKE)
        cd dir2/rtv;          $(MAKE) debug=$(debug) etc

'top.mk' 包括全局定义、导出等。

这是一项艰巨的工作,但为您提供了比我所知道的任何构建系统都更好的 fine-grained 控制。