Quantcast
Channel: Makefile to build and test a C program - Code Review Stack Exchange
Viewing all articles
Browse latest Browse all 3

Answer by J_H for Makefile to build and test a C program

$
0
0

specification

make shalt build ...

Writing down requirements in English can be very helpful, keep doing it.But please spell it "shall".In KJVit appears fifteen hundred times, in fourteen hundredof them next to "thou".But "thou" is going to look a little funny in a modern spec.

conventional targets

make tclean

This is a pretty OK target name, you can certainly keep it.

Consider adopting a more broadly used target name seenin other packages, such as clean-all or very-clean.Then even without consulting documentation, a maintenanceengineer will immediately understand that this is "more destructive"and should take care, perhaps should even consult the docs or thesource or use make -n, before blindly plunging ahead with it.

OTOH these five PHONYs are perfect:

  • all
  • valgrind
  • benchmark
  • test
  • clean

standard

CFLAGS += -std=gnu2x

I know, we're using GCC.And maybe there is a good reason for needing this.But for new projects you might consider habituallyasking for ISO compliance, e.g. c17 or c2x.Go with it till you hit a speedbump that makes gnu2xlook attractive. And then you'll be able to write downa comment for future maintainers explaining whichGNU feature we're relying on.

Generally the "pedantic plus others" looks great.It's unclear to me why TEST_CFLAGS drops most of them.And I assume there was some "sanitize" trouble.

surprising switches

RM = /bin/rm -rMKDIR = /bin/mkdir -p...clean:    $(RM) $(TARGET) $(OBJ_DIR)

Please don't do that.

I suppose the -p is harmless enough.But that -r is a land mine waiting to go off.This is aPOLAviolation.Down at the call site (the clean recipe) we shouldbe explicitly supplying a -r recursive argument,for clarity to anyone working with this.Hiding it way at the top gives misleading signalsto someone reading the recipe.

OTOH you might consider putting repeated flagsinto VALGRIND or VALGRIND_FLAGS.

Also, please don't hardcode full pathnames; prefer to use $PATH.On my ubuntu jammy server, it happens that /bin is symlinkeddown into /usr/bin. But there are lots of machines where /binis on the root filesystem so it's available during fsckbefore /usr has been mounted.There's just no reason to include a full pathname.

propagate the dep

Rather than hardcoding the binary name in a bash script

benchmark: $(TARGET)    ./benchmark > log.txt

you might consider writing ./benchmark $(TARGET) > log.txt,and then have bash pick it out from argv.

test deps

reduce the duplication that the test target has

Yeah, I agree, that does look kind of nightmarish.

First thought on this is to simply throw *.o into a test.a archive.Including common.o.And then build executable binaries as needed.

But then we have the {FEOF, RESIZE_FBUF, ALLOC_AND_APPEND_LINE}stuff to worry about.Maybe that doesn't quite belong here?Maybe deal with it in .c and .h source code?And then the Makefile need only worry about these objects:

  • readlines_fread_test_failure_feof.o
  • readlines_fread_test_failure_resize_fbuf.o
  • readlines_fread_test_failure_alloc_and_append_line.o

It would be simple to write rules to build the associated executables.

I'm thinking we could have three very short *.c files for those threevariants, which simply #define and then #include the bulk of the source.

Flags like ALLOC_AND_APPEND_LINE appear repeatedly.Trading efficiency for simplicity, would it perhaps make anysense to gather up a list of all flags, and rebuild everythingonce per flag, re-using a single executable name?Ok, prolly not, just a thought.More realistically, perhaps define five option listswith 3 to 4 -D defs in each, and loop over those liststo produce five test run results.


Viewing all articles
Browse latest Browse all 3

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>