Compiling¶
Or more precicely, HOW DO I RUN MY CODE???¶
Before we talk about C++ in particular, lets take a quick detour and talk about running any code on a computer. Computers have a specific “language” that they understand - and this is communicated via a specific set of instructions expressed through an ISA (Instruction Set Archtecture). Different computers can have different ISAs. You’ve probably heard of things like Arm and Intel. They tend to have a specific ISA that they operate with. What this means is that if you want to run a program on that system, you need to “translate” your code into some machine level code that is compatible. Something like:
std::cout << "Hello World!" << std::endl;
doesn’t really mean anything to a computer. But something like:
push rbp
mov edx, 12
mov esi, OFFSET FLAT:.LC0
mov edi, OFFSET FLAT:std::cout
call std::basic_ostream<char, std::char_traits<char> >& std::__ostream_insert<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*, long)
mov rax, QWORD PTR std::cout[rip]
mov rax, QWORD PTR [rax-24]
mov rbp, QWORD PTR std::cout[rax+240]
does.
Ain’t nobody got time to write code like that (well, some do - and we’ll go over that way later in this book!). So we instead have higher level languages like C++ that let us write code that’s still readable. But something still needs to convert our easy to read C++ into machine level code. That’s where a compiler comes in. A compilers job is to translate from one language to another. Notice that we say “one language to another” and not “one language to machine code”. There are compilers that can convert from one language into another that isn’t immediately useable by a computer. Compilers are also responsible for making sure that the code you write works for the intended computer archtecture. This means that you might have to compile a program with different targets (computer archtectures) in mind somethings. This is also why you can’t just run a program that was build for linux on windows, windows on mac, mac on linux, etc without doing something fancy. You generally have to compile them independently.
Alright, now back to talking about C++.
C++ is a compiled language. Since we can’t just hand C++ code to a computer, we need something that takes our marvelous code and convert it into something a computer can understand (like assembly language). That’s exactly what we’ll be doing as well. Below is a quick view of what this would look like:
The above flow: [C++ Code] -> [Command to compile] -> [Assembly code from the compiled output] -> [Running the program]
This will generally be the flow of every program we write going forward.
Okay, okay, enough with the background. How do I compile my code?¶
With some handy dandy C++ compilers!¶
There are a ton of compilers for C++. Here is a pretty long, but incomplete list.
In general, compilers try to stay ahead of the curve in terms of support and feature functionality but there are still differences between them. We will exclusively be discussing / using clang
and gcc
in this book, but you are welcome to use any at your disposal. It’s very possible that you might not be able to use either of these compilers and that’s okay. There are plenty of resources online on how to get setup if so. If you really don’t want to setup anything locally, you can also always use your friendly neighborhood website Compiler Explorer.
If you would like to follow along by developing locally (highly recommended), we suggest you pick a compiler to use and then we can march forward in our adventure in C++. It doesn’t really matter too much for our purposes what you pick at this stage. Usually your computer comes with a compiler already installed, but you may want to use something different (or a newer version). This process can be a little daunting. Using something like conda
might help make this easier by isolating your changes from your broader computer. If you are interested in doing so:
conda: https://docs.conda.io/projects/conda/en/latest/user-guide/install/
gcc: https://anaconda.org/conda-forge/clang
clang: https://anaconda.org/conda-forge/gcc
The 10-15 mins it’ll take to get up to speeds on the basics of conda will definately be worth it long term: https://docs.conda.io/projects/conda/en/latest/user-guide/getting-started.html. The primary benefit being that you can isolate your enviroments so that if you do screw something up, it’s not a big deal. If you are a power user and want multiple compilers and versions, then conda is going to be even better. Just switch environments to switch compilers trivially!
So hopefully at this point you’ve either decided to develop locally or use Compiler Explorer. If you’ve decided on the latter, feel free to skim the below section.
How about we try compiling code with an actual example:¶
Lets start by creating a new file called “test.cpp”. Feel free to whip out whatever text editor is most accessible for you. Go ahead and copy the following code into that file:
#include <iostream> // for std::cout
#include <cstdlib> // for EXIT_SUCCESS
int main()
{
// A simple program that will print "Hello world!" to the terminal
// C++ provides std::cout which lets you pipe output to stdout.
// << is a specific operator, just like +, =, etc that you can overload
// someone went ahead and overloaded the << operator so that when you use it
// it'll write text to the target stdout.
// std::endl just says add a new line and flush
std::cout << "Hello world!" << std::endl;
// A predefined value for a successful run
// (so you don't have to figure out what to return when you are done with the main loop)
return EXIT_SUCCESS;
}
Go ahead and save the file now. Now that we have some valid code, we can go ahead and compile it. Let’s go ahead and do precisely that.
To compile:
With gcc:
g++ -std=c++17 -o to_run test.cpp
[compiler] [standard library version to use] -o [output file] [input file]
With clang:
clang++ -std=c++17 -o to_run test.cpp
[compiler] [standard library version to use] -o [output file] [input file]
To run:
Running the above command should generate a file called to_run
locally. Lets go ahead and run that by doing:
./to_run
and you should see this output:
Hello world!
What we showed above is actually just how to run the simplest of programs. This doesn’t really show you how to include other system libraries, how to add multiple files, or add special compiler flags. If you are curious about reading more about what goes on in this part of the world, feel free to look up “build systems C++” and you’ll find tons of resources related to make
, cmake
, and ninja
to name a few.
That takes too long. Is there a faster way?¶
You bet! Automate all the things!
Compiling locally with tmux + vim + inotifywait¶
Online tools like Godbolt might not always be handy or accessible. In cases like this, it’s nice to have a local setup that will quickly compile your programs and display your output. We showed you how to compile a given C++ file, but we haven’t show you how you can automate this process. What we’d like to be able to do is edit out code, and then once we save the file, we’d like to see the compiler output and (if successfully compiled) the program output. Here is an screenshot of what this would look like locally:
Commands being run:¶
Top left pane:
vim test.cpp
Top right pane:
watchman-wait *.cpp --max-events 0 | while read line; do echo "----------------------------" && date && ls -lart; done
Bottom pane:
watchman-wait *.cpp --max-events 0 | while read line; do echo "----------------------------" && date && g++ -o to_run $line -std=c++17 && ./to_run; done
Tools you can use to accomplish this:¶
tmux:
is an open-source terminal multiplexer for Unix-like operating systems.
To install:
Ubuntu / Debian:
sudo apt-get install tmux
Fedora:
sudo dnf -y install tmux
Centos:
sudo yum -y install tmux
OSX:
brew install tmux
Vim:
(a contraction of Vi IMproved) is a clone, with additions, of Bill Joy’s vi text editor program for Unix.
To install: https://www.vim.org/download.php
Something to watch for file changes:
Compilers vs. Interpreters¶
Note
TODO Talk about python vs. C++ example.
References:¶
Lots of wonderful people have publically shared information on the ins and outs of compilers, what they do, how they work, and how to best use them. This is definately a topic you can write multiple books on (and people have!). Here are a few references that we think are worth checking out if you are curious in this matter: