milanHrabos
milanHrabos

Reputation: 1965

How to construct makefile to compile AND run the binary?

I would like to compile and run in one rule. Now I have :

CC = g++

%: %.o
    $(LINK.c) $^ -o $@; 
    ./$@

But the make only compiles the source to binary, but do not run it. How to construct make to do this in one step?

Having file foo.cpp. Applying the makefile:

user@Host:~/Desktop/bin/2$ make foo
g++     foo.cpp   -o foo
user@Host:~/Desktop/bin/2$ 

Compilation is done. After which I want to run it (and see the output of that program), but that will not happen.

EDIT: Please use patterns, I will not accept solution with explicit filenames.

Upvotes: 0

Views: 1905

Answers (1)

Dirk is no longer here
Dirk is no longer here

Reputation: 368181

I suspect you are being tripped up by the implicit rules in make. It already knows how to a) make an object file from a C++ source and b) how to link.

So I suggest to rewrite the Makefile to be more explicit. One example would be

all:
    g++ -c hello.cpp
    g++ -o hello hello.o
    ./hello

where I redefine the default all target and (for simplicity) make the steps explicit. With a trivial file such as this

#include <iostream>

int main() {
  std::cout << "Hello, world." << std::endl;
  exit(0);
}
    

it works as expected:

$ make
g++ -c hello.cpp
g++ -o hello hello.o
./hello
Hello, world.
$

You can refine and adapt as needed, i.e. with the $^ and $@ variables as needed.

Edit: Here is a second variant. It does "nothing" as building a executable from (same-named) source file is known to make. So here I just do three things:

  1. establish the names of all sources
  2. derive the names of all programs from all sources
  3. tell the all target to run the programs one-by-one

The following (minimal) Makefile does that:

sources :=  $(wildcard *.cpp)
programs := $(sources:.cpp=)

all:    $(programs)
        ./$^

Works as expected:

$ ls -l
total 8
-rw-rw-r-- 1 edd edd 94 Nov 15 16:36 hello.cpp
-rw-rw-r-- 1 edd edd 88 Nov 15 17:13 Makefile
$ make
g++     hello.cpp   -o hello
./hello
Hello, world.
$ 

I actually use that very same pattern in an example directory with 18 or so example in this repo.

Edit 2: The above actually run one command over all targets in programs; I copied it from strip invocation where that makes sense. One may to have them all run after they have been built is to use this:

sources :=  $(wildcard *.cpp)
programs := $(sources:.cpp=)

all:    $(programs)
        for p in $(programs); do ./$$p; done

Upvotes: 1

Related Questions