Makefile for c++ with one .o file and one .CPP file - c++

I am trying to create a makefile to build a windows c++ project on linux. I have to compile .cpp in different directories, to create a library .so with the objects.
For that I have created a script to find the .cpp and put it in a file :
SOURCE= \
./Source/CHAINE.CPP\
./Source/CRACKCHN.CPP\
./Source/LISTEPTR.CPP\
Now my makefile looks like : (I know I will have to change the $(TARGET) : $(OBJECT) rule, but thats not my problem here i think)
-include sources.mk
OBJECT = $(SOURCE:%.CPP=%.o)
#
$(TARGET) : $(OBJECT)
$(CC) $(CFLAGS) -o $# $^ $(LIBS)
$(OBJECT) : $(SOURCE)
$(CC) $(CFLAG) $(PREPROC) -c $< -o $(OBJ_DIR)/$# $(INCLUDE)
But when i do the make command, all the objects are created with the first .CPP (CHAINE.CPP here) :
g++ -Wall -D _MSC_VER -D _GPP -c Source/CHAINE.CPP -o ./Source/CHAINE.o
===
g++ -Wall -D _MSC_VER -D _GPP -c Source/CHAINE.CPP -o ./Source/CRACKCHN.o
===
g++ -Wall -D _MSC_VER -D _GPP -c Source/CHAINE.CPP -o ./Source/LISTEPTR.o
This is the first time I have to create a makefile, and I have a lot of problems to solve it, if anybody have a solution?

$(OBJECT) is a list of all objects. With the last rule you seem to want to tell Make how to build a single .o from a single .cpp. It should have a for of:
%.o: %.cpp
$(CC) $(CFLAG) $(PREPROC) -c $< -o $(OBJ_DIR)/$# $(INCLUDE)

Related

Combing object files generated out of C and C++ projects

I am trying to compile two projects together to create one executable. The first project is written in C and it uses the following portion of the makefile to generate the corresponding object files.
obj/%.o : %.c .dirs
$(CC) $(MKDEPEND) -w -c -o $# $(CFLAGS) $(INCDIRS) $<
The second project is written in C++ and it uses the following portion of the Makefile to generate the object file.
obj/%.o : %.cpp .dirs
$(CXX) $(MKDEPEND) -w -c -o $# $(CFLAGS) $(INCDIRS) $<
When I try to create the final executable, I receive an "undefined reference to function" for my C objects. What am I doing wrong? Any help is appreciated.
$(TARGET) : $(OOBJS) $(SUBTARGETS)
$(CXX) -w -o $(TMP_TARGET) $(OOBJS) $(LIBS) $(LFLAGS) $(SUBTARGETS) && mv -f $(TMP_TARGET) $#

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

Makefile - .o: file not recognized: File truncated?

I'm just learning GNU make, but I'm having trouble linking when using .d (dependency) files. Can anyone point me in the right direction with this error:
...../part1.o: file not recognized: File truncated
recipe for target 'bin/target/prog' failed
It's a simple program containing: main.cpp, part1.cpp, part1.h, part2.cpp, part2.h
Where part1 and part2 have a method to print something.
This is from terminal when running make:
I don't get why I'm getting a warning for using #pragma once?
stud#GoldenImageASE:~/Desktop/ISU/L1/2$ make ARCH=target -f Makefile.th
Compiling...part2.cpp
arm-devkit-g++ -MTbuild/target/part2.o -MM -I. part2.cpp > build/target/part2.d
Compiling...part1.cpp
arm-devkit-g++ -MTbuild/target/part1.o -MM -I. part1.cpp > build/target/part1.d
Compiling...main.cpp
arm-devkit-g++ -MTbuild/target/main.o -MM -I. main.cpp > build/target/main.d
object file....main.o
arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o
part1.h:1:9: warning: #pragma once in main file
#pragma once
^
part2.h:1:9: warning: #pragma once in main file
#pragma once
^
object file....part1.o
arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o
object file....part2.o
arm-devkit-g++ -I. -c part2.cpp > build/target/part2.o
arm-devkit-g++ -I. -o build/target/main.o build/target/part1.o build/target/part2.o -o prog
build/target/part1.o: file not recognized: File truncated
collect2: error: ld returned 1 exit status
Makefile.th:27: recipe for target 'bin/target/prog' failed
make: *** [bin/target/prog] Error 1
My Makefile is found below:
# Variables
SOURCES=main.cpp part1.cpp part2.cpp
OBJECTS=$(SOURCES:.cpp=.o)
DEPS=$(SOURCES:.cpp=.d)
EXE=prog
CXXFLAGS =-I.
# Making for host
# > make ARCH=host
ifeq (${ARCH},host)
CXX=g++
BUILD_DIR=build/host
EXE_DIR=bin/host
endif
# Making for target
# > make ARCH= target
ifeq (${ARCH},target)
CXX=arm-devkit-g++
BUILD_DIR=build/target
EXE_DIR=bin/target
endif
$(addprefix ${EXE_DIR}/,$(EXE)): $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))
# << Check the $(DEPS) new dependency
#mkdir -p $(dir $#)
$(CXX) $(CXXFLAGS) -o $(addprefix ${BUILD_DIR}/,$(OBJECTS))
$(addprefix $(BUILD_DIR)/, %.o): %.cpp
#echo "object file...."$*.o
$(CXX) $(CXXFLAGS) -c $^ > $#
# Rule that describes how a .d ( dependency ) file is created from a .cpp
# Similar to the assigment %. cpp -> %.o
${BUILD_DIR}/%.d: %.cpp
#mkdir -p $(dir $#)
#echo "Compiling..."$<
$(CXX) -MT$(#:.d=.o) -MM $(CXXFLAGS) $^ > $#
debug:
#echo "DEPS: "$(DEPS)"\n"
#echo "OBJ: " $(addprefix ${BUILD_DIR}/,$(OBJECTS))"\n"
#echo "EXE: " $(addprefix ${EXE_DIR}/,$(EXE))"\n"
.PHONY:clean
clean:
rm -f $(EXE) $(addprefix ${BUILD_DIR}/,$(DEPS)) $(addprefix ${BUILD_DIR}/,$(OBJECTS))
ifneq ($(MAKECMDGOALS),clean)
-include $(addprefix ${BUILD_DIR}/,$(DEPS))
endif
You have two unrelated problems. The first one is that you have two conflicting -o options when linking.
The actual problem you ask about is something different, but still related to the -o option: Namely that you don't have one when attempting to create the object files.
When creating the object files, the generated object file is not written to standard output, therefore your redirection will not cause the gcc frontend program to create an object file with the name you think.
For example:
arm-devkit-g++ -I. -c part1.cpp > build/target/part1.o
The above command will create an object file named part1.o in the current directory, and write the (empty) standard output to the file build/target/part1.o. That will leave build/target/part1.o empty, which is what the linker is complaining about (that's what it means when it says the file is truncated).
The command should instead look like
arm-devkit-g++ -I. -c part1.cpp -o build/target/part1.o
Note the use of the -o option to name the output file.
You need to modify the makefile to not use redirection when building the object files.
Also, you should not list the header files when building object files, only the source file you want to build, so the command
arm-devkit-g++ -I. -c main.cpp part1.h part2.h > build/target/main.o
should really be
arm-devkit-g++ -I. -c main.cpp -o build/target/main.o
You're not compiling your object files correctly. g++ doesn't output the files to stdout, it writes them to the local directly. If you want to put the object files in a specific directory, you need to use the -o option:
$(BUILD_DIR)/%.o: %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -c $^ -o $#
^^^^^^
$(BUILD_DIR):
#mkdir -p $#
Also you're building your executable incorrectly. The dependencies are insufficient and you don't have your target listed. You'll want this:
$(EXE_DIR)/$(EXE) : $(addprefix $(BUILD_DIR),$(OBJECTS)) | $(EXE_DIR)
$(CXX) $(CXXFLAGS) -o $# $^
$(EXE_DIR):
#mkdir -p $#
This will create an order-only dependency from your binary on the directory, and correctly build the binary. Note that you shouldn't have a dependency from your target on your .d files. That makes little sense. Instead, your rule for building the .os should simply also build the .ds (that rule suffers the same problem currently as your .o rule):
# build the .o and the .d in one go
$(BUILD_DIR)/%.o : %.cpp | $(BUILD_DIR)
$(CXX) $(CXXFLAGS) -o $# -c $< -MP -MMD -MF $(#:.o=.d)
AS AN EDITORIAL ASIDE, THERE IS THIS COMMON TENDENCY TO WRITE ALL VARIABLES IN MAKEFILES IN SHOUTY_CAPS. THIS IS PROVABLY MUCH MORE DIFFICULT TO READ THAN USING JUST USING snake_case. Lower case letters work just fine.

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)