Makefile configuration for entire system - c++

As we know, in the appliance when we use the command
make [file-name]
It automatically compiles with some flags:
-ggdb -O0 -std=c99 -Wall - Werror
I need to know in which directory the CS50 edited Makefile is located, because I want to configure my own Makefile for the entire system by which I can make any .cpp file.
When I compile c++ file with make it automatically compiles with g++ but I want to compile .cpp file with clang++ compiler, adding some essential flag such for -g for debugging -O0 for assembly code.
I'm asking how to create a Makefile for that specific reasons, if possible.

Make uses Makefiles in the current directory and Implicit-Rules. You can modify the behavior of implicit rules by changing the variables that those explicit rules use.
For example, to change the compiler for .cpp files, you could set your own CXX variable, either
in the environment (Make uses it):
CXX=clang++ make [file-name]
#OR
export CXX=clang++; make [file-name]
in a local Makefile:
CXX:=clang++
#The implicit rule, which you'll find in the link, takes care of the rest

Related

How do you save links with g++/C++?

I am writing some OpenGL code, and my links to libraries in /usr/lib is getting quite unwieldly:
g++ Application.cpp -lglfw -lGL -lGLEW
I don't want to hunt around/can't remember the exact names of the libraries EVERY TIME i want to complile something, so in my project folder I have a file called linkingsNeeded.txt. That file contains that command and nothing else. Is there a way to save the list of linkings so I can just type
g++ Application.cpp
And not have to deal with manually linking? Say, in the #include section of the CPP file?
Learn to use some build automation tool such as GNU make or ninja.
You'll then edit your Makefile (with make); this could be inspirational and just build your program by typing make. Most source code editors (like GNU emacs) or IDEs can be easily configured to run make with a single keypress.
Of course you want to invoke GCC as g++ -Wall -Wextra -g since you want all warnings and debug info (for the GDB debugger).
Read also How to debug small programs and more about C++, perhaps even the n3337 quasi C++11 standard.

Create Makefile to be used in different environments for C++

I would like to compile and run my program in two different environments. The libraries in both environments are installed on slightly different places, resulting in different makefile-lines:
In makefile A:
CXXFLAGS=-I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I/opt/interp2d/include -std=c++17 -I/opt/splinter/include -I/usr/include/eigen3
In makefile B:
CXXFLAGS=-I$(DIR) -nostindc++ -I~/local_opt/eigen/include/eigen3/ -I~/local_opt/boost/include -I~/local_opt/armadillo/include -flto -fopenmp -O3 -g -march=native -std=gnu++17 -c -I~/local_opt/interp2d/include -std=c++17 -I~/local_opt/splinterp/include -I/usr/include/eigen3
My problem now is that I am developing the program on the first machine, using makefile A, but also deploying it on the second machine. The deployment is done using git.
Every time I do a git pull on the second machine, I have to fix all the paths in the makefile in order to compile the program properly. Nevertheless I still would like to include the makefile in the git repository in order to keep both makefiles at the same level regarding compiling flags and linked libraries.
Thus, is there an easier way to still sync the makefile via git, while using different paths for the libraries and includes?
I think you could solve your problem by conditionally setting the variable CXXFLAGS in a common file (e.g.: config.mk) and by including that file in your makefiles.
The value used for setting the CXXFLAGS variable could, for example, depend on the value of the environment variable HOST:
ifeq ($(HOST),A)
CXXFLAGS = ... # for machine A
else # B
CXXFLAGS = ... # for machine B
endif
Then, include this config.mk makefile in both makefileA and makefileB:
include config.mk
I like this answer, however, I thought I'd mention this for completeness: If you have a lot of different hosts you can do something to the effect of:
include HostConfig_$(HOST).mk
And then create HostConfig_A.mk and HostConfig_B.mk which set host specific flags (Be it directories, etc). This is useful if you are managing a large project with lots of different host-specific variables.
As well, (for smaller projects), you could do something to the effect of:
CXX_INCLUDES_A = ...
CXX_INCLUDES_B = ...
CXX_FLAGS := -I$(DIR) -flto -fopenmp -O3 -g -march=native -std=gnu++17
CXX_FLAGS += $(CXX_INCLUDES_$(HOST))
The traditional answer to this problem is a configure script (see automake, autoconf for widely used framework). After checking out the source you run ./configure --with-eigen=~/local_opt/eigen/include/eigen3/ and it will adjust your Makefiles accordingly (usually generates Makefile from Makefile.in and only Makefile.in is in git).
Note: Properly done you only need to run configure on the first checkout, not on updates. make can generate Makefile again automatially as needed.

can you create a c++ file from an .o object file with makefile?

What I'm trying to do is create a c++ file from an object file but I cannot figure out a way to do so.
INCLUDEDIR = ../headers
CXXFLAGS = -std=c++11 -I $(INCLUDEDIR) -Wall -Wfatal-errors -O2
all:primeFactors.o
primeFactors.o: primeFactors.cpp $(INCLUDEDIR)/primeFactors.h
g++ $(CXXFLAGS) -c $< -o $#
When I try to build this I get
make: *** No rule to make target 'primeFactors.cpp', needed by
'primeFactors.o'. Stop.
which I understand but when I take out the primeFactor.cpp argument I then get told there is nothing to be done with the make file. So is there a way to do this?
In general; no, you cannot do that. An object file (.o file) is the result of the code passing through the compiler front-end (to parse the language) the optimizer (to make it run fast) and the compiler back-end (to produce code that will run on your CPU).
This process is not reversible. You cannot go from compiled code back to source.
can you create a c++ file from an .o object file with makefile?
A makefile will allow you to do that only if you have an underlying tool to do it. make, which uses makefiles to do its job, does not have any built-in mechanisms to pull that off.
Your makefile has a rule for building primeFactors.o.
primeFactors.o: primeFactors.cpp $(INCLUDEDIR)/primeFactors.h
It says that primeFactors.cpp and $(INCLUDEDIR)/primeFactors.h are needed to build primeFactors.o. If you don't have those files, or no rules to build them, there is no way for make to build primeFactors.o.

make not executing correct Makefile

I should preface this by saying I am very new to Makefiles.
I created the following Makefile:
all: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
I am trying to make sure that -ligraph is included. However, when I type "make", I get the following output: "c++ -c -o tiling_graph.o tiling_graph.cpp"
Why is it not using the Makefile that I created in the current directory? I have tried using "make -f Makefile" and "make --file=Makefile" but none of these are working.
Also, right after I first made the Makefile, it worked correctly. The output after typing make was
"g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph"
I executed ./tiling_graph and it was successful.
Then I edited tiling_graph.cpp, ran make again, and the output was "c++ -c -o tiling_graph.o tiling_graph.cpp" and has been ever since.
I would really appreciate any help. Thanks!
A simple way to think about a make rule:
target: dependency list
commands to make the target
is that it is a recipe for making the file called target from the list of files in the dependency list. Since make can see the file system, it can tell whether any file in the dependency list is newer than the file named target, which is its signal for recreating target. After all, if none of the dependencies have changed, the target must be up-to-date.
Note that make knows quite a lot about how to build files. In particular, it has a lot of built-in "pattern" rules, so it knows, for example, how to make an object file (prog.o) from a C++ source file (prog.cpp) or from a C source file (prog.c) or many other things. So you only need to actually write a makefile when you have other requirements, like a library (and even then you could just add that to an environment variable, but the makefile is better).
Now, you don't actually want to build a file called all. You want to build a file called tiling_graph. So the correct make rule would be:
tiling_graph: tiling_graph.o
g++ -o tiling_graph tiling_graph.o -L/usr/local/lib -ligraph
Since make already knows how to create tiling_graph.o, it can actually figure out how to make tiling_graph from tiling_graph.cpp.
So where does this all come from? The usual way to use all is:
all: program1 program2 program3
which tells make that the all target requires program1, program2 and program3. So if you need to build all three of those programs, the all rule would let you just do one make command. Since there is no file named all, that's a "phony" target and (with gnu make, at least) it should be declared as a phony target:
all: tiling_graph
.PHONY: all
But you really don't need that if you just want to build one program.
When you just type make (as opposed to make target), make chooses the first target in the makefile. So if you put the thing you usually want to build first, you'll save some typing.

Makefile for compiling a number of .cpp and .h into a lib

I am running Windows 7 with gcc/g++ under Cygwin. What would be the Makefile format (and extension, I think it's .mk?) for compiling a set of .cpp (C++ source) and .h (header) files into a static library (.dll). Say I have a variable set of files:
file1.cpp
file1.h
file2.cpp
file2.h
file3.cpp
file3.h
....
What would be the makefile format (and extension) for compiling these into a static library? (I'm very new to makefiles) What would be the fastest way to do this?
The extension would be none at all, and the file is called Makefile (or makefile) if you want GNU Make to find it automatically.
GNU Make, at least, lets you rely on certain automatic variables that alone give you control over much of the building process with C/C++ files as input. These variables include CC, CPP, CFLAGS, CPPFLAGS, CXX, CXXFLAGS, and LDFLAGS. These control the switches to the C/C++ preprocessor, compiler, and the linker (the program that in the end assembles your program) that make will use.
GNU Make also includes a lot of implicit rules designed to enable it automatically build programs from C/C++ source code, so you don't [always] have to write your own rules.
For instance, even without a makefile, if you try to run make foobar, GNU Make will attempt to first build foobar.o from foobar.c or foobar.cpp if it finds either, by invoking appropriate compiler, and then will attempt to build foobar by assembling (incl. linking) its parts from system libraries and foobar.o. In short, GNU Make knows how to build the foobar program even without a makefile being present -- thanks to implicit rules. You can see these rules by invoking make with the -p switch.
Some people like to rely on GNU Make's implicit rule database to have lean and short makefiles where only that specific to their project is specified, while some people may go as far as to disable the entire implicit rule database (using the -r switch) and have full control of the building process by specifying everything in their makefile(s). I won't comment on superiority of either strategy, rest assured both do work to some degree.
There are a lot of options you can set when building a dll, but here's a basic command that you could use if you were doing it from the command line:
gcc -shared -o mydll.dll file1.o file2.o file3.o
And here's a makefile (typically called Makefile) that will handle the whole build process:
# You will have to modify this line to list the actual files you use.
# You could set it to use all the "fileN" files that you have,
# but that's dangerous for a beginner.
FILES = file1 file2 file3
OBJECTS = $(addsuffix .o,$(FILES)) # This is "file1.o file2.o..."
# This is the rule it uses to assemble file1.o, file2.o... into mydll.dll
mydll.dll: $(OBJECTS)
gcc -shared $^ -o $# # The whitespace at the beginning of this line is a TAB.
# This is the rule it uses to compile fileN.cpp and fileN.h into fileN.o
$(OBJECTS): %.o : %.cpp %.h
g++ -c $< -o $# # Again, a TAB at the beginning.
Now to build mydll.dll, just type "make".
A couple of notes. If you just type "make" without specifying the makefile or the target (the thing to be built), Make will try to use the default makefile ("GNUMakefile", "makefile" or "Makefile") and the default target (the first one in the makefile, in this case mydll.dll).