CS 70

Compiling and Running Code in C++

  • LHS Cow speaking

    In previous CS classes, you've written code in languages like Python and Java. In this class, we'll be writing code in C++. But let's remind ourselves how we get from our source code to a runnable program in those other languages first.

  • Python speaking

    For Python, we just write our code in a file, say foo.py, and then run it with the Python interpreter, as in:

    python foo.py
    

    So actually, your computer doesn't directly run your Python code. Instead, it runs the Python interpreter (a program called python), and that runs your code.

  • Jo speaking

    Phew! I'm so jazzed to tell you that Java is a bit like Python and C++!! We use

    javac Foo.java
    

    to compile the code into a Java Virtual Machine (JVM) bytecode file, Foo.class! Assuming we've done everything right (!!), we can give that bytecode to the JVM to actually run our code, by typing

    java Foo
    

    So, a bit like Python, your computer doesn't run the .class file directly. Instead, it runs the JVM (the program java), and that runs your code. Sometimes it even runs faster than Python!!!

  • Bjarne speaking

    C++ is a compiled language that turns your code into a program that your computer can run directly. The fundamentals of C++ compilation are the same as in C, which dates back to the 1970s. It's part of our heritage!

    With no middle-man interpreter, C++ programs can run faster than Python or Java programs. But it also means that we have to do a bit more work to get our code to run.

  • Hedgehog speaking

    Oh no, it's going to be complicated, isn't it?

  • Pig speaking

    MORE steps, but MORE speed!!!

  • Goat speaking

    Meh, less is more.

  • LHS Cow speaking

    Let's get back to C++…

Going from C++ code you've written to an executable you can run can be as simple as running the compiler (clang++) once, then running the executable it produces, as in

clang++ -std=c++17 -pedantic -Wall -Wextra foo.cpp

which compiles our code in foo.cpp into an executable file called a.out. In a terminal, you can then run the executable by typing ./a.out and hitting Return.

a.out is the default name for an executable, but you can use the -o flag to provide the compiler with a much more descriptive name, as in

clang++ -std=c++17 -pedantic -Wall -Wextra  foo.cpp -o foo

You can then run your program by typing ./foo and hitting Return in a terminal.

C++ with Several Source Files

Compiling C++ code gets a bit more complicated when you have an application with more than one .cpp file. Assuming we have have three source files—foo1.cpp, foo2.cpp, and foo3.cpp—we could get an executable (a.out) with

clang++ -std=c++17 -pedantic -Wall -Wextra foo1.cpp foo2.cpp foo3.cpp

Separate Compilation

While you can (sometimes) get away with compiling everything on one line, C++ programs are often more complicated—for example, they might use libraries provided by the system or an application framework.

There are tools that make building C++ applications easier and faster, but in CS 70 we want to dive into all the nitty-gritty details, so we start by doing things the hard way and then work our way up.

So if you have several C++ files that make up a single executable program, you should compile each .cpp file to object files on its own line, as in

clang++ -c -std=c++17 -pedantic -Wall -Wextra  part1.cpp
clang++ -c -std=c++17 -pedantic -Wall -Wextra  part2.cpp
clang++ -c -std=c++17 -pedantic -Wall -Wextra  part3.cpp

The first command will create an object file called part1.o, the second part2.o, and the third part3.o. You can then link the object files together to build your executable, as

clang++  -o myprogram  part1.o part2.o part3.o

which gives you an executable myprogram, which can be run in a terminal with ./myprogram.

Why So Many Steps?

The process of separate compilation—where we compile each file into its own object file, then link those corresponding object files to build an executable—can actually save quite a bit of time when working on large projects!

For example, imagine that your project has 20 C++ files that must be compiled and linked to build an executable program. Without separate compilation, you would have to recompile the entire project every time you changed any part of it, even if that change was a minor tweak in a single file. With separate compilation, you only need to recompile the file(s) you changed, then relink the new object file(s) with the object files you already have from your unchanged source code files.

For example, imagine you find a bug in file16.cpp. After you fix it, you can rebuild your executable with the following command:

clang++ -c -std=c++17 -pedantic -Wall -Wextra  file16.cpp
clang++ -o program  file1.o file2.o ... file20.o

You only need to recompile file16.cpp, then link the resulting object file with the unchanged object files you already built

Tools

As we mentioned, there are various tools that people use to help them build and maintain large projects written in C++. Those tools can monitor files for changes, then just rebuild the bits of the code that have changed, and handle linking them all together without you having to keep track of what's changed and what depends on what yourself. We'll get to some of those tools later in the semester!

(When logged in, completion status appears here.)