180 Programming program: source1.o source2.o cc -o program source1.o source2.o # I'm debugging source1.c -Dennis source1.o: source1.c cc -c -g source1.c source2.o: source2.c cc -c source2.c The line beginning with “#” is a comment. The make program ignores them. Well, when poor Dennis runs make, the program complains: Make: Makefile: Must be a separator on line 4. Stop And then make quits. He stares at his Makefile for several minutes, then several hours, but can’t quite figure out what’s wrong with it. He thinks there might be something wrong with the comment line, but he is not sure. The problem with Dennis’s Makefile is that when he added the comment line, he inadvertently inserted a space before the tab character at the begin- ning of line 2. The tab character is a very important part of the syntax of Makefiles. All command lines (the lines beginning with cc in our example) must start with tabs. After he made his change, line 2 didn’t, hence the error. “So what?” you ask, “What’s wrong with that?” There is nothing wrong with it, by itself. It’s just that when you consider how other programming tools work in Unix, using tabs as part of the syntax is like one of those pungee stick traps in The Green Berets: the poor kid from Kansas is walking point in front of John Wayne and doesn’t see the trip wire. After all, there are no trip wires to watch out for in Kansas corn fields. WHAM! You see, the tab character, along with the space character and the newline character, are commonly known as whitespace characters. Whitespace is a technical term which means “you should just ignore them,” and most pro- grams do. Most programs treat spaces and tabs the same way. Except make (and cu and uucp and a few other programs). And now there’s nothing left to do with the poor kid from Kansas but shoot him in the head to put him out of his misery.
Programming in Plato’s Cave 181 Dennis never found the problem with his Makefile. He’s now stuck in a dead-end job where he has to wear a paper hat and maintains the sendmail configuration files for a large state university in the midwest. It’s a damn shame. Header Files C has these things called header files. They are files of definitions that are included in source files at compilation time. Like most things in Unix, they work reasonably well when there are one or two of them but quickly become unwieldy when you try to do anything serious. It is frequently difficult to calculate which header files to include in your source file. Header files are included by using the C preprocessor #include directive. This directive has two syntaxes: #include header1.h and: #include "header2.h" The difference between these two syntaxes is implementation dependent. This basically means that the implementation is free to do whatever the hell it wants. Let’s say Dennis has a friend named Joey who is also a novice Unix pro- grammer. Joey has a C program named foo.c that has some data structure definitions in foo.h, which lives in the same directory. Now, you probably know that “foo” is a popular name among computer programmers. It turns out that the systems programmer for Joey’s machine also made a file named foo.h and stored it in the default include file directory, /usr/include. Poor Joey goes to compile his foo.c program and is surprised to see multi- ple syntax errors. He is puzzled since the compiler generates a syntax error every time he mentions any of the data structures defined in foo.h. But the definitions in foo.h look okay. You and I probably know that the Joey probably has: #include foo.h in his C file instead of: #include "foo.h"
Previous Page Next Page