0

The problem: I want to run only a script (e.g. run.sh), which will decide for me if make should be called (and call it if needed) and then run the executable.


My project has only one file, that is main.c. However, just the linking makes me wait a bit, something that I do not like when I debug and I am eager for the program to run. I would like something like this into run.sh:

#!/bin/bash
if[ main.c has changed from the last time make was called] then
  make > compile.txt
fi
./a.out

so that the make is called only if main.c is modified. By modified, one could take that the timestamp is changed (even if that may not the actual criterion). Is this feasible?


If so, I saw this answer, which made me think that every time I enter the body of the if statement that calls make, a copy of main.c would be created, or the timestamp of the file would be stored (in a file maybe), so that the next time the script runs, it will restore that information and check the if condition to see if timestamps differ. So, the second question is, how to do it?

Community
  • 1
  • 1
gsamaras
  • 71,951
  • 46
  • 188
  • 305
  • 1
    `make` will only recompile if you've modified `main.c` (under the assumption that your program consists of just `main.c`). And it doesn't take long for `make` to run and do nothing — or it shouldn't. So, what's the problem you're trying to solve? Why would the modification time on `main.c` change if you haven't changed the content of the file? Have you got some broken rule in your makefile such that the program is linked every time even if you haven't changed anything? (See [`make` compiles some programs every time even if they are just compiled](http://stackoverflow.com/questions/31151069/)) – Jonathan Leffler Jul 01 '15 at 13:55
  • @JonathanLeffler yes, it doesn't. I just say that because I saw the answer that uses touch. I said that for simplicity. If the file is modified though, the timestamp would surely differ, that's why I had this idea. Thanks for the comment. I will edit. Better now? :) – gsamaras Jul 01 '15 at 13:57
  • 1
    (1) If you're debugging and changing your code, you need to rebuild to see the effect of the changed code. That means you need to relink. (2) If `main.c` has not changed, then your program will not be relinked unless there is a bug in your `makefile` that forces the relink when it is not needed. If (2) is your problem, fix your `makefile`. If (1) is your problem, why are you saving the edits before you're ready to rebuild the program. Or why don't you just run `a.out` directly instead of running your script. Basically, you seem to have a methodological problem; you're misusing `make`… – Jonathan Leffler Jul 01 '15 at 14:05
  • Maybe you are right @JonathanLeffler, thanks for pointing out. :) – gsamaras Jul 01 '15 at 14:14
  • I note that the problem described in the companion question, [SO 31164161](http://stackoverflow.com/questions/31164161) is precisely of the same type as in [`make` compiles some programs every time even if they are just compiled](http://stackoverflow.com/questions/31151069/), and a number of other earlier questions. – Jonathan Leffler Jul 01 '15 at 16:25
  • Good catch @JonathanLeffler. – gsamaras Jul 01 '15 at 16:57
  • 1
    Call **always** make. If `main.c` has to be recompiled, it will be! Make does the work best on detecting if some file has been modified, so why to put that in one shell script to decide if we call to make. Just call it, and let it decide! – Luis Colorado Jul 02 '15 at 08:19
  • @LuisColorado you are right, this is the right approach! – gsamaras Jul 02 '15 at 10:41

1 Answers1

3

Simply

#!/bin/bash

if [ a.out -ot main.c ]; then
    make > compile.txt
fi

./a.out

-ot is equivalent to older than

However, this behaviour is expected from make itself. I would prefer a makefile like

CC = gcc
CFLAGS = -Wall -W

main: main.c
    $(CC) $(CFLAGS) -o $@ $^

The main rule would run only if main.c is updated after last make

Shreevardhan
  • 12,233
  • 3
  • 36
  • 50
  • Note that while Bash and Korn shell support `-ot` in a test, POSIX does not require such support and POSIX-compliant shells might not then work. This shouldn't be an issue since the script starts `#!/bin/bash`, but … – Jonathan Leffler Jul 01 '15 at 14:18
  • Thanks! However, I may have to change my Makefile, because I am not sure what am I missing, but that's another question. I would appreciate if you could explain the last two symbols here: `-o $@ $^`. – gsamaras Jul 01 '15 at 14:23
  • That `main: main.c` rule is essentially the same as the built in `%: %.c` rule that make already has (which uses `$(CFLAGS)` and `$(CC)` already) so that rule definition isn't necessary so the makefile for a single-file C program like this can just be the `CFLAGS` definition (and `CC` if necessary but on many systems the default of `cc` will be `gcc` anyway). – Etan Reisner Jul 01 '15 at 14:27
  • Thanks @EtanReisner, follow-up question here: http://stackoverflow.com/questions/31164161/avoid-linking-and-compiling-in-make-if-not-needed – gsamaras Jul 01 '15 at 14:27
  • @EtanReisner Yes, we don't even need to create a makefile, just running `make main` in the working directory will do. – Shreevardhan Jul 01 '15 at 14:40
  • Correct, you don't even need a makefile at all if you don't need to set any values (or don't mind putting them on the command line). – Etan Reisner Jul 01 '15 at 14:43