building the same file for different targets with different options - c++

I have one "helper" file included in two "main" files which are built into two executables with the same makefile. I have debug print statements in the helper file. I want the print statements to actually be printed in one executable, but not the other. Is there a way to do it? Right now I have the following, and I was hoping to compile with DEBUG_PRINT defined for one executable but not the other, but I don't see how.
main1.cpp:
#include "helper.h"
...
main2.cpp:
#include "helper.h"
...
helper.cpp:
#ifdef DEBUG_PRINT
cout << "here is a debug message" << endl;
#endif
Makefile:
build: main1 main2
main1: main1.o helper.o
g++ -g -o main1 main1.o helper.o
main2: main2.o helper.o
g++ -g -o main2 main2.o helper.o
%.o: %.cpp
gcc -g -c $<

You will need two different object files (main1-helper.o and main2-helper.o) and target-specific compiler flags:
main1: CXXFLAGS=-DDEBUG_PRINT
%.o: %.cpp
gcc $(CXXFLAGS) -g -o $# -c $<
Note: This leaves you with the problem of generating main1-helper.o from helper.o. There are a few ways to solve this; however, you might be more comfortable using automake from the start instead of rolling your own solutions.

Related

Compiling multiple c++ files doesn't work with certain file names

I am trying to compile multiple .cpp files, using a Makefile with make. I have a .cpp file containing the main function, in the other .cpp file a basic class (for every doubt I'll put all the code i'm using down here).
Example of names used to make it compile or to make it not compile:
-it works by having them named "prova.cpp"(contains the main function) and "pa.cpp"(contains the class) (below the commands done by the Makefile)
gioele#GioPC-U:~/Dev/Cpp/Exercises/666prova$ make
g++ -g -Wall -c src/prova.cpp -o obj/prova.o
g++ -g -Wall -c src/pa.cpp -o obj/pa.o
g++ -g -Wall obj/prova.o -o bin/provaBin
-it doesn't work by having them named "ciao.cpp"(contains the main function) and "pa.cpp"(contains the class)
gioele#GioPC-U:~/Dev/Cpp/Exercises/666prova$ make
g++ -g -Wall -c src/pa.cpp -o obj/pa.o
g++ -g -Wall -c src/ciao.cpp -o obj/ciao.o
g++ -g -Wall obj/pa.o -o bin/provaBin
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x24): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Makefile:15: bin/provaBin] Errore 1
I think the problem is with the order of the files inside the Makefile. When it doesn't work is because is trying to get a binary from the .o without the main function. No idea on how to resolve.
The file with the main method:
#include <iostream>
int main() {
std::cout << "Hello world!" << std::endl;
return 0;
}
The class file:
class Class {
public:
int x;
int y;
};
The Makefile (still learning to work with Makefiles, probably the problem is here, any advice to make a Makefile of this kind better is appreciated, or if I am using something not properly):
CC=g++
CFLAGS=-g -Wall
OBJ=obj
SRC=src
BINDIR=bin
BIN=$(BINDIR)/provaBin
SRCS=$(wildcard $(SRC)/*.cpp)
OBJS=$(patsubst $(SRC)/%.cpp, $(OBJ)/%.o, $(SRCS))
all: $(BIN)
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $< -o $#
$(OBJ)/%.o: $(SRC)/%.cpp
$(CC) $(CFLAGS) -c $< -o $#
clean:
$(RM) $(BINDIR)/* $(OBJ)/*
Thank you in advance.
You can fix this by changing one character.
In this rule:
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $< -o $#
the prerequisite list $(OBJS) expands to a list of object files, such as prova.o pa.o or pa.o ciao.o. You want Make to incorporate that list into the linking command, like this:
g++ -g -Wall prova.o pa.o -o bin/provaBin
But the automatic variable $< expands to only the first item in the prerequisite list. If the first item is an object file that does not contain the main() function, such as pa.o, the linker will complain that main() is missing. (If it is an object file that contains main(), such as prova.o, then you will not get that error, but you may still have problems.)
The solution is to use the automatic variable $^, which expands to the complete list of prerequisites:
$(BIN): $(OBJS)
$(CC) $(CFLAGS) $^ -o $#

makefile issues multiple definitions

I'm learning how to use makefile however after a few hours of research and still being stuck I just can not manage to resolve what is wrong with my makefile:
output: main.o module.o
g++ main.o module.o -o output
main.o: module.cpp module.h
g++ -c module.cpp
module.o: module.cpp module.h
g++ -c main.cpp
my main.cpp file has #include "module.cpp"
my module.cpp file has #include "module.h"
after attempting to execute my makefile i get lots of "multiple definitions of" and "undefined references"
help will be highly appreciated
p.s code in codeblocks works flawlessly, that's why i am so confused. i am using mingw32-make
You are getting "multiple definition errors" becasue you are linking module.o and main.o together but your main.cpp already includes module.cpp. Do not include module.cpp in main.cpp (i.e.: remove the #include "module.cpp directive inside main.cpp). Since main.o won't depend then on module.cpp, you should remove that prerequisite from the main.o rule as well.
Also, consider using GNU Make's automatic variables instead of hard-coded filenames and predefined variables (i.e.: CXX) instead of hard-coded commands (i.e.: g++):
output: main.o module.o
$(CXX) $^ -o $#
main.o: main.cpp module.h
$(CXX) -c $<
module.o: module.cpp module.h
$(CXX) -c $<
Or even better, rely on the predefined pattern rule for generating .o files from .cpp files:
output: main.o module.o
$(CXX) $^ -o $#
main.o: module.h
module.o: module.h
Note that failing to provide the last two lines will cause main.o and module.o to be still up-to-date (i.e.: not being rebuilt) even though module.h changes.
Thanks to implicit rules in Makefiles, this should be enough:
output: main.o module.o
g++ main.o module.o -o output
The implicit rules allows make to know how to create .o files from .cpp files.
But this could be even simpler:
output: main.o module.o
$(CXX) -o $# #^
$(CXX) is your C++ compiler, usually g++
$# is an automatic variable of the target (value before the colon)
#^ is an automatic variable of the prerequisites (values after the colon)

C++ - Makefile using g++

I have made a Makefile for my CMSC 202 course project, 'Blackjack'. It does everything I need it to and it works perfectly. You may be asking why I posted here then, this is because I have no idea how it works and I didn't use any other resources but myself to create it.
Here is my Makefile code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created at the end
EXEC = Proj2.out
# The flags to use for compilation
FLAGS = -Wall
# The code compiler to use for compilation
CC = g++
# Perform action on all object files (May or may not exist)
all: $(OBJECTS)
$(CC) $(FLAGS) -o $(EXEC) $(OBJECTS)
Here is the terminal output when I call make in the terminal.
g++ -c -o Proj2.o Proj2.cpp
g++ -c -o Blackjack.o Blackjack.cpp
g++ -c -o Deck.o Deck.cpp
g++ -c -o Card.o Card.cpp
g++ -c -o Hand.o Hand.cpp
g++ -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Can anyone tell me how the .o files are being compiled? It does not look like they are being prompted to be compiled with that g++ -c -o $.o $.cpp command anywhere in the Makefile. Nor did I state to use any .cpp files.
Thank you in advance for your help.
Edit
Thanks to all your great help, this is now the terminal output I receive when using make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
Thank you so much to all of you who have contributed.
Make has a set of implicit rules (see here for a reference). For instance
Compiling C++ programs
`n.o' is made automatically from `n.cc' or `n.C' with a command of the form
`$(CXX) -c $(CPPFLAGS) $(CXXFLAGS)'.
Most make's will also use this rule for .cpp files.
When make sees there's a x.o requirement for one of your targets, it will try to see if it can generate x.o using implicit rules, and in your case find it can do it starting from a .cpp file.
This Makefile uses implicit rules which are a great way to reduce duplication.
By default the first target will be built, here all. It depends on a number
of object files listed in a variable $OBJECTS, e.g. Proj2.o who's
dependencies aren't listed in the Makefile. Now if make sees an input file in the current directory
with a matching name, e.g. Proj2.cpp it will try
to build Proj2.o from it (there are other implicit rules for sources in
other languages). Proj2.o would then be built by default with the command
$(CXX) $(CXXFLAGS) -c -o Proj2.o
where $(CXX) the name of the C++ compiler (g++ in your case).
The explicit build step for all assembles all the object files into the
target executable.
Looking at above build command you'll notice a small problem in your Makefile. Since the flags to the C++ compiler are given in a variable FLAGS and not the standard CXXFLAGS no warnings will be emitted when building the object files. Using the standard name would fix this (you do want warnings, maybe even more than -Wall gives you).

C++ - Makefile Good Practice

I have a Makefile that works for how I'm using it, but will anyone tell me if what I'm doing is good practice? Or if there is a better, cleaner or more efficient way to achieve the goal I am reaching?
Here is my Makefile Code.
# Object files to either reference or create
OBJECTS = Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
# The executable file that will be created
EXEC = Proj2.out
# The c++ flags to use for compilation
CXXFLAGS = -Wall
# The c++ compiler to use for compilation
CXX = g++
# This section is called on 'make'
# Will call compile, and then call clean
all: compile clean
# Perform action on all object files (May or may not exist)
# The makefile will implicitly compile all .o files needed
# Will also compile them into the EXEC file listed
compile: $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $(EXEC) $(OBJECTS)
# This section is called after compilation is completed
# This will clean all existing .o files listed in the directory
clean:
rm -f *.o
Here is the terminal output when I call make.
g++ -Wall -c -o Proj2.o Proj2.cpp
g++ -Wall -c -o Blackjack.o Blackjack.cpp
g++ -Wall -c -o Deck.o Deck.cpp
g++ -Wall -c -o Card.o Card.cpp
g++ -Wall -c -o Hand.o Hand.cpp
g++ -Wall -c -o Player.o Player.cpp
g++ -Wall -o Proj2.out Proj2.o Blackjack.o Deck.o Card.o Hand.o Player.o
rm -f *.o
Is it good practice to use a Makefile like this? Specifically, am I doing the cleaning part of my Makefile correctly?
You should not make all depend on clean at all. By doing this you are ensuring that every time you run make, you have to recompile everything. If you want to do that then using make is itself useless: just write a shell script that compiles and links your code.
The clean target should be a separate target and if you want to clean your workspace you run make clean explicitly.
The other problem with your makefile is that the link rule lists compile as the target, but it builds $(EXE). It's almost never a good idea to have a rule create a file which is not exactly the target you told make it would build. To ensure this, always use $# as the target to generate. Rewrite it like this:
compile: $(EXE)
$(EXE): $(OBJECTS)
$(CXX) $(CXXFLAGS) -o $# $^

Projecting the makefile for debug/release configurations

Need your help with projecting the makefile. So, what I have and what I want to get. I need to build two executables. Source code is common. Preprocessor macros control differences for both exes, for example, in main.cpp:
#if PROJECT_TYPE==FTP
std::cout << "FTP" << std::endl;
#else
std::cout << "SFTP" << std::endl;
#endif
Differences aren't only in source code but also in additional libraries that used for linking:
FTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libftpclient.a -l:libftplib.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libws2_32.a
SFTP_LDFLAGS= -static-libstdc++ -static-libgcc -s -L $(ROOT_DIR)/lib/Release -l:libboost_thread-mgw46-mt-1_49.a -l:libcommon.a \
-l:libfile.a -l:libfilesearcher.a -l:libdbclient.a -l:libsqlite3.a -l:libscheduler.a -l:libsftpclient.a -l:libws2_32.a -l:libssh.dll
Also I want to create debug/release build targets with own CXXFLAGS and output directories, so in result to get following:
TARGETS= ftp_auto_backup sftp_auto_backup
Screenshot of dirs tree here.
I want use implicit rule for compiling, smth like this:
%.o: %.cpp
$(CXX) -c $(CXXFLAGS) $< -o $(O_DIR)/$#
But how can I specify separate O_DIR for each target int $(TARGETS) and for each build configuration? My main problem is in this step. I can paste all the makefile that I have at this moment, but it still won't build anything. Just in case here it is: http://pastebin.com/jjB5Ld1s
Thanks in advance, guys!
There are many ways to do this. The simplest seems to be by means of recursive Make. (I am not among those who think that this is always a bad idea.)
.PHONY: release
release: VERSION=Release
.PHONY: debug
debug: VERSION=Debug
release debug:
#$(MAKE) -S ftp_auto_backup sftp_auto_backup VERSION=$(VERSION)
Now to make the executables, given VERSION. We could handle the two project types with another layer of recursion, but we can do without it (and I won't go into detail about preprocessor macros and compiler/linker flags, since you seem to know about them already-- I'll spell them out if you like):
OBJ_LIST = foo.o bar.o baz.o
ftp_auto_backup: PROJECT_TYPE=FTP
ftp_auto_backup: $(addprefix $(VERSION)/ftp_auto_backup/obj/, $(OBJ_LIST))
sftp_auto_backup: PROJECT_TYPE=SFTP
sftp_auto_backup: $(addprefix $(VERSION)/sftp_auto_backup/obj/, $(OBJ_LIST))
ftp_auto_backup sftp_auto_backup:
#g++ -Wall $^ -o $# with various flags
$(VERSION)/ftp_auto_backup/obj/%.o: %.cc
#g++ -Wall -c $< -o $# with various flags
$(VERSION)/sftp_auto_backup/obj/%.o: %.cc
#g++ -Wall -c $< -o $# with various flags