GNU G++ (GCC) vs Visual C++ (VCC)





Introduction

The first operating system I used was DOS (on an old 286 with 2Mo of RAM). I naturally used it to learn the C using Borland C++ 2.0. Then I've discovered Windows 3.1. Then I've learned C++ with Borland C++ 5.0 Student Edition. I have also learned Windows' programming (Windows API, GUI, ...) using Borland's OWL (C++ classes to create Graphical User Interfaces). After Windows 3.1 came Windows 95 ... Then I learned Win32 programming, which was much better than the old fashioned 16 bits architecture.

In my university, we had UNIX systems. So I began learning UNIX. First I used IBM AIX. It was not very convenient because I could not study it at home since AIX was (and is still) very expensive. Therefore I installed Linux on my PC (a 486 this time, with 8Mo of RAM). With Linux I discovered the Open Source world. And, of course, I discovered gcc .... You can not develop under Linux if you don't know gcc. Later I used other UNIX systems: Sun Solaris, Lynx and VxWorks.

I began developping X-Windows applications using MOTIF. And step by step I learned avanced UNIX system programming, ... I even played with drivers.

I found UNIX much more "clear" than Windows. Under Windows you used "ready-to-use" components for everything. You want to get a HTML document? Use a HTTP object. You want to connect a POP3 server? The use a POP3 object ... You've got objects for almost everything.

This is good and bad at the same time. You don't have to develop your own HTTP client because you've got one ready to use ... It saves you time. OK, but by using this "ready-to-use" objects, you don't know how things really work! I know many Windows' programmers that does not know what is a socket. And they have a very vague notion of what is TCP/IP. All right, they don't need to know TCP/IP to use the "ready-to-use" HTTP object. But do you really think it is serious?

UNIX gives you a deep understanding of how an OS works. It also gives you a better understanding of the development tools.

Although I clearly have a Windows' backgroung I prefer the UNIX system. It gave me low-level knowledge (system, networking, development tools, ...).

But today, you should be versatile. So I decided to come back to Windows. I also decided to use Microsoft Visual C++ (Introductory Edition). I still develop under UNIX of course ... I do both at the same time.

These notes underline several differences between the GNU development tools and the Microsoft Visual C++.

The tools

OK, like everybody I began playing with the nice graphical user interface provided by the Microsoft Visual Studio. After many years using vi and the GNU command line utilities, the Microsoft's GUI seems very pretty.

But soon I wanted to know what was behind this user friendly interface. I've got to look at the mechanics. I expected it to look like UNIX ... and it's pretty much the case.

Tool GNU Microsoft Visual C++
The compiler g++ (alias gcc) cl.exe
The linker ld link.exe
The make utility gmake (alias make) nmake.exe
Dumping binary content objdump dumpbin.exe
Library dumping nm dumpbin.exe
Building a library ar (and optionally ranlib) lib.exe

So far nothing new ... Microsoft's documentation is not bad. I like the nice user's interface provided by Visual Studio to browse the online documentation. But, I think that the GNU documentation is much more detailed. The GNU documentation does not only tells you that "ar" is used to make libraries, it also gives you an explanation about what is a labrary. And, because GNU is synonym to "Open Source", it is really easy for you to find more about what you are searching for. You get a full explanation.

Makefiles

The first think I wanted is to write my own "Makefile" under Windows. I have written many "Makefiles" under UNIX and I wanted to do the same with Visual C++. If you want to do cross-platform developments, you should use the command-line utilities since all platforms don't provide the same GUIs.

The text below is my first Visual C++ "Makefile":


CC = CL.EXE
CFLAGS = /GX

exc.obj: exc.hpp exc.cpp
        $(CC) $(CFLAGS) /c exc.cpp /Foexc.obj

test.exe: exc.obj test.cpp
        $(CC) $(CFLAGS) test.cpp exc.obj /Fe test.exe

all: test.exe

clean:
        del test.exe
        del *.obj

It looks pretty much like a standard UNIX Makefile. The following "Makefile" illustrates the GNU version of a Makefile.


CC = g++
CFLAGS = -Wall -o $@

exc.o: exc.hpp exc.cpp
        ${CC} ${CFLAGS} -c exc.cpp

test: exc.o test.cpp
        ${CC} ${CFLAGS} test.cpp exc.o

all: test

clean:
        rm *.o

Although Microsoft's Makefiles looks pretty much like GNU's Makefiles, GNU allows you to create much more complex Makefiles.

Compiler's configuration

The following table illustrates common compiler's configuration options.

What to do GCC Visual C++
Where to look for extra header files -Iinclude_path Tools => Options => "show directories for" => "include files"
/Iinclude_path
Where to look for extra libraries -Llibrary_path Tools => Options => "show directories for" => "library files"
/link /LIBPATH:library_path
Linking a library: -lname
This will link the library libname.a
Project => settings => link

Just add the library name to the compiler's command line. Any files with name extension other than .C, .CXX, .CPP, or .DEF are passed to the linker.
Specify an output file name -ofile_name Project => settings => link
  • /Fefile_name (to create an executable).
  • /Fofile_name.obj (to create an onject file).
Compile only, produce an object file. -c
This will create a ".o" file.
/c /Fofile_name.obj

This will create a ".obj" file.
Produce full warning output -Wall Project => settings => C/C++ => category => General
/W4
Define a macro -Dmacro[=...] Project => settings => C/C++ => category => preprocessor
/Dmacro[=...]
Undefine a macro -Umacro Project => settings => C/C++ => category => preprocessor
/Umacro
Building a static library ar rcs library_name.a file1.o file2.o file3.o ... lib.exe file1.obj file2.obj ... /OUT:library_name.lib
Building a dynamic library gcc -shared -fPIC -ldl -o library_name.so file1.o file2.o ... link.exe /DLL file1.obj file2.obj ... /OUT:library_name.dll