passing optional arguments to a makefile - c++

I have a program and i have this make file and im trying to run my program with this makefile, and it compiles well the problem is when i run the program i what to run it like this ./user -n tejo.tecnico.ulisboa.pt -p 58011 with this -n tejo.tecnico.ulisboa.pt or this -p 58011 being optional.
I saw this post Passing arguments to "make run" and im not understanding what im doing wrong in the make run command
So can anyone tell me whats wrong in my makefile?
btw im fairly new at making makefiles and using the command line.
Program:
# Makefile
CC = g++
LD = g++
AUXLIB = auxiliar_code/aux_functions.h
SOCKETLIB = socket_operations/socket_functs.h
COMMANDSLIB = commands/commands.h
.PHONY: all clean run
all: client
client: socket_operations/socket.o auxiliar_code/aux.o commands/commands.o commands/client.o main.o
$(LD) -o user socket_operations/socket.o auxiliar_code/aux.o commands/commands.o commands/client.o main.o
auxiliar_code/aux.o: auxiliar_code/aux_functions.cpp $(AUXLIB) client_constants.h
$(CC) -o auxiliar_code/aux.o -c auxiliar_code/aux_functions.cpp
commands/client.o: commands/Client.cpp $(COMMANDSLIB) $(SOCKETLIB) $(AUXLIB) client_constants.h
$(CC) -o commands/client.o -c commands/Client.cpp
commands/commands.o: commands/commands.cpp $(COMMANDSLIB) $(SOCKETLIB) $(AUXLIB) client_constants.h
$(CC) -o commands/commands.o -c commands/commands.cpp
socket_operations/socket.o: socket_operations/socket_functs.cpp $(SOCKETLIB) $(AUXLIB) client_constants.h
$(CC) -o socket_operations/socket.o -c socket_operations/socket_functs.cpp
main.o: main.cpp $(COMMANDSLIB) $(AUXLIB) client_constants.h
$(CC) $(CFLAGS) -o main.o -c main.cpp
clean:
#echo Cleaning files generated
rm -f auxiliar_code/*.o commands/*.o socket_operations/*.o *.o user
run: user
#echo ./user $(filter-out $#,$(MAKECMDGOALS))
%:
#:

What you should do is to declare a variable (possibly with default):
# Fill in your default here, setting from command line will override
USER_OPTIONS ?=
run: user
./user $(USER_OPTIONS)
Then invoke make setting the option from the command line:
make run USER_OPTIONS="-n tejo.tecnico.ulisboa.pt -p 58011"

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

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)

Trouble running a make file

Here is my make file
cat Makefile
# define required macros here
SHELL= /bin/sh
OBJS = main.o factorial.o hello.o
CFLAG = -Wall -g
CC = gcc
INCLUDE =
LIBS = -lm
hello:${OBJ} ${CC} ${CFLAGS} ${INCLUDES} -o $# ${OBJS} ${LIBS}
clean:
rm -f *.o core *.core
.cpp.o:
${CC} ${CFLAGS} ${INCLUDES} -c $<
Whenever I run make I get the following error
make
Makefile:13: * missing separator. Stop.
Where should I put a separator?
The problem is in line 13: a tab is missing before the rm command (you put some spaces, but instead a tab must be put before each command).
Some further suggestions for a good Makefile:
Better to add
.PHONY:clean
Better to use -Wextra instead of -Wall
A "TAB" character is missing from the beginning of Line 13 in your make file. May be you used spaces instead of TAB

Creating static library in a makefile, using linux g++ compiler

I have simple files:
hello.h , hello.cpp
I have created a makefile in order to generate a static library (libhello.a)
but I'm getting error message , what am I doing wrong?
My code is:
CC = g++
CFLAGS = -Wall -g
utilObjs = hello.o
libhello.a: $(utilObjs)
ar rc $# $(utilObjs)
ranlib $#
hello: hello.o libhello.a
$(CC) $(CFLAGS) hello.o -L ./ -lutil -o $#
hello.o: hello.cpp hello.h
$(CC) $(CFLAGS) -c $>
clean:
rm -rf *.o libhello.a hello
all: hello
.PHONY: all clean
The error message :
g++: fatal error: no input files
compilation terminated
I don't think $> means anything special, change it to $< , which expands to the first prerequisite of the rule. (hello.cpp in this case)

Modifying a makefile

I have the following file from the PARSEC opensource benchmarks, and I want to be able to profile it using gcc. yet as u know i need to raise the -pg flags. yet i am having difficulties doing so. i tried to use a regular g++ -pg -o files.cpp yet it didnt work. i also tried to modify the makefile that infront of the -o i placed a -pg yet it also gave huge errors. So now i am stuck, either I did something wrong or the -pg flags require something special...yet the makefile when executed alone gave me an output which i tested by running and it was successfull! so i am sure the source code is accepted by my compiler
# Makefile for parallel simulated annealer
PREFIX=${PARSECDIR}/pkgs/kernels/canneal/inst/${PARSECPLAT}
TARGET=canneal
LIBS:=$(LIBS) -lm
ifdef version
ifeq "$(version)" "pthreads"
CXXFLAGS+=-DENABLE_THREADS -pthread
endif
endif
all:
$(CXX) $(CXXFLAGS) annealer_thread.cpp -c -o annealer_thread.o
$(CXX) $(CXXFLAGS) rng.cpp -c -o rng.o
$(CXX) $(CXXFLAGS) netlist.cpp -c -o netlist.o
$(CXX) $(CXXFLAGS) main.cpp -c -o main.o
$(CXX) $(CXXFLAGS) netlist_elem.cpp -c -o netlist_elem.o
$(CXX) $(CXXFLAGS) $(LDFLAGS) *.o $(LIBS) -o $(TARGET)
clean:
rm -f *.o $(TARGET)
install:
mkdir -p $(PREFIX)/bin
cp -f $(TARGET) $(PREFIX)/bin/$(TARGET)
Try adding this near the top of the file:
CXXFLAGS+= -pg