There are many new languages with native build targets: Swift, Rust, ReasonML, etc. But let’s take a look at an often overlooked choice: C.
Hopefully, if you’re anything like me, getting a little C under your belt will not only be a great addition to your skillset — it’ll also feel like a personal victory. Let’s get started by learning how to compile and run 3 variations of, the classic, “Hello, World!” 🎉.
I GCC What You Did There
To compile C code, we’re going to need a compiler. Luckily, C is one of the languages supported by the GNU Compiler Collection (GCC), and chances are it’s already available on your system. If so, we can use it on the command line via
Note: If you’re on Windows, you probably don’t have gcc available in Command Prompt 😭. You will need something like MinGW to follow along with the rest of this post.
Working with a Single File
Let’s create a
hello.c file and add the following code to it:
The absolute simplest way to compile it is with the following command:
gcc will produce an executable file named
a.out¯_(ツ)_/¯. We can run the file like so:
./a.out. Maybe it’s just me, but I usually want to name my program something else, so I often do something like this:
gcc hello.c -o hello
-o flag lets us name our executable. Similarly, we can run it with
./hello. But what if we have multiple source files? 🤔
Working with Multiple Files
Now, we’ve got
hello.c just like before, but we’ve added a
greet.c. Files that end in
.h are called “headers”. It’s their job to declare the public type definitions their respective
.c file will implement. Examine the following:
A little complex for a “hello world” program, but I’m just trying to get a point across 😛
First, we must make sure to add the necessary
#include statements. Then to compile, we simply list out all of the
.c source files in use:
gcc greet.c hello.c -o hello
Not bad 😎.
It’s often the case in application programming that we don’t want to write every single bit of code ourselves. Let’s say we want to make a game, for instance. Writing all of the cross-platform window management, input polling, and graphics rendering code from scratch will take us pretty much forever. So to make our lives easy, we decide to use Raylib.
We can install it to the standard location via the command line (
brew install raylib on macOS, for example). Then, we write a few lines of code to open a window with our canonical greeting:
The library we depend on doesn’t exist as a single file in our project directory, so simply adding
raylib.c won’t work. Technically, it’s a
.h header file and an archive file living somewhere on our system¹.
Anyways, this just means it’s time to use
gcc -lraylib hello.c -o hello
Too easy. Under the hood,
gcc uses a linker called
ld to include libraries. The
-l flag lets the linker know which ones to search for and include. If we had multiple libraries, we’d just list them out like
-lfoo -lbar -lbaz. Anyways, we can run it with
./hello, just like in the previous examples, to pop open an application window with a familiar greeting 👋.
There are many other useful and interesting compiler flags to learn about , but we’ll skip those for now². And as fun as it may or may not be to use gcc directly, we ought to figure out how to automate the build process.
In the next part, we’ll solve this problem by learning about, our good friend, the Makefile 💪.
¹ In C, libraries have two components: a header and an archive file. Archives come in static and dynamic flavors:
.so on Linux,
.dylib on MacOS,
.dll on Windows , respectively. By default,
gcc will probably search for library headers in
/usr/include and for archives in
/usr/lib and usr/local/lib. However, this can vary depending on your setup. If we do happen to place a library header or archive somewhere the linker wouldn’t normally look, the compiler will fail unless we explicitly tell it where to look. So in addition to
-l, we would also need to use the
² Just run
gcc --help if you’re curious. For more in-depth explanations, check out the docs for Overall Options, C Dialect Options, and Options for Linking. Or for a simple overview, you can quickly browse the Option Summary. Keep in mind, many of these flags may be somewhat difficult to grok until you actually need to use them.
Thanks to Erik Nygren for reviewing.