“递归Makefile被认为是有害的”样式makefile问题

时间:2014-02-16 00:56:41

标签: c++ makefile

我在使用受Recursive Makefile Considered Harmful论文启发的makefile构建程序时遇到了一些麻烦。

我对makefile很新,而且我能够把它全部搞定,但是根据我的理解,有一些不起作用的东西应该正常工作。我希望你们/ gals能够为我澄清这些事情!

我正在运行OSX。使用g ++编译(或至少,打算)。以下是相关的makefiledepend.sh

生成文件

CC = g++
MODULES := src Engine Engine/core Engine/render
# look for include files in
# each of the modules
CFLAGS := $(patsubst %,-I%,$(MODULES)) -I/usr/local/include/SDL2/
# extra libraries if required
LIBS := -lm -L/usr/local/lib/ -lSDL2 -lSDL2main -lSDL2_image
# each module will add to this
SRC :=
# include the description for
# each module
include $(patsubst %,%/module.mk,$(MODULES))
# determine the object files
OBJ := $(patsubst %.cpp,%.o, $(filter %.cpp,$(SRC))) #\
#$(patsubst %.y,%.o, \
#$(filter %.y,$(SRC)))
# link the program
main: $(OBJ)
    $(CC) -o $@ $(OBJ) $(LIBS) $(CFLAGS)
# include the C++ include
# dependencies
include $(OBJ:.o=.d)
# calculate C++ include
# dependencies
%.d: %.cpp
    ./depend.sh ‘dirname $*.cpp‘ $(CFLAGS) $*.cpp > $@

clean:
    find ./ -iname "*.o" -exec rm {} \;
    find ./ -iname "*.d" -exec rm {} \;
    rm main

depend.sh

#!/bin/sh
DIR="$1"
shift 1
case "$DIR" in 
"" | ".")
g++ -MM -MG "$@" | 
sed -e ’s@ˆ\(.*\)\.o:@\1.d \1.o:@’
;;
*)
g++ -MM -MG "$@" | 
sed -e "s@ˆ\(.*\)\.o:@$DIR/\1.d $DIR/\1.o:@"
;;
esac

1。包含目录

我在我的应用程序中使用SDL2来处理Windows和其他媒体功能。我在/usr/local/include/SDL2/安装了SDL2 include目录。所以在我的CFLAGS中我有-I/usr/local/include/SDL2/。在之前的,非常简单的makefile这有效。包含SDL目录,包含SDL标头的代码文件按预期工作。但是使用上面的makefile,SDL include目录似乎被完全忽略了!我需要在我的代码文件中使用绝对路径来包含SDL(即忽略包含目录,对吗?)。

我的工作是在我的工作目录中创建一个符号链接并使用相对路径来访问它,但这远非理想......任何想法我可能在这里做错了什么?我从根本上误解了什么吗?

2。模块

此时似乎我需要更新顶级MODULES变量以包含我项目中的几乎所有文件夹。我试图将子文件夹附加到相应的module.mk文件,但没有任何效果。例如。我还从顶级Engine/core删除了Engine/rendermakefile模块,然后在module.mk文件夹中的Engine文件中删除了:< / p>

MODULES += Engine/core Engine/render

我的想法是,顶级makefile会看到有一个Engine模块,它会检查Engine文件夹,打开module.mk文件,并看到还有2个模块。这是不正确的吗?

奇怪的观察

在我的makefile我将CC定义为g++。然后,我在$(CC)目标中使用main。我还在depend.sh中指定了g ++。但是,当我成功构建时,我得到了一堆这些错误:

./depend.sh ‘dirname src/main.cpp‘ -Isrc -IJEngine -IEngine/core -IEngine/render -I/usr/local/include/SDL2/ src/main.cpp > src/main.d
clang: error: no such file or directory: 'src/main.cpp‘'

成功之后:

c++    -c -o src/main.o src/main.cpp
c++    -c -o Engine/Engine.o Engine/Engine.cpp
c++    -c -o Engine/core/Error.o Engine/core/Error.cpp
c++    -c -o Engine/core/Window.o Engine/core/Window.cpp
c++    -c -o Engine/render/Render.o Engine/render/Render.cpp
g++ -o main src/main.o Engine/Engine.o Engine/core/Error.o Engine/core/Window.o Engine/render/Render.o  -lm -L/usr/local/lib/ -lSDL2 -lSDL2main -lSDL2_image -Isrc -IEngine -IEngine/core -IEngine/render -I/usr/local/include/SDL2/

耶!它建成了!它运行!但那些错误到底是什么?为什么c++被用于除最后一次通话之外的所有内容而不是g++?我没有在任何地方指定c++(我认为!)

任何帮助将不胜感激!如果我遗漏了任何必要的信息,请告诉我。

1 个答案:

答案 0 :(得分:2)

CC变量是指c编译器而不是C ++编译器。对于cpp文件,make将使用默认为CXX的{​​{1}}值。这就是你在输出中看到c ++的原因。 c++也用于链接,这就是为什么您将CC的值视为最后一行输出的原因。

如果你想使用g ++作为cpp文件(假设你这样做了?),请设置CC而不是CXX(或添加到CC

您可以通过在没有makefile的目录中运行make -p来查看所有隐式规则和变量。

我认为dirname的{​​{1}}参数应该没有引号。您想要传递目录。

更新: 我应该注意到CFLAGS由隐式.c文件配方使用,但不适用于.cpp文件配方。因此在编译cpp文件时会忽略您的CFLAGS -I。您需要设置CXXFLAGS。