我的项目中有以下目录结构:
bin/
dist/
include/
??? module_a/
??? module_b/
Makefile
src/
??? module_a/
??? module_b/
Run Code Online (Sandbox Code Playgroud)
文件夹include/中包含*.hpp的,同时*.cpp的是src/.我想编译所有的源bin/,然后将它们连接起来dist/.对我来说似乎是一个非常合理的愿望.
我想知道这个案例的Makefile的最佳实践.我所能找到的只是%.o: %.cpp目标,但由于源文件和二进制文件夹不同,这并不能真正起作用.
我试图使用这样的东西:
D_SRC = src
D_BIN=bin
F_CPP := $(shell find $(D_SRC) -iname '*.cpp' -type f)
F_OBJ := $(shell echo $(F_CPP) | sed s:\ :\\n:g | sed s:$(D_SRC):$(D_BIN): | sed 's:^\(.*\)\.cpp$$:\1\.o:')
$(F_OBJ): $(F_SRC)
$(foreach file, $(F_SRC), \
$(GXX) $(CXXFLAGS) -c $(file)\
)
Run Code Online (Sandbox Code Playgroud)
此目标不起作用,因为$(F_OBJ)路径以#开头bin/,同时foreach将源编译为当前工作目录.我可以让它编译成bin/,但只有更多的sed表达式才会发生这种情况,并且它很难实现.
这对我来说可能很难,因为我不太了解make这一点,但我不能成为这个项目设置的唯一一个.在我看来,它必须是一个非常普遍的.我知道我可以Makefile单独为每个模块写一个,但这真的是最好的选择吗?
编辑:我现在想知道我将用几个Makefile实现什么.如果一个人在根,另一个人在src/module_a,如何知道bin/?如果你执行它make -f src/module_a/Makefile,它将与从根目录执行它相同,因为它的工作目录将是root.我想,另一种方法是在执行之前更改目录,如下所示:make -C include/module_a但在这种情况下,它会如何找到bin/?我不想D_BIN = ../../bin在Makefile中有类似的东西.
我通常做的是在src目录中有一个Makefile(如果你愿意,可以从顶级Makefile中调用),然后使用如下规则:
D_BIN = ../bin
$(D_BIN)/%.o: %.cpp
Run Code Online (Sandbox Code Playgroud)
您还可以在顶级目录中尝试使用makefile,并使用如下所示的规则:
D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp
Run Code Online (Sandbox Code Playgroud)
但是我没有使用过这样的规则,所以我不知道利弊与我通常做的方式.我通常这样做的方式工作正常,我甚至有建立的规则依赖于这样:
$(D_BIN)/%.d: %.cpp
Run Code Online (Sandbox Code Playgroud)
和链接规则将是:
../dist/outexe: $(F_OBJ)
Run Code Online (Sandbox Code Playgroud)
使用foreach通常是不受欢迎的,因为它没有使用普通makefile规则中内置的所有功能(即没有依赖于每个文件的检查,无论是构建一切还是什么都没有),因此foreach应该只是作为最后的手段,但在这种情况下,你将能够让它在没有foreach的情况下工作.
除此之外,还有更简单的方法来构建文件列表,您不需要使用shell或sed.
F_CPP = $(wildcard *.cpp)
F_OBJ = $(F_CPP:.cpp=.o)
Run Code Online (Sandbox Code Playgroud)
更新:这是我通常发出递归make的方式:
SUBDIRS = src
.PHONY: $(SUBDIRS)
all: $(SUBDIRS)
$(SUBDIRS):
@echo "Building $@..."
$(MAKE) -C $@ $(MFLAGS)
Run Code Online (Sandbox Code Playgroud)
然后确实在你的子制作中,你需要使用../bin.
但是,对于像您这样简单的项目,您可能最好只在根级别使用一个makefile并使用如下规则:
D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp
Run Code Online (Sandbox Code Playgroud)
如果你有一个非常复杂的目录结构,那么递归makefile是可以的(好但不是很好),随着时间的推移你将添加/删除/修改新的目录树.但是对于一个简单的项目,你只想拥有代码和objs的单独目录,这可能有点过分了.