4

I've recently been spoiled by using nodemon in a terminal window, to run my Node.js program whenever I save a change.

I would like to do something similar with some C++ code I have. My actual project has lots of source files, but if we assume the following example, I would like to run make automatically whenever I save a change to sample.dat, program.c or header.h.

test: program sample.dat
    ./program < sample.dat

program: program.c header.h
    gcc program.c -o program

Is there an existing solution which does this?

(Without firing up an IDE. I know lots of IDEs can do a project rebuild when you change files.)

tshepang
  • 12,111
  • 21
  • 91
  • 136
andrewffff
  • 579
  • 2
  • 6
  • 2
    If you're on linux you can use a bash script and `inotifywait`. – Dan Sep 24 '12 at 17:51
  • Here's an alternative build system that has a pretty nice monitor mode: http://gittup.org/tup/ just do `tup monitor -a -f` – leafo Feb 04 '13 at 05:30
  • I think this question is a duplicate of http://stackoverflow.com/questions/1515730/is-there-a-command-like-watch-or-inotifywait-on-the-mac, or, in the very least the fswatch answer also answers this question: http://stackoverflow.com/questions/1515730/is-there-a-command-like-watch-or-inotifywait-on-the-mac#answer-13807906 – Nathan Nov 19 '13 at 16:42

1 Answers1

5

If you are on a platform that supports inotifywait (to my knowledge, only Linux; but since you asked about Make, it seems there's a good chance you're on Linux; for OS X, see this question), you can do something like this:

inotifywait --exclude '.*\.swp|.*\.o|.*~' --event MODIFY -q -m -r . |
while read
do make
done

Breaking that down:

inotifywait

Listen for file system events.

--exclude '.*\.swp|.*\.o|.*~'

Exclude files that end in .swp, .o or ~ (you'll probably want to add to this list).

--event MODIFY

When you find one print out the filepath of the file for which the event occurred.

-q

Do not print startup messages (so make is not prematurely invoked).

-m

Listen continuously.

-r .

Listen recursively on the current directory. Then it is piped into a simple loop which invokes make for every line read.

Tailor it to your needs. You may find inotifywait --help and the manpage helpful.


Here is a more detailed script. I haven't tested it much, so use with discernment. It is meant to keep the build from happening again and again needlessly, such as when switching branches in Git.

#!/bin/sh
datestampFormat="%Y%m%d%H%M%S"
lastrun=$(date +$datestampFormat)
inotifywait --exclude '.*\.swp|.*\.o|.*~' \
            --event MODIFY \
            --timefmt $datestampFormat \
            --format %T \
            -q -m -r . |
while read modified; do
    if [ $modified -gt $lastrun ]; then
        make
        lastrun=$(date +$datestampFormat)
    fi
done
Community
  • 1
  • 1
Keith Pinson
  • 7,835
  • 7
  • 61
  • 104