0

I have a makefile:

CFLAGS= -Wall -g

all: ex1.c 
    cc ex1.c -o ex1
    valgrind ./ex1
    cc ex2.c -o ex2
    valgrind ./ex2
    cc ex3.c -o ex3
    valgrind ./ex3

clean:
    rm -f ex1
    rm -f ex2
    rm -f ex3

Is there any way of simplifying this so I do not have to add 3 lines per file (I am expecting ~50 files) and instead I can just insert a number and it will run the commands for that number of files? All of the files will have the same naming scheme /^ex\d{1,}\.c/ and are all in the same directory.

Thank you for your help.

Computer Backup
  • 187
  • 1
  • 3
  • 14

1 Answers1

5

You do not necessarily need loops:

CFLAGS= -Wall -g

ALL_EX=ex1 ex2 ex3

all: $(ALL_EX)

ex%: ex%.c
    $(CC) $(CFLAGS) $@.c -o $@
    valgrind ./$@

clean: ; rm -f $(ALL_EX)

To add another test, all you need is to add another exN to the ALL_EX variable.

Or alternatively, splitting the valgrind invocation from the compilation:

CFLAGS= -Wall -g

ALL_EX=ex1 ex2 ex3
TEST_EX=$(ALL_EX:ex%=test_ex%)

all: $(TEST_EX)
cmp: $(ALL_EX)

ex%: ex%.c
    $(CC) $(CFLAGS) $@.c -o $@
test_ex%: ex%
    valgrind ./$<

clean: ; rm -f $(ALL_EX)

That way you would also avoid redundant recompilation of the ex*.c files. And most importantly: this way you can parallelize the compilation and the tests with the make -j.

Dummy00001
  • 16,630
  • 5
  • 41
  • 63
  • I definitely approve of separating the `valgrind` run into a separate rule, but why not make it a rule for creating a *bona fide* file, such as one containing valgrind's output? Or if you do not do that, then at least mark the `test_ex%` as `.PHONY`. – John Bollinger Jun 22 '16 at 14:41
  • I'm not making assumption about how OP uses the make or valgrind. I have focused only on the question asked: automating the compilation and testing of many files. – Dummy00001 Jun 22 '16 at 14:46
  • That's fine, but a target whose recipe does not generate the file designated by the target name should be declared `.PHONY`. This has nothing to do with how the OP intends to use the `make` or `valgrind`, and everything to do with defining the correct semantics to `make`. In particular, it's about what to do in the event that the build directory happens to contain a file with the same name as the target. – John Bollinger Jun 22 '16 at 15:16
  • Your rules are missing prerequisites. – 2501 Jun 22 '16 at 15:34
  • Unless the OP explicitly asks for it, I'm not going to burden the answer with the banal nitpicks. – Dummy00001 Jun 22 '16 at 15:35
  • The files won't be updated. This is the main point of make. Op will be confused. – 2501 Jun 22 '16 at 15:36
  • @JohnBollinger, btw, you can't add `test_ex*` targets to `.PHONY` since phony targets never match rules with `%`. – Dummy00001 Jun 22 '16 at 16:00
  • @Dummy00001 what would you recommend? I am working my way through Lean C The Hard Way and am saving each exercise in an appropriately named file. What I want this to be able to do is remove all output files, build the files and test them with valgrind. – Computer Backup Jun 22 '16 at 16:42
  • I hate to mention it, but the compile line should mention CFLAGS: as in cc $(CFLAGS) $@.c -o $@ – TonyB Jun 23 '16 at 05:06
  • @ComputerBackup, if you are still learning, then this would suffice. My personal way of learning is different: first study the underlaying concepts, then learn by doing. Small games are probably the most common starting point for many: learn coding while having some fun. There are plenty of books for the 2D game programming. You can pick many used ones very cheaply. – Dummy00001 Jun 23 '16 at 07:59