makefile to run the code it compiles - c++

If I have a code that will run, call it main.cpp, and the executable is r.exe, then I write a makefile with the following target:
compile:
g++ -std=c++11 main.cpp -o r
The executable, r.exe takes as two arguments i.txt, o.txt. How do I add a second target to the makefile such that I can run the following command, and see the program execute:
make run i.txt o.txt
I have tried adding a second target to the makefile:
run:
r.exe $1 $2
for instance, but make declares: "'r' is up to date" and "nothing to be done for 'i.txt', ... etc."
I have also tried searching for a while now, but 'make', 'run' and 'variables' or 'arguments' have, essentially, a search firewall of unrelated content.

You can't pass arguments to make like that. The command make run i.txt o.txt would attempt to build the rules run, i.txt, and o.txt.
What you could instead to is use a variable:
run:
r.exe ${ARGS}
make run ARGS="i.txt o.txt"
Side-note, rules should make the files that they say they do. So you really would want your compile rule to look like:
r.exe : main.cpp
g++ -std=c++11 $^ -o $#
compile : r.exe
.PHONY : compile

Related

I need some Makefile wizardry explained

So I was following one of the Makefile by example tutorials (cause I'm fairly fresh) and thats how I ended up here.
files = src/main.cpp src/compiler.cpp
all: $(files)
%.cpp:
echo $#
And this for some reason produces this
echo src/compiler.cpp
src/compiler.cpp
echo all.cpp
all.cpp
g++ -c -o all.o all.cpp
cc1plus: fatal error: all.cpp: No such file or directory
compilation terminated.
make: *** [<builtin>: all.o] Error 1
I don't see any refrences to g++ at all and for some reason it's getting called. The idea here was to use it to compile all my stuff from /src to .o files in /obj then produce a binary. Any ideas on how to do that or explanations on how to not call g++ without even referencing it in the makefile is highly appreciated.
It's being called because you have created a target all, and you haven't given make any recipe to build that target. So, make looks through its built-in rules and it sees that it knows how to build a program x given a prerequisite x.cpp. Well, make knows how to build a all.cpp, because you provided a rule that tells it how to build any .cpp file.
So first it runs the rule to build all.cpp, then it runs its built-in rule to build a target all from that all.cpp (which doesn't exist because your rule that told make how to build %.cpp doesn't actually create that target).
If you don't actually want to build a target all, then you should declare it to be a phony target:
.PHONY: all

C++ Makefile Which Uses The Correct Source File?

I want to type the following:
make fileName.cpp
To compile, and then to execute:
./fileName
If I have a make file like this:
commandToCompileFileName:
g++ -o fileName fileName.cpp
Then I can do:
make commandToCompileFileName
And then:
./fileName
I want to be able to do this with different files, without having to write a different prompt for each of them in makefile. So something would be in place of
commandToCompileFileName
in the makefile that would just compile whatever I type in after make, and the executable would just be named the same minus the .cpp.
This page in the very first paragraph describes precisely what I want and probably answers my question, yet I couldn't figure it out after playing around with '$#' and '$<'.
You actually do not need a Makefile to do this: make ships with a whole bunch of default rules, one of which creates programs from .cpp files.
In other words, just type make fileName, and be happy :)
(if you want to custom compilation flags, see the CXXFLAGS and LDFLAGS variables)
I use the following:
run_% : %
#echo "---- running $< ----"
$<
.PHONY : run_%
So that when you do, for example, make run_test it builds test target and runs it.

make with argument for different executable name

I have a c++ codebase. I have a CMakeLists. When I run make, it creates the binary myexec.
I would like to be able to run, say, make -- v2, and that it creates the exact same binary, but called myexec_v2. It would be great if it did not have to recompile everything to create this binary, but only the modified files.
How can I do that?
myexec myexec_v2: $(prerequisites)
#echo compile $#
observe:
$ make myexec
compile myexec
$ make myexec_v2
compile myexec_v2
if nothing else is needed to compile myexec_v2 then you are done.
see here for more information: https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html
here is a slightly more advanced version
myexec myexec_v2: myexec%: $(prerequisites)
#echo compile $# $*
this is called a static pattern rule. the myexec% in the middle is called the target pattern. in this example we only use it to get the so called stem. the stem would be _v2 and the variable $* expands to the stem.
for more information: https://www.gnu.org/software/make/manual/html_node/Static-Usage.html
observe:
$ make myexec
compile myexec
$ make myexec_v2
compile myexec_v2 _v2
now you can use either $# or $* in the recipe to modify the behaviour to compile on or the other.
but if you want to do if branches in the recipe read this first: Basic if else statement in Makefile

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.

Make GNU make use a different compiler

How can I make GNU Make use a different compiler without manually editing the makefile?
You should be able to do something like this:
make CC=my_compiler
This is assuming whoever wrote the Makefile used the variable CC.
You can set the environment variables CC and CXX, which are used for compiling C and C++ files respectively. By default they use the values cc and g++
If the makefile is written like most makefiles, then it uses $(CC) when it wishes to invoke the C compiler. That's what the built-in rules do, anyway. If you specify a different value for that variable, then Make will use that instead. You can provide a new value on the command line:
make CC=/usr/bin/special-cc
You can also specify that when you run configure:
./configure CC=/usr/bin/special-cc
The configuration script will incorporate the new CC value into the makefile that it generates, so you don't need to manually edit it, and you can just run make by itself thereafter (instead of giving the custom CC value on the command line every time).
Many makefiles use 'CC' to define the compiler. If yours does, you can override that variable with
make CC='/usr/bin/gcc'
Use variables for the compiler program name.
Either pass the new definition to the make utility or set them in the environment before building.
See Using Variables in Make
Makefile:
#!MAKE
suf=$(suffix $(src))
ifeq ($(suf), .c)
cc=gcc
else
ifeq ($(suf), .cpp)
cc=g++
endif
endif
all:
$(cc) $(src) -o $(src:$(suf)=.exe)
clean:
rm *.exe
.PHONY: all clean
Terminal:
$ make src=main.c