Simple Makefile Problem (with a simple dependency) - c++

I have 4 '.cpp' files and 1 header files:
Tools.cpp
Code1.cpp
Code2.cpp
Code3.cpp
and Tools.hh
Now all Code1.cpp, Code2.cpp, Code3.cpp
use functions stored in Tools.cpp.
Currently, what I do to compile all of them is using
this simple shell script:
#!/bin/bash
echo "compiling Code1.cpp";
g++ Code1.cpp Tools.cpp -o Code1
echo "compiling Code2.cpp";
g++ Code2.cpp Tools.cpp -o Code2
echo "compiling Code3.cpp";
g++ Code3.cpp Tools.cpp -o Code3
It all works fine.
Now I want to do that using a standard makefile.
But why this doesnt' work:
CXX = g++
TOOLSRC = Tools.cpp Code1.cpp Code2.cpp \
Code3.cpp
TOOLSINC = Tools.hh
all: Code1 Code2 Code3
Code1: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
Code2: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
Code3: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
The error I got is this:
ld: warning in makefile, file is not of required architecture
ld: duplicate symbol neighbors(std::vector<int, std::allocator<int> >&, int, int)in /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccQCrGHe.o and /var/folders/Yx/YxKmmyVPGpakdPL4St7X6++++TI/-Tmp-//ccreq9YU.o
collect2: ld returned 1 exit status
make: *** [FindNeighbours] Error 1
How can I correct the mistakes?

In these targets:
Code1: $(TOOLSRC) $(TOOLSINC) makefile
$(CXX) $^ -o $#
The resulting command will be:
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
This is clearly not what you want. g++ is attempting to compile both the header file and the makefile and doesn't know what to do with the makefile. You're also declaring dependencies on all three of your main units for each unit. So if Code3.cpp changes, Code1 will require recompilation. This is also undesirable.
Try something like this instead:
CXX = g++
all: Code1 Code2 Code3
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c -o $# $^
Code1: Code1.o Tools.o
$(CXX) -o $# $^
Code2: Code1.o Tools.o
$(CXX) -o $# $^
Code3: Code1.o Tools.o
$(CXX) -o $# $^

In short, $^ isn't what you want here. It evaluates to the "names of all the prerequisites, with spaces between them." In the problem Makefile, that causes all three targets to use almost identical command lines, that each look like
g++ Tools.cpp Code1.cpp Code2.cpp Code3.cpp Tools.hh makefile -o Code1
From the error message quoted, g++ has decided that makefile should be passed to the linker as if it were an object. It isn't. Without makefile on the line, you would still be compiling and linking all four of your source files, and quite likely leaving the linker to decide which of four main() functions to use.
You probably want to leverage the fact that make has a huge number of builtin rules for common cases. Compiling two source files and linking the result fits neatly into those common cases. Its untested, but the following should do all you want (assuming a recent build of gnu make, at least), and have the advantage of only compiling each object once.
all: Code1 Code2 Code3
Code1: Code1.o Tools.o
Code2: Code2.o Tools.o
Code3: Code3.o Tools.o
Code1.o Code2.o Code3.o Tools.o: Tools.hh
If you needed to set some compiler options you could add a definition for CXXFLAGS, traditionally near the top of the file.

Hm. Normally you'd specify dependencies on object files, with ".o" extensions. It might be that Make is being confused, since it has built-in rules for files of various types.
The error is because you're trying to link the makefile into the program, by passing $^ to the compiler.

On the right hand side of a rule you should put only the files that are usefull.
Code1: Code1.cpp Tools.cpp
$(CXX) $^ -o $#
Code1: Code2.cpp Tools.cpp
$(CXX) $^ -o $#
Code3: Code3.cpp Tools.cpp
$(CXX) $^ -o $#
While this solves your problem you should definitely read Grayfade’s answer on how to do things the "Right Way".

I am no expert at makefiles, but this is how I usually do it, and it works well.
COMPILER = g++
CXXFLAGS =
EXECUTABLE = code
all: code
code: Code1.o Code2.o Code3.o Tools.o
${COMPILER} ${CXXFLAGS} -o ${EXECUTABLE} Code1.o Code2.o Code3.o Tools.o
Code1.o: Code1.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code1.cpp
Code2.o: Code2.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code2.cpp
Code3.o: Code3.cpp Tools.o
${COMPILER} ${CXXFLAGS} -c Code3.cpp
Tools.o: Tools.cpp Tools.hh
${COMPILER} ${CXXFLAGS} -c Tools.cpp
clean:
rm *.o
rm ${EXECUTABLE}

Related

Building shared libraries with Makefile

I have a project that I want to build a shared library for it. The following Makefile works:
libfastpd.so: fastpd.cpp
$(CXX) -std=c++11 -fPIC -c fastpd.cpp -o fastpd.o
$(CXX) -std=c++11 -fPIC -c graph.cpp -o graph.o
$(CXX) -std=c++11 -fPIC -c LinkedBlockList.cpp -o LinkedBlockList.o
$(CXX) -std=c++11 -fPIC -c maxflow.cpp -o maxflow.o
$(CXX) -std=c++11 -shared -Wl,-soname,libfastpd.so -o libfastpd.so fastpd.o graph.o LinkedBlockList.o maxflow.o
clean:
rm *.o *.so
Then I came across this recipe in Cogswell et al.'s C++ Cookbook: https://www.oreilly.com/library/view/c-cookbook/0596007612/ch01s18.html
and decided to improve my Makefile based on that:
# Specify extensions of files to delete when cleaning
CLEANEXTS = o so
# Specify the source files, the target files,
# and the install directory
SOURCES = fastpd.cpp graph.cpp LinkedBlockList.cpp maxflow.cpp
OUTPUTFILE = libfastpd.so
INSTALLDIR = ./
.PHONY: all
all: $(OUTPUTFILE)
# Build lib*.so from all the *.o;
# subst is the search-and-replace
# function demonstrated in Recipe 1.16
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -o $# $^
.PHONY: install
install:
mkdir -p $(INSTALLDIR)
cp -p $(OUTPUTFILE) $(INSTALLDIR)
.PHONY: clean
clean:
for file in $(CLEANEXTS); do rm -f *.$$file; done
# Generate dependencies of .ccp files on .hpp files
include $(subst .cpp,.d,$(SOURCES))
%.d: %.cpp
$(CC) -M $(CPPFLAGS) $< > $#.$$$$; \
sed 's,\($*\)\.o[ :]*,\1.o $# : ,g' < $#.$$$$ > $#; \
rm -f $#.$$$$
Running this file I obtained the following error:
/usr/bin/ld: fastpd.o: relocation R_X86_64_32 against `.rodata' can
not be used when making a shared object; recompile with -fPIC
fastpd.o: error adding symbols: Bad value
Checking the terminal output, I observed that the following commands were executed:
g++ -c -o fastpd.o fastpd.cpp
g++ -c -o graph.o graph.cpp
g++ -c -o LinkedBlockList.o LinkedBlockList.cpp
g++ -c -o maxflow.o maxflow.cpp
No -fPIC!
My question is: Which lines of the Makefile execute these commands and how to add -fPIC to them?
Any references to good ressources to understand the entire Makefile above would be very much appreciated as well!
Thank you very much in advance for your help!
Which lines of the Makefile execute these commands... ?
The short answer is none. The rule...
$(OUTPUTFILE): $(subst .cpp,.o,$(SOURCES))
$(CXX) -shared -fPIC $(LDFLAGS) -o $# $^
only specifies the link time dependencies and command. The -fPIC option needs to be specified when you compile the source file but you haven't provided any rule to build a .o from a .cpp so make falls back on its implicit rule which (for the purposes of this example) is essentially...
%.o: %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $<
So the obvious solution is to add -fPIC to CXXFLAGS...
CXXFLAGS += -fPIC

Need help understanding makefile pattern rule % : %.o

I want to change this makefile into something simpler using pattern rules I read about in a book:
VPATH = src
CPPFLAGS = -I include
main.o: main.cpp
g++ $(CPPFLAGS) $<
TwoDimensionalShape.o: TwoDimensionalShape.cpp
g++ -c $(CPPFLAGS) $<
Square.o: Square.cpp Square.h
g++ -c $(CPPFLAGS) $<
Circle.o: Circle.cpp Circle.h
g++ -c $(CPPFLAGS) $<
Rectangle.o: Rectangle.cpp Rectangle.h
g++ -c $(CPPFLAGS) $<
Triangle.o: Triangle.cpp Triangle.h
g++ -c $(CPPFLAGS) $<
ShapeStack.o: ShapeStack.cpp ShapeStack.h
g++ -c $(CPPFLAGS) $<
ScreenManager.o: ScreenManager.cpp ScreenManager.h
g++ -c $(CPPFLAGS) $<
ScreenState.o: ScreenState.cpp ScreenState.h
g++ -c $(CPPFLAGS) $<
SquareState.o: SquareState.cpp SquareState.h
g++ -c $(CPPFLAGS) $<
CircleState.o: CircleState.cpp CircleState.h
g++ -c $(CPPFLAGS) $<
After reading the book I can write the above using pattern rules like this. But I don't understand how it is working:
#source files are in "src" folder.
VPATH = src
#header files are in "include" folder.
CPPFLAGS = -I include -Wall
all: main.o TwoDimensionalShape.o Square.o Circle.o Rectangle.o Triangle.o ShapeStack.o ScreenManager.o ScreenState.o SquareState.o CircleState.o
g++ $(CPPFLAGS) $^
%.o: %.cpp
g++ -c $(CPPFLAGS) $<
%: %.o
g++ $<
This makefile is correct however I don't understand how it is working.
If I change for example 2 source files, how does this makefile understand to only compile the changed two source files and not all of source files?
In the book I read, example was about C not C++ and last line was %: %.c. Then why is my line which is %: %.o working? Shouldn't it be %: %.cpp?
This makefile is correct however I don't understand how it is working.
If your new Makefile is a replacement for the old one, it is definitely NOT working.
In the "old" one you have e.g.
ShapeStack.o: ShapeStack.cpp ShapeStack.h
which tells that ShapeStack.o depends on the .cpp and header file. Your new Makefile did not have any dependencies to other files which will result in a lot of trouble. Simply touch one of your headers and type make. Nothing will happen!
So at minimum you have to introduce your source file dependecies, maybe manual as in your old makefile or with some more automatism which uses the dependency check from the compiler, using gcc it is with "gcc -MM".
For getting automated prerequisites see https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
And using vpath can result in a lot of trouble. There are some articels, e.g.:
http://make.mad-scientist.net/papers/how-not-to-use-vpath/
Some example Makefiles can be found already here:
minimum c++ make file for linux

"make" fails when using pattern matching

I'm trying to create a generic make file so that I can compile my project independently of how many files I add to it and where I decide to put them in the project tree.
In my step by step approach I cam to this makefile which works fine.
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
main.o : main.cpp board.hpp
$(CC) -c -I include $< -o build/$#
board.o : board.cpp board.hpp
$(CC) -c -I include $< -o build/$#
This version will do the job just fine. See output below:
me#01:~/code/projects/boardG$ make
g++ -c -I include src/main.cpp -o build/main.o
g++ -c -I include src/board/board.cpp -o build/board.o
g++ -o bin/boardG build/main.o build/board.o
The problem here is that I will have to create one rule for each .cpp file. Which is precisely what I try to avoid. Hence I tried to adapt the version above using matching patterns like this:
CC=g++
OBJECTS=main.o board.o
VPATH=src:\
src/board:\
include/board:\
build:\
bin
boardG : main.o board.o
$(CC) -o bin/boardG build/main.o build/board.o
%.o : %.cpp %.hpp
$(CC) -c -I include $< -o build/$#
When I run make now I get the follwing output:
me#01:~/code/projects/boardG$ make
g++ -c -o main.o src/main.cpp
src/main.cpp:2:27: fatal error: board/board.hpp: No such file or directory
compilation terminated.
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
My project has the follwing structure/files in it.
./bin/
./build/
./include/board/board.hpp
./src/main.cpp
./src/board/board.cpp
./makefile
I'm wondering why make would change the command when using pattern matching? Or, and probably more accurately, what am I doing wrong that makes make fail?
Just avoid using VPATH when it comes to object files. What's happening is that make is actually using the built-in rule for %.o and not using your rule at all.
If you prefix all your objects with the directory, this should work:
CC=g++
OBJDIR = build
OBJECTS = $(OBJDIR)/main.o $(OBJDIR)/board.o
VPATH = src:\
src/board:\
include/board:\
bin/boardG : $(OBJECTS)
$(CC) -o $# $^
$(OBJDIR)/%.o : %.cpp %.hpp
$(CC) -c -I include $< -o $#
Here is a helpful resource, which more or less exactly describes the problem you've run into.

GCC linking a static library

I have seen questions like these on SO but everyone has different answers and directory structures that aren't working for me.
My makefile:
CC = g++
DEBUG = -g -std=c++11
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
start: clean BingResultSet.o main.o
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) $(OBJECT_FILES) -o $(TARGET)
rm -f *.o
BingResultSet.o: BingResultSet.cpp BingResultSet.h
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c BingResultSet.cpp
main.o: main.cpp
$(CC) $(DEBUG) $(INC_PATH) $(LIB_PATH) -c main.cpp
clean:
rm -f $(OBJECT_FILES) $(TARGET)
My file structure:
/Desktop/DataMiner/.cpp, .h, and makefile
/Desktop/DataMiner/HTTPClientLib/include/HTTPClient.h
/Desktop/DataMiner/HTTPClientLib/lib/HTTPClient.a
What's the correct way to link my static lib in my makefile?
Here's my $0.02:
there was no static library involved. Assuming you meant the .o files
you mix dependencies and build rules, instead, avoid repeating build rules:
$(TARGET): $(OBJECT_FILES)
$(CXX) $(DEBUG) $(INC_PATH) $^ -o $# $(LIB_PATH)
%.o: %.cpp
$(CXX) $(DEBUG) $(INC_PATH) -c $< -o $#
You used CC for a C++ compiler. That's strange. Use CXX
You used LDFLAGS when you were just compiling
You hardcoded the source and destination paths. Instead use the automatic variables ($^, $< for source; $# for destination)
You tried to hardcode header dependencies. That's error-prone and messes up source specification (you don't want $^ to list .h files in your command line...). Instead, use gcc -MM¹ to generate the dependencies for you!
Next, do a conditional include of those dependencies:
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
It's usually handy to keep the .o files so you can speed up builds. Of course, this was not a good plan until you generated the header dependencies automatically. If you insist, you can comment the .PRECIOUS target. Intermediate targets are automatically deleted by GNU Make
Here's the integrated offering I ended up with:
CXX = g++
TARGET = main
OBJECT_FILES = BingResultSet.o main.o
INC_PATH = -I HTTPClientLib/include
LIB_PATH = -L HTTPClientLib/lib/
CPPFLAGS = -g -std=c++11
CPPFLAGS+= $(INC_PATH)
# standard derived flags:
CXXFLAGS+=$(CPPFLAGS)
LDFLAGS+=$(LIB_PATH)
start: .depends $(TARGET)
$(TARGET): $(OBJECT_FILES)
$(CXX) $(CXXFLAGS) $^ -o $# $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
clean:
rm -f .depends $(OBJECT_FILES) $(TARGET)
# to keep the .o files:
.PRECIOUS: $(OBJECT_FILES)
.depends:
$(CXX) -MM $(CXXFLAGS) -c *.cpp > $#
-include .depends
On a very simple sample set of files you get:
$ make clean
rm -f .depends BingResultSet.o main.o main
$ make
g++ -MM -g -std=c++11 -I HTTPClientLib/include -c *.cpp > .depends
g++ -I HTTPClientLib/include -c BingResultSet.cpp -o BingResultSet.o
g++ -I HTTPClientLib/include -c main.cpp -o main.o
g++ -I HTTPClientLib/include BingResultSet.o main.o -o main -L HTTPClientLib/lib/
$ cat .depends
BingResultSet.o: BingResultSet.cpp BingResultSet.h
main.o: main.cpp BingResultSet.h
test.o: test.cpp
¹ (or similar, see man-page)

g++ consolidation: ld: fatal: file main.o: unknown file type

I'm scanning the web and all my project files for solution but still can't find the answer why my linker won't finish the job. Everything smoothly compiles into .o files, but the last make command fails. And here is the Makefile content:
CXX = g++
CXXFLAGS = -Wall -pedantic -c
OBJS = main.o operacje.o porownaj.o
dzialania: $(OBJS)
$(CXX) $^ -o $#
main.o: main.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
porownaj.o: porownaj.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $^ -o $#
clean:
rm -f *o
and again, here is the mistake that pops out:
g++ main.o operacje.o porownaj.o -o dzialania
ld: fatal: file main.o: unknown file type
ld: fatal: file processing errors. No output written to dzialania
*** Error code 1
make: Fatal error: Command failed for target `dzialania'
I'm sure it's some kind of a basic mistake but after staring at the file for a few hours I won't notice it anyway. Maybe some of you folks with notice the bug with a fresh eye.
btw. it's my first post after long-term passive lurking, I hope I did everything right. Thanks in advance!
#edit1 OK, I did all the suggested corrections
#edit2 Seems like the problem is caused by improper module division of my program. I'll rearrange it's structure and let you know if it works then. Thanks for all the support!
#edit3 OK, I changed the structure of my program and everything runs smooth, Thanks again!
Try using $< instead of $^ in your rules to compile main.o, operacje.o, and porownaj.o:
main.o: main.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
porownaj.o: porownaj.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) $< -o $#
That will cause make to compile only the corresponding .cpp file. When you use $^ the header files are passed to the g++ command which tells the compiler to create precompiled headers for them - that's what's ending up in main.o instead of the object file for main.cpp.
GNU make variable definitions like CC = g++, or CFLAGS = -Wall -pedantic etc.. should each be on its own line:
CC = g++
CFLAGS = -Wall -pedantic
OBJS = main.o operacje.o porownaj.o
BTW, you probably mean
CXX = g++
CXXFLAGS = -Wall -pedantic
You certainly don't want -c explicitly in your CFLAGS or CXXFLAGS; you really should remove it.
Also, recipes should be after its rule, so you want
dzialania: $(OBJS)
$(LINK.cc) $^ -o $#
operacje.o: operacje.cpp operacje.h porownaj.h
$(CXX) $(CXXFLAGS) -c $< -o $#
The several spaces are actually a single tab character.
Run make -p to understand the rules known by make; see also this answer and that one.
Take time to read GNU make documentation.