(or What's the best IDE for WATCOM C++)
Hamburg (Germany), the 16th November 1997.
Written by Nils Pipenbrinck aka Submissive/Cubic & $eeN
What is a makefile, and why should you use them?
If you've ever written a program with more than 2 or 3 sourcefiles
without the aid of an IDE (like Watcom C for DOS or pure assembly) you
know and hate the following situation: You've found a bug or added a
single line to your code and you want to build your program to check
if it works. You start your batch-file and wait ages because your
stupid batch compiles every single module of your code... This is
what makefiles are good for: They can organize and speed up your build
progress. This small tutorial will only touch the basics of Makefiles,
and most of the stuff is specific to the Watcom Make
(since I use it, and I think most of the guys who'll read this will
also use Watcom for their coding work). Makefiles aren't usable
without a make-program. If you want to execute a Makefile you have to
call your Make utility (for watcom it's called WMAKE). I've also
examined the Borland MAKE Utility. If you don't have WATCOM WMAKE but
still want to use MAKEFILES check out my Makefile
Compatibility Chart Page.
First: don't panic, it's not harder to understand than batches! I'll start with a simple example, and won't go into the difficult details of makefile-coding right now...
Imagine you have written a small game with WATCOM C and wrote a couple of sourcefiles like:
So, what do you need to build your game? At first you have to define a TARGET for your game. Usually this target is named as the executable you want to build (in our example it's called game.exe).
The target definition in a makefile looks like this:
game.exe: video.obj mouse.obj game.obj
This means that the make-program knows which object files are needed to
build your game.exe. The files listed after the colon are called
Dependencies. Most of them are usually object files, but
you can include any kind of file you want.
Ok. Now Make knows what's needed to build your game, but it still has no clue how to generate these .obj files you declared in your dependencies. That's what Rules are for. the most simple form of a rule looks like this.
.cpp.obj wpp386 $<
or for assembler fans:
.asm.obj tasm $<
With this rule the makefile knows how to turn a .asm or .cpp file into a .obj file. If you're wondering what the $< stands for: It's just a macro or placeholder for the current file that has to be compiled.
Right now we know how to build everything needed for game.exe, but we haven't declared how to build game.exe. We have to alter the target again, and add some lines to call the linker:
game.exe: video.obj mouse.obj game.obj %write game.lnk NAME $@ %write game.lnk SYSTEM DOS4G %write game.lnk FILE video.obj %write game.lnk FILE mouse.obj %write game.lnk FILE game.obj wlink @game.lnk
%write does just what it says, it writes something
into the file game.lnk. The first %write command will create the file
game.lnk if it doesn't exist, or it'll erase it (so you don't have to
worry about the game.lnk file at all, it'll be recreated every time
you start MAKE).
$@ is again a macro. It expands to the name of the
current target. In our example it's just game.exe.
You can do everything you want in this body, you can start your own
tools and call dos-commands. Finally the line wlink @game.lnk
executes wlink and passes game.lnk as command file. This will build
your game.exe from the object files.
Now here is the makefile nicely formatted and in one piece:
.cpp.obj wpp386 $< game.exe: video.obj mouse.obj game.obj %write game.lnk NAME $@ %write game.lnk SYSTEM DOS4G %write game.lnk FILE video.obj %write game.lnk FILE mouse.obj %write game.lnk FILE game.obj wlink @game.lnk
Important:
Add a blank line between two different sections and make sure that
there is always a blank at the start of the section bodies. The make
utility needs this. If you now call your make-utility it will read
the makefile, call Wpp386 for each source-module, write the game.lnk
and then finally call wlink. The make-utility will stop if any of the
make steps (e.g. compiling a sourcefile or linking) returned an error.
MAKE will only do the steps needed to build your program. If a
.cpp file hasn't changed since the last make, it won't call wpp386 on
this file (unless your force it to do so, but I'll explain this
later).
Now you've written a joystick input module for your game and want to include it in your makefile. To do so, you have to change the makefile at two different lines:
Since all coders are lazy MAKE also supports macros to make our life more fun :) A macro is basically a simple text replacement and it's also very easy to use.
Now we want to replace our dependency list with a macro and also add some other macros (compiler options, name of the executable). The new makefile will look like this:
objects1 = video.obj mouse.obj game.obj joystick.obj coptions = /5r /s /ox dest = game.exe .cpp.obj wpp386 $(coptions) $< $(dest): $(objects1) %write game.lnk NAME $@ %write game.lnk SYSTEM DOS4G %write game.lnk FILE {$(objects1)} wlink @game.lnk
I think this is very simple to understand: to declare a macro you just do it like I did it in the first 3 lines. If you want to use a macro you write $(macroname). This makefile is very flexible, and most of my makefiles look exactly the same. I usually also include a rule for .asm files (even if I don't need it). The {$(objects1)} is a trick I saw in someone's makefile: Watcom WLINK is able to process multiple object files in one FILE statement. You only have to group them in {}.
Now you have all the tools you need to work successfully with WMAKE. For a start it might be a good idea to cut'n'paste my example makefile and save it as a template for new projects. If you want to learn more about makefiles you should check out the TOOLS helpfile in the watcom-directory, but be warned: this stuff really goes into detail and you might get confused. You will also find other people's makefiles which are completely different to my style. You should know: Everyone has his own coding style, even for makefiles. It might be fun to explore other makefiles and learn their tricks. This can be a challenge, and you might waste a couple of hours on it, but it's definitely fun (a hint for those folks who think they know everything about makefiles: check out the makefile from the LINUX Kernel. If you understand what's going on you are an expert) Afterwards you can be proud and say "I have WMAKE and EDIT. I don't need a stupid IDE." And finally, before I forget it: If you think that make is out of sync, and you want to rebuild your complete application from scratch you should type WMAKE -A . This will build every single dependency from scratch.
If you want to contact me for any reasons (bugs, suggestions, typos or cool makefile-tricks), then write an email.
... please let me read the follow-up tutorial: MAKEFILES For Experienced!
© by submissive