Makefile的好习惯

时间:2012-12-03 17:34:41

标签: makefile

我的项目中有以下目录结构:

bin/
dist/
include/
├── module_a/
└── module_b/
Makefile
src/
├── module_a/
└── module_b/

文件夹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)\                                              
    )

此目标不起作用,因为$(F_OBJ)路径以bin/开头,而foreach将源编译为当前工作目录。我可以将其编译为bin/,但只有少数几个sed表达式才会发生这种情况,而且它很难实现。

这对我来说可能很难,因为我不知道make那么好,但我不能成为唯一一个有这个项目设置的人。在我看来,它必须是一个非常普遍的。我知道我可以分别为每个模块写一个Makefile,但这真的是最好的选择吗?

编辑:我现在想知道几个Makefile会实现什么。如果一个人在src/module_a处于根,另一个在bin/,那么后者如何知道make -f src/module_a/Makefile?如果你用make -C include/module_a执行它,它将与从根目录执行它一样,因为它的工作目录是root。我想另一种方法是在执行之前更改目录,如下所示:bin/,但在这种情况下,它会如何找到D_BIN = ../../bin?我不希望在Makefile中有类似{{1}}的内容。

1 个答案:

答案 0 :(得分:6)

我通常做的是在src目录中有一个Makefile(如果你愿意,可以从顶级Makefile中调用),然后使用这样的规则:

D_BIN = ../bin
$(D_BIN)/%.o: %.cpp

您还可以在顶级目录中尝试使用makefile,并使用如下所示的规则:

D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp

但我没有使用过这样的规则,所以我不知道利弊与我通常做的方式。我通常这样做的方式工作正常,我甚至有建立的规则依赖于这样:

$(D_BIN)/%.d: %.cpp 

,链接规则如下:

../dist/outexe: $(F_OBJ)

使用foreach通常是不受欢迎的,因为它没有使用普通makefile规则中内置的所有功能(即,没有依赖于每个文件的检查,无论是构建一切还是什么都没有),以及这样的foreach应该只作为最后的手段使用,但在这种情况下,你可以在没有foreach的情况下让它工作。

除此之外,还有更简单的方法来构建文件列表,您不需要使用shell或sed。

F_CPP = $(wildcard *.cpp)
F_OBJ = $(F_CPP:.cpp=.o)

更新:这就是我通常发出递归制作的方式:

SUBDIRS = src
.PHONY: $(SUBDIRS)
all: $(SUBDIRS)

$(SUBDIRS):
    @echo "Building $@..."
    $(MAKE) -C $@ $(MFLAGS)

然后确实在你的子制作中,你需要使用../bin作为例子。

然而,对于像您这样简单的项目,您可能最好只在根级别使用一个makefile并使用如下规则:

D_BIN = bin
D_SRC = src
$(D_BIN)/%.o: $(D_SRC)/%.cpp
如果你有一个非常复杂的目录结构,那么递归makefile是可以的(好但不是很好),随着时间的推移你将添加/删除/修改新的目录树。但对于一个简单的项目,你只想拥有代码和objs的单独目录,这可能有点过头了。