GNU makefile detect header changes - gnu-make

I have a directory with dozens of source and header files. Is there a better or cleaner way than the following %.o target for make to detect changes to header files? When the object is compiled, g++ is invoked with both the .cc and .h files which doesn't seem right, it should find the .h file automatically.
%.o: %.cc %.h
g++ -c $^
OBJECTS=headless-driver.o config.o simplefm2.o emulator.o basis-util.o objective.o weighted-objectives.o motifs.o util.o
learnfun : $(OBJECTS) learnfun.o
g++ $^ -o $#

%.o: %.cc %.h
g++ -c $^
You are specifying $^ which expands to all dependencies. If you just want the first dependency on the Gcc command line, use $< instead.

Related

What is the meaning of -lNew in Makefile?

I am confused with the option -lNew in a Makefile.
What is the meaning of -lNEW ?
Do you know where can I get more information?
TARGET = Example
OBJS = main.o user.o
CXXLIBS = -Wall -lNew -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
all: $(TARGET)
$(TARGET):$(OBJS)
$(CXX) -o $# $(OBJS) $(LIBS) $(CXXLIBS)
Supposing GCC is your build toolchain, -lNew tells to the linker to add the library called "libNew.so" or "libNew.a" to the list of files to link in the output binary.

Why is it compiling file twice

I have a makefile
jumbo: objs/jumbo.o objs/utils.o
objs/%.o: %.C
$(CXX) $(CFLAGS) $(CPPFLAGS) -c -o $# $<
The result of the compile
g++ jumbo.C objs/jumbo.o objs/utils.o -o jumbo
objs/jumbo.o:jumbo.C:(.text+0x0): multiple definition of `main'
/tmp/ccwEFt9o.o:jumbo.C:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
make: *** [<builtin>: server] Error 1
if I replace the definition of jumbo
jumbo: jumbo.C objs/utils.o
the problem goes away but the object file is not put away in the objs directory
And I don't know whether it is recompiling jumbo or not when it should only be relinking
You haven't defined any recipe for building the target jumbo. Because of that, make looks for a built-in rule and there is one that knows how to build a file X from a file X.C. Make looks at the directory and lo and behold, there's an X.C (jumbo.C) that exists, so make chooses to use that built-in rule. The built-in rule is:
%: %.C
$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $#
so, since jumbo depends on objs/jumbo. and objs/utils.o directory plus the jumbo.C from the default implicit rule, you get all three on the command line.
To fix this just define your own recipe for creating jumbo:
jumbo: objs/jumbo.o objs/utils.o
$(LINK.C) $^ $(LOADLIBES) $(LDLIBS) -o $#

gnu make multiple targets one object each

I have an old project for which I'm trying to create a multiple binaries, one for each object in the directory. I cannot for the life of me figure out how to deal with multiple targets in this manner. The following works, but it seems to me I should be able to have one rule to link them all, so to speak,
# compile objects, no problem
%.o: %.c
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#
bin: bin.o
$(CC) -o $# $< ../lib/libfoo.a -lm $(ARCH)
bar: bar.o
$(CC) -o $# $< ../lib/libfoo.a -lm $(ARCH)
One approach that I did get to work is to strip off the suffix from the target name like this, and compile and link in one step, but it feels a little hackish,
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) $< ../lib/libfoo.a -lm -o $(*F)
Disclaimer: I despise make
UPDATE 1: this is what I ended up with
EXECS = bin bar ...
all: $(EXECS)
%: %.c
#echo "Building $# from $<"
$(CC) -c $(CFLAGS) $(CPPFLAGS) $< -o $#.o
$(CC) $(CFLAGS) $(CPPFLAGS) $#.o ../lib/libfoo.a -lm -o $#
The convention is to have something like this at the top of your Makefile:
.PHONY: all
all: bin bar
Thus make all will make bin and bar, and by putting it at the top it's the default target for make without arguments. The .PHONY: documents this as a "metatarget", but also instructs Make to run it even if there happens to be a file called all with a fresh datestamp.
%: %.o
$(CC) -o $# $< ../lib/libfoo.a -lm $(ARCH)
This tells Make how to make them both.

Makefile errors when I change a directory name

I have a Makefile that compiles, but I want to change the name of one of the directories from "release" to "objects". This is the original Makefile -
# This makefile compiles ....
INCLUDE = -I/usr/include/X11 -I/usr/local/include -I/usr/local/include/FL/images -I/usr/include/freetype2
CC=g++
CFLAGS=-w -D LINUX -O3 -fpermissive
OBJDIR=release # HERE IS THE DIRECTORY I WANT TO CHANGE
SRCDIR=src
LDFLAGS= -L/usr/X11R6/lib$(LIBSELECT) -lpthread -lfltk -lXext -lXft -lfontconfig -lXinerama -lpthread -ldl -lm -lX11
SOURCES_RAW= robot_driver_agent.cpp robot_driver_position.cpp robot_driver_priorityqueue.cpp main.cpp robot_driver_tree.cpp robot_driver_stack.cpp robot_driver_grid.cpp robot_driver_path.cpp grid_analyzer.cpp tcpserver.cpp tcpclient.cpp servercontrol.cpp clientcontrol.cpp robot.cpp udpserver.cpp udpclient.cpp owncontrol.cpp guiwindow.cpp rs232.cpp
TARGET:= go
TARGETD:= go_d
OBJECTS:=$(SOURCES_RAW:.cpp=.o)
OBJECTS:=$(patsubst %.o, $(OBJDIR)/%.o, $(OBJECTS))
SOURCES:=$(SOURCES_RAW)
SOURCES:=$(patsubst %.cpp, $(SRCDIR)/%.cpp, $(SOURCES))
all: $(TARGET)
$(TARGET): $(OBJECTS)
$(CC) -w -D LINUX $(INCLUDE) $^ -o $# $(LDFLAGS)
release/%.o: src/%.cpp
test -d $(OBJDIR) || mkdir $(OBJDIR)
$(CC) -g -c $< $(CFLAGS) -o $#
debug: $(TARGETD)
$(TARGETD): $(OBJECTS)
$(CC) -w -D LINUX $(INCLUDE) $^ -o $# $(LDFLAGS)
%.o: $(SRCDIR)/%.cpp
$(CC) -c -g $< $(CFLAGS)-o $#
.PHONY : clean
clean:
rm -f $(OBJDIR)/*.o
rm -f $(TARGET) $(TARGETD)
All I do is change the OBJDIR symbol to "objects" so it would just be -
OBJDIR=objects
But when I do that, I get the error -
make: *** No rule to make target `objects/robot_driver_agent.o', needed by `go'.
What am I missing? Is "objects" a word reserved for something in make so I can't use it for directories? Is it something in the make file that I need to change? Honestly, I don't know that much about makefiles so any help at all would be great. Thanks.
You have a rule:
release/%.o: src/%.cpp
...
So that when OBJDIR=release and Make wants to build release/robot_driver_agent.o, it knows just what to do. Then you try OBJDIR=objects, it wants to build objects/robot_driver_agent.o, and it doesn't know how because there's no rule that fits. Try changing the rule to:
$(OBJDIR)/%.o: src/%.cpp
...

How to include clean target in Makefile?

I have a Makefile that looks like this
CXX = g++ -O2 -Wall
all: code1 code2
code1: code1.cc utilities.cc
$(CXX) $^ -o $#
code2: code2.cc utilities.cc
$(CXX) $^ -o $#
What I want to do next is to include clean target so that every time
I run make it will automatically delete the existing binary files of code1 and code2 before creating the new ones.
I tried to put these lines at the very end of the makefile, but it doesn't work
clean:
rm -f $#
echo Clean done
What's the right way to do it?
The best thing is probably to create a variable that holds your binaries:
binaries=code1 code2
Then use that in the all-target, to avoid repeating:
all: clean $(binaries)
Now, you can use this with the clean-target, too, and just add some globs to catch object files and stuff:
.PHONY: clean
clean:
rm -f $(binaries) *.o
Note use of the .PHONY to make clean a pseudo-target. This is a GNU make feature, so if you need to be portable to other make implementations, don't use it.
In makefile language $# means "name of the target", so rm -f $# translates to rm -f clean.
You need to specify to rm what exactly you want to delete, like rm -f *.o code1 code2
By the way it is written, clean rule is invoked only if it is explicitly called:
make clean
I think it is better, than make clean every time. If you want to do this by your way, try this:
CXX = g++ -O2 -Wall
all: clean code1 code2
code1: code1.cc utilities.cc
$(CXX) $^ -o $#
code2: code2.cc utilities.cc
$(CXX) $^ -o $#
clean:
rm ...
echo Clean done

Resources