2

I have this Makefile:

CFLAGS := $(CFLAGS) -std=c99

shell: main.o shellparser.o shellscanner.o
    $(CC) -o shell main.o shellparser.o shellscanner.o

main.o: main.c shellparser.h shellscanner.h

shellparser.o: shellparser.h

shellparser.h: shellparser.y lemon
    ./lemon shellparser.y

shellscanner.o: shellscanner.h

shellscanner.h: shellscanner.l
    flex --outfile=shellscanner.c --header-file=shellscanner.h shellscanner.l

# Prevent yacc from trying to build parsers.
# http://stackoverflow.com/a/5395195/79202
%.c: %.y

lemon: lemon.c
    $(CC) -o lemon lemon.c

For some reason, on the first run of make, shellparser.o isn't built:

> make
cc -o lemon lemon.c
./lemon shellparser.y
flex --outfile=shellscanner.c --header-file=shellscanner.h shellscanner.l
cc  -std=c99   -c -o main.o main.c
cc  -std=c99   -c -o shellscanner.o shellscanner.c
cc -o shell main.o shellparser.o shellscanner.o
i686-apple-darwin10-gcc-4.2.1: shellparser.o: No such file or directory
make: *** [shell] Error 1
rm shellscanner.c

If I run it again, it then builds it correctly:

> make
cc  -std=c99   -c -o shellparser.o shellparser.c
cc -o shell main.o shellparser.o shellscanner.o

So what do I have out-of-order such that it doesn't build it the first time?

theory
  • 9,178
  • 10
  • 59
  • 129

1 Answers1

1

The first time you try to build, Make doesn’t know that lemon outputs shellparser.c, so it doesn’t try to build it. When you rebuild, shellparser.c does exist, so Make uses it. The solution is to explicitly tell Make that lemon outputs shellparser.c:

diff --git a/Makefile b/Makefile
index bf2655e..d6b288d 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ main.o: main.c shellparser.h shellscanner.h

 shellparser.o: shellparser.h

-shellparser.h: shellparser.y lemon
+shellparser.c shellparser.h: shellparser.y lemon
        ./lemon shellparser.y

 shellscanner.o: shellscanner.h
diff --git a/main.c b/main.c
index 81ec151..4179981 100644
--- a/main.c
+++ b/main.c
@@ -33,7 +33,7 @@ void parse(const char *commandLine) {
 }

 // Borrowed from http://stackoverflow.com/a/314422/79202.
-char * getline(void) {
+char * my_getline(void) {
     char * line = malloc(100), * linep = line;
     size_t lenmax = 100, len = lenmax;
     int c;
@@ -69,7 +69,7 @@ int main(int argc, char** argv) {
     void* shellParser = ParseAlloc(malloc);
     char *line;
     printf("> ");
-    while ( line = getline() ) {
+    while ( line = my_getline() ) {
         parse(line);
         printf("> ");
     }

Also I renamed getline so it would build on my mac; thanks for posting all your source!

andrewdotn
  • 32,721
  • 10
  • 101
  • 130
  • Awesome, I just figured this out myself and pushed the fix, then found your answer when I came back to answer it. Thanks! – theory Jan 25 '13 at 07:32
  • Also [renamed `getline()` to `get_stdin_line()`](https://github.com/theory/flex-lemon-example/commit/d8ab8de07b5079fa9bdf2393f551dbf03650a4af). Thanks for pointing that out. For some odd reason, `getline()` is not defined on my Mac (OS X Mountain Lion). – theory Jan 25 '13 at 07:36
  • Huh—I’m on Mountain Lion but it’s flagged `__OSX_AVAILABLE_STARTING(__MAC_10_7)` in [stdio.h](http://opensource.apple.com/source/Libc/Libc-825.25/include/stdio.h). – andrewdotn Jan 25 '13 at 07:41
  • Maybe because I upgraded from Lion? My `/usr/include/stdio.h` doesn't have `getline`, though `/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk/usr/include/stdio.h` has it. – theory Jan 25 '13 at 08:22