Windows users who want to learn C++ often ask if there is a free C++ compiler. Linux users don't have this problem because they have the GNU tools. But, in fact, the exact same tools are available free from Cygwin, and if you learn to use them, your skills will be extremely portable. Learn to install and use the tools, compile a simple program, and write a simple makefile.
Pssst... Want a Free C++ Compiler?
Is there such a thing as a free C++ compiler for Windows? In fact, there are several. For example, Microsoft recently released their Visual C++ Toolkit 2003, which gets you a bare-bones compiler.
But, another possibility exists, from an unlikely source, and it has the added attraction that when you learn to use it, you are learning to use the same software that you would find in a typical Linux installation. Even if you're a dyed-in-the-wool Windows user (which I'm afraid I am), this has to be worth investigating.
Linux can be quite overwhelming when you first install it, which makes it hard to learn anything about it. To a Windows user, everything
is different and strange. It would be better to be able to play with some pieces of it, without having to leave the safe, familiar surroundings of Windows just yet.
So, if you want to learn C++ for free, and get some understanding of how to use a UNIX-like environment (without having to find the Linux driver for your DSL modem), read on.
Linux and GNU
The vast majority of the software on a Linux CD-ROM set is not specifically anything to do with Linux. It's GNU software, distributed freely as source code, that can be run on any UNIX-like operating system, and in fact it provides all the pieces of a typical UNIX operating system—at least, the parts you interact with directly, such as shells, editors, and development tools.
The good news for us Windows users is that if you visit http://www.cygwin.com, you will find a convenient bundle of this software ready to download and install all in one step. If you have a decent connection, be sure to ask the installer to give you everything—it's a huge download, but it gives you a vast and very complete UNIX-like environment to play with.
It puts a shortcut on your desktop to open the BASH shell, which is a version of the Bourne shell, the original "interactive" user interface of UNIX. Bourne himself wrote a beautifully clear and helfpful introduction to it, way back when.
The shell is really just the same thing as the Windows command prompt. Just as Windows has batch files that are just lists of commands, a UNIX shell has scripts (although shell scripts have somewhat better looping and control features than batch files.)
All UNIX operating systems have a version of the Bourne shell, but they usually aren't as good as BASH, and so most people get a version of BASH for their UNIX flavour and use it instead of the default shell.
Now, you have Cygwin, and you feel just about ready to start hacking the Linux kernel. So, where is this C++ compiler?
Compiling a Program
So, now that you have Cygwin, let's compile a program. Open a BASH shell and type:
It should say:
g++: no input files
You've now got a C++ compiler on your system, completely free. One of the best, in fact. Linux itself is compiled with this compiler, as are most running copies of Apache, the world's most popular Web server.
As well as a compiler, you obviously need an editor to write your code in. This is where I tend to find the standard UNIX offerings somewhat lacking. There's a thing called VI, but if you're not already familiar with it, count yourself lucky.
So, let's use Notepad!
std::cout << "Hi" << std::endl;
Save the above code as helloworld.cpp. Now, a slight puzzle: Where to save it? On a UNIX system, a file is located with a path delimited by forward slashes. Instead of having drive letters, one disk partition acts as the root of the file system, and other partitions are "mounted" into it, so they look just like directories.
Cygwin pretends to be Linux, and it does this by using C:\cygwin (or wherever you installed it) as the root of the pretend Linux file system. So, enter:
Note: On Windows, you don't need a space after cd, but on Linux, UNIX, and Cygwin, you do.
That's the UNIX equivalent of dir. Take a look at C:\cygwin in Windows Explorer to convince yourself that it's the same thing, and then save your helloworld.cpp source file into that directory.
This will either generate errors about your source file, or it will generate a real live executable, with the fun default name:
Note: On a real UNIX or Linux system, the default name will usually be a.out. There is some historical reason for this that made sense a few decades ago.
Try running it. Ahh, gotcha. Just entering a doesn't work, and nor does a.exe. UNIX people think it's unsafe to allow programs in the current directory to run unless you specifically say so, so you have to type:
To get a program with a sensible name, try:
g++ helloworld.cpp -o helloworld
You can easily make a program out of several separate source files like this:
g++ hello.cpp goodbye.cpp main.cpp -o myprogram
That's not very practical for a large program, because even if you only change one of the files, that command will compile all of them. The traditional solution is to use a tool call make, and guess what? Yep, Cygwin has that too, and it's really essential in a large cross-platform project.
Right, you know how to compile helloworld.cpp using the fabulous free C++ compiler you get with http://www.cygwin.com.
The next step is to write a makefile, which will play a similar role to a "project" or "solution" file in your typical Microsoft-style IDE. You write a makefile, and then you type make in the same directory and it will find your makefile and obey the instructions.
Suppose you had a main function in the main.cpp file and a module in the other.h and other.cpp files. You need to compile main.cpp and other.cpp and link the resulting .o files together into an executable. The makefile we need to write, which must be saved with the name makefile with no extension, is surprisingly short:
foolery.exe : main.o other.o
g++ main.o other.o -o foolery.exe
The odd thing is that we haven't even mentioned the .cpp files!
What's In a Makefile?
In simple terms, a makefile is just a list of rules. When you run make with no parameters, the first rule in the file is evaluated, and this will usually in turn trigger off the evaluation of other rules.
A rule starts with a line such as:
foolery.exe : main.o other.o
This literally means the following: Look at the file modification times on main.o and other.o. If either is newer than the modification time of foolery.exe, we need to recreate foolery.exe.
So, you write the name of a target file, then a colon, and then a space-separated list of files that the target file depends on. Next, you need to specify how to re-create foolery.exe in the event that the rule is triggered. This is specified by ordinary shell commands that appear immediately after the dependency line. Important: these lines have to start with a tab character. So in the example, I had:
g++ main.o other.o -o foolery.exe .cpp .o
This tells the compiler to link the two object files together into an executable.
But, we still don't know how the .cpp files get compiled into .o files. The answer is: by a built-in rule of make. Pretty much all C++ compilers will do a pure compilation step on a single file if you specify the -c switch; for example,
g++ -c main.cpp
That will spit out a file called main.o, just as we require. So, we could add a rule to our makefile, like this:
main.o : main.cpp
g++ -c main.cpp
But, we'd have to repeat that for every .cpp file in the project, which quickly becomes very tedious. And, I hate the kind of thing where some repeating pattern has to mention the same name three times (in this case, the word "main"). To avoid this, make has a feature where you can specify how to translate from one type of file to another (where the type of file is described by a wildcard). The rule for .cpp files is:
%.o : %.cpp
g++ -c $<
The % character is the wildcard matching symbol, and the funny-looking $< character sequence is the name that matched the filter on the right. The final piece of the puzzle is that make has this rule built into it. You can override it with your own rule if you want to specify extra switches to the compiler.
Even with this built-in rule doing a lot of the work, I'm still not happy with the makefile because the list of objects and the target name each appear twice. So, if you added a new source file, you'd have to add it to two different places. Fortunately, you can define variables in a makefile and refer to them with an amusing syntax:
objects = main.o other.o
target = foolery.exe
$(target) : $(objects)
g++ $(objects) -o $(target)
So, with that makefile, whenever we want to add a new source file to the project, we just add it to the list in the objects variable.
You also can add dependencies for your header files. For example, if other.cpp includes other.h, you should add a line to the make file:
other.o : other.h
This means that if the timestamp on other.h is newer than that on other.o, the rule to make other.o should be executed—and that's just the built-in rule we saw just now.
The GNU C++ compiler we've been using is part of a "compiler collection" that also covers several other languages. You can find out more from http://gcc.gnu.org/.
The GNU make tool has a great online manual.
Once you start digging into what you can do with Cgywin, it's amazing how capable it is. The graphics system used on UNIX is http://www.x.org/. Try typing this into the Cygwin shell:
This starts an X server and an xterm window. You can now run a famous X sample program:
I remember being pretty impressed by this, but it's nothing compared to what you'll find at http://kde-cygwin.sourceforge.net/—KDE, one of the most popular desktop environments on Linux, and the whole thing runs on Windows! This is partly testament to the completeness of Cygwin and partly to the extremely portable, modular nature of free software.
But, getting back to what we've looked at, now you have experienced the basic building blocks of a UNIX-style C++ development environment. It's nothing fancy so far, no graphical user interfaces and whatnot, but you can write network servers with it. It's how most servers on the Internet are written!
(But you should probably practise for a while before you start hacking the Linux kernel.)