For many languages, a program has to be compiled before you can run it. This includes .NET languages, Java, C family languages, Pascal family languages, Fortran, Assembly, and many others. The reason is simple: source code is not understood by the computer/operating system/virtual machine, so the source code has to be translated into something it can understand and execute. For many people, however, this process remains a complete mystery.

Contrary to what you might assume, compiling a program is not a simple process. What I am about to describe is lifted from the C/C++ way of compiling with GCC, but applies quite well to a variety of languages. For many languages, the compilation process will involve one or more of the following steps: performing any preprocessing on the source code, checking the syntax of the source code, converting the source code to assembly, converting the code to machine code, and linking multiple pieces of machine code from separate files into a single executable file.

If this sounds like a lot, it is. Let's look at some of the details to understand what's going on. Examples will mainly come from C++, but many other languages have similar constructs.

Preprocessing: frequently, the source code you type into a program is incomplete and invalid. Consider the following:
Code:
#include <iostream>
int main()
{
  std::cout<<"Hello World!\n";
  return 0;
}
As this file stands, it is NOT valid code! std::cout is not defined anywhere within this file, nor is operator<< appropriately overloaded. Nevertheless, this will compile. Why? Because the definitions located in iostream.h are prepended into this file. The result is a different file where class cout is defined in namespace std with an appropriately overloaded << operator.

Directives, macros, and includes are all examples of the type of processing that can be performed at this stage. The result of this stage is code that may be quite a bit different from what you originally typed. wxWidgets defines entire functions, including main() or winmain(), this way.

Syntax Checking: Once the code is updated based on the preprocessing, the code can be checked for valid syntax. This includes things like checking for semi-colons, matching braces, every "begin" has an "end", etc. This doesn't mean the code is correct, but it does determine whether the code can be turned into machine code as written.

Converting To Assembly: This step doesn't exist for all languages/compilers. Java, obviously, doesn't use this step. Some compilers may go straight to machine code. GCC supports various languages, so converting all programs to Assembly makes converting to machine code much easier.

Converting to Machine Code: What counts as machine code varies somewhat. Java goes to byte code (.class files). GCC creates object files. This step creates a file that is PART of the final program.

Linking Machine Code Into An Executable: Frequently, functions that are used by a program are defined in separate files. Delphi uses components that are in a variety of different files (especially commercially sold components). C/C++ use a variety of libraries. Java often merges .class files into a .jar file. At this step, many linkers will do final checks to make sure all the required pieces, functions, components, etc have been accounted for.

As you may have guessed, there is a LOT going on here! All of this manipulation, checking, etc results in a lot of work. If you have a realistic program, you are also going to be dealing with a program that is spread across dozens or hundreds of source files. Organizing all this information can be a huge project. As a result, most development tools include a mechanism for organizing these files. Project files (.dpr in Delphi, .prj in some other languages, make files for GCC) allow you to define all the files that need to be compiled, linked, etc to create your executable. They may also include instructions about additional libraries/components that need to be linked into your program.

The point of this is not to discourage you, but raise your awareness. There are many development environments that can dull our awareness of what is happening. The simplistic nature of many programs that are written while learning a language can make this situation worse. When a typical "learning" program in a C++ course includes one custom header, and to .cpp files, people can fail to understand the potential complexity of a realistic program. By contrast, a program like Wordpad could contain a dozen source files, and a program like Word can easily contain hundreds of source files. Project files greatly reduce the complexity of working with these programs, while keeping individual source files manageable.