ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm trying to figure out how Make handles directories. How can I modify this makefile so it will put all of the .o files in a separate build directory?
but make ignores this and still puts main.o in the base directory. And if I refer to the build directory in the dependencies for bandit, make complains about "no rule ..."
I want to keep main.cpp in the base directory, all other sources in the src directory, and all object files in the build directory.
Thanks, tuxdev, I can hardly see any resemblance between yours & mine. I'll have to study it tonight -- there's much that I don't understand, but have to go to class now. If you can post a link to something that explains what you did (hopefully something more compact than the entire gnu make manual) that would be great.
I'm still having a hard time with this. Your makefile didn't do anything. At first it was saying "nothing to do for all", so I added a rule under bandit. Then it said "undefined reference to main" so I added rule for main. Then it was failing on undefined references to JBandit and JBanditX1, so it seems that for some reason the wildcard definitions weren't working. I couldn't figure out how to fix them, so I finally put back separate rules for those sources as well. clean wasn't deleting the .d files or the executable. (It never made an "obj" directory either.)
So, in order to get it to work, I went back to writing a separate line for each target (although I see now that I don't have to write explicit rules for each object file).
But I still can't figure out how to put the .o files in a separate directory. I haven't found anything in the make manual about this.
So here's what I have now. I added some dependencies that I had omitted from my original makefile.
It works, but still doesn't use the directory structure I wanted, and doesn't use any of those nice pattern substitution rules.
Can you see what's wrong with the wildcard statements in your makefile? Also, what are the lines "LINK.o = $(LINK.cpp)" and "-include $(DEPS)" for? I don't understand what they are doing.
The wildcards should only fail if: 1. you aren't really using GNU make or 2. the files aren't where I think they are.
The point of LINK.o = $(LINK.cpp) is to change the default linker for .o files from the C linker (cc) to the C++ linker (g++). That allows GCC to know how to make "bandit" from the .o files properly without any extra effort.
The -include relates to the -MD flag for GCC automated dependency tracking.
Don't go adding rules willy-nilly, the point of the implicit rule is to completely avoid the need to write any manually (which is what you ended up doing anyway).
Yes, I am trying to learn how to use the implicit rules as much as possible. I am definitely using Gnu Make 3.81.
I think you understand where the files are. main.cpp is in the project root directory (jbandit). The other source files are in the jbandit/src directory. All headers are in the jbandit/include directory.
I went back to your version, and tried again to modify it only to the minimum extent necessary to get it to work. My code is below, with comments embedded describing why (I think) the changes were needed.
I had to use VPATH to get it to find the files in obj.
I had to define OBJS explicitly; couldn't work out how to use % subst.
DEPS never seems to get defined.
I had to add an explicit rule to link the executable bandit.
I added a separate dependency line for main.o because main depends on all of the class headers.
Finally, I tried (unsuccessfully) to add a %-substitution expression for the class headers to the dependency line for the other (class) object files, but when I did, for some mysterious reason it failed to compile main.o, even though there is a separate rule for main.o.
Can you shed any light on any of these?
(It's not as bad as it looks here -- plain code is posted below this.)
Code with comments:
Code:
CXXFLAGS = -g -pipe -O3 -Wall -Wextra -Weffc++ -ansi -pedantic -MD
LDFLAGS = -lgsl -lgslcblas
LINK.o = $(LINK.cpp)
#without VPATH "No rule to make target `obj/JBandit.o` needed by `bandit`
VPATH = src include
SRCS = $(wildcard *.cpp) $(wildcard src/*.cpp)
INCLS = $(wildcard include/*.h)
#Can't define OBJS by %-substitution -- because obj doesn't exist yet?
OBJS = obj/main.o obj/JBandit.o obj/JBanditX1.o
#OBJS = $(SRCS:%.cpp:obj/%.o)
#I left your DEPS definition here, but it seems that $(DEPS) is never defined.
#Whenever I run `make test`, the "DEPS" line is empty.
DEPS = $(DEPS:%.cpp:obj/%.d)
.PHONY: all clean test
all: bandit
#without an explicit rule for bandit, only .o files are compiled (no executable)
bandit: $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o bandit
#I think I need this rule for main.o because (1)main.cpp is not in srcs directory and
#(2)main depends on all headers whereas the individual classes in srcs each depends
#only on its own header
obj/main.o: main.cpp $(INCLS)
#however, if I add %.h to the following rule, i.e.
#obj/%.o: %.cpp %.h
#it compiles JBandit.o and JBanditX1.o but NOT main.o, and says
#g++: obj/main.o:No such file or directory
#make: *** [bandit] Error 1
#on the other hand, if I write
#obj/%.o: %.cpp $(INCLS)
#it works, but this is really not the correct dependency since each of the
#class .cpp files depends only on its own header.
#It also works if I omit the header dependency altogether, but then a header
#could be changed without triggering a recompile of the object file.
obj/%.o: %.cpp
mkdir -p `dirname $@`
$(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $< -o $@
clean:
$(RM) bandit
$(RM) obj/*
rmdir obj
test:
@echo "SRCS: $(SRCS)"
@echo "INCLS: $(INCLS)"
@echo "OBJS: $(OBJS)"
@echo "DEPS: $(DEPS)"
-include $(DEPS)
#without VPATH "No rule to make target `obj/JBandit.o` needed by `bandit`
Not sure why it's not finding stuff - it really should, unless something else is weird.
Quote:
#Can't define OBJS by %-substitution -- because obj doesn't exist yet?
%-sub is a simple text macro - it just pastes the text, doesn't even glance at the filesystem.
Quote:
#I left your DEPS definition here, but it seems that $(DEPS) is never defined.
#Whenever I run `make test`, the "DEPS" line is empty.
Hehe, it'd help if it used SRCS in the #-sub. Oops.
Quote:
#without an explicit rule for bandit, only .o files are compiled (no executable)
Not sure why it isn't, the LINK.o = $(LINK.cpp) should automatically take care of things.
Quote:
#I think I need this rule for main.o because (1)main.cpp is not in srcs directory and
#(2)main depends on all headers whereas the individual classes in srcs each depends
#only on its own header
The automated dependency tracking is *exactly* to avoid needing to do anything special for (2).
succeeds at defining OBJS and DEPS. Needed a "=" instead of ":". That does almost what I wanted, but it creates a objs/srcs subdirectory where I wanted objs to be a flat file, so my solution is this:
which puts all of the .o and .d files in objs with no subdirectory.
Are you *really* sure you want to do this? Filenames can clash badly. Might not be an issue for this particular project right now, but later..
Quote:
I can't find any documentation on this. Can you point me in the right direction?
It's something I discovered while I was reading through the output of "make -p". When run in a directory without a Makefile, it dumps all the variables and implicit rules provided for free. One of these rules is:
Code:
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@
Hmm.. perhaps I've been using LDFLAGS when I should be using LDLIBS.. Learn something new every day
Are you *really* sure you want to do this? Filenames can clash badly. Might not be an issue for this particular project right now, but later..
Yes, I think you're right. I've changed it back to "OBJS = $(SRCS:%.cpp=obj/%.o)" so it preserves the directory structure in obj/.
Quote:
Hmm.. perhaps I've been using LDFLAGS when I should be using LDLIBS.. Learn something new every day
For what it's worth, I tried replacing LDFLAGS with LDLIBS but it seems to make no difference -- I still need the explicit rule to generate an executable.
I have another question: where is "core" defined? When I had "$(RM) core" under clean, it had no effect. I have to explicitly name "bandit" in the clean section in order to delete it. The Make Manual uses core in the example in Appendix C but doesn't say anything about it, and I can't find any mention of core in the output of make -p.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.