简体   繁体   中英

“Recursive Makefile Considered Harmful” style makefile issues

I am having some troubles getting my program to build using a makefile inspired by the Recursive Makefile Considered Harmful paper.

I am quite new to makefile s, and I am able to get it all to build fine, however there are a couple of things that aren't working that, from my understanding, should be working. I was hoping that you guys/gals would be able to either clarify that things for me!

I am running OSX. Using g++ to compile (or at least, intending to). Here is the relevant makefile and depend.sh

makefile

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. Include Directories

I am using SDL2 in my application to handle windows and other media functionality. I have my SDL2 include directory installed at /usr/local/include/SDL2/ . So in my CFLAGS I have -I/usr/local/include/SDL2/ . In a previous, very simple makefile this worked. The SDL directory was included and my code files that were including SDL headers worked as expected. But using the makefile above, the SDL include directory seems to be completely ignored! I need to use absolute paths in my code files to include SDL (ie. Include directory ignored, correct?).

My work around has been to create a symlink in my working directory and use relative paths to access that, but that is far from ideal... Any ideas what I could be doing wrong here? Am I fundamentally misunderstanding something?

2. Modules

At this point it seems as though I need to update the top-level MODULES variable to include pretty much every folder in my project. I have tried to append child folders to the respective module.mk file but that had no effect. Eg. I also removed the Engine/core and Engine/render modules from the top-level makefile , then in the module.mk file found in the Engine folder, I had:

MODULES += Engine/core Engine/render

My thinking is that the top-level makefile would see that there is an Engine module, it would check the Engine folder, open up the module.mk file, and see that there were 2 more modules. Is this incorrect?

A strange observation

In my makefile I define CC as g++ . I then use $(CC) in the main target. I also specify g++ in depend.sh . However when I build successfully, I get a bunch of these errors:

./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‘'

Followed by success:

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/

Yay! It built! And it runs! But what were those errors? And why is c++ being used for everything except the last call and not g++ ? I haven't specified c++ anywhere (i think!)

Any help will be greatly appreciated! Let me know if I am missing any necessary information.

The CC variable refers to the c compiler not the C++ compiler. For cpp files, make will use the value of CXX which defaults to c++ . That's why you see c++ in the output. CC is also used for linking, which is why you see the value of CC as the last line of output.

If you want to use g++ for the cpp files (assume you do?), set CXX instead of (or addition to) CC .

You can see all the implicit rules and variables by running make -p in a directory with no makefiles.

I believe the dirname argument to depend.sh should have no quotes around it. You want to pass the directory in.

UPDATE: I should have noted that CFLAGS is used by the implicit .c file recipe, but not for the .cpp file recipe. So your CFLAGS -I is ignored when compiling your cpp files. You need to set CXXFLAGS instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM