<< Home

Chapter 2: Setting Up Your Environment

This chapter gets a working C toolchain on your machine, shows how to compile from the command line, introduces small Makefile builds, and points to editor and IDE choices that fit a portable workflow.

Installing GCC on Linux, macOS, and Windows

GCC is available on all major platforms. Install it with the native package manager on Linux, with Apple’s command line tools or Homebrew on macOS, and with MSYS2 or MinGW on Windows. After installation, verify with gcc --version.

Installing under Linux

Here is how to install under some top flavors of Linux:

DistroInstall
Debian, Ubuntu, Mintsudo apt update && sudo apt install build-essential
Fedorasudo dnf groupinstall "Development Tools"
RHEL, AlmaLinux, Rockysudo dnf groupinstall "Development Tools"
Arch, Manjarosudo pacman -S base-devel
openSUSEsudo zypper install -t pattern devel_C_C++
💡 The meta packages above install more than gcc (for example make, gdb). This saves time later.

Installing under macOS

Using macOS install like this:

# Apple Command Line Tools (provides Clang; often enough)
xcode-select --install

# Optional: Homebrew GCC alongside Clang
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
brew install gcc

After installing, run gcc --version. On macOS the default gcc is usually Clang’s driver for compatibility. Installing Homebrew gcc gives you a GNU build as well (named gcc-… such as gcc-14).

Installing under Windows

Following are the various Windows installation options:

OptionPurposeNotes
MSYS2 (MinGW-w64) GCC toolchains for native Windows pacman -S --needed base-devel mingw-w64-ucrt-x86_64-gcc; use the MSYS2 MinGW shell
MinGW-w64 standalone Lightweight GCC for Windows Add bin to PATH; verify with gcc --version
WSL (Ubuntu on Windows) Linux userland on Windows Install Ubuntu from Store; then sudo apt install build-essential
⚠️ If you use Visual Studio with MSVC, you compile with cl rather than gcc. This guide shows GCC/Clang commands first, with MSVC equivalents when needed.

Using the command line to compile and run programs

The compiler driver handles preprocessing, compiling, and linking. Start with a single-file program, then add warnings and standard selection. Keep commands simple and repeatable.

A single-file build

A single-file build looks like tyis:

# GCC
gcc -std=c23 -Wall -Wextra -O2 hello.c -o hello

# Clang
clang -std=c23 -Wall -Wextra -O2 hello.c -o hello

# Run (Unix-like)
./hello

# Run (Windows)
hello.exe

Use -std=c23 for a modern baseline. Enable warnings with -Wall -Wextra. Add -g for debug symbols when needed.

Separating compiling and linking

This is how you separate compiling and linking:

# Compile to objects
gcc -std=c23 -Wall -Wextra -O2 -c util.c -o util.o
gcc -std=c23 -Wall -Wextra -O2 -c main.c -o main.o

# Link objects into an executable
gcc util.o main.o -o app

Compiling to objects avoids rebuilding every file. The linker step produces the final program.

💡 Use -pedantic when you want extra standard conformance checks. Add platform libraries at link time with -l<name> (for example -lm for math).

Using Makefiles for simple builds

make automates rebuilds based on file timestamps. A small Makefile turns multi-file commands into named targets. Variables keep flags in one place.

A minimal portable Makefile

An example Makefile might look like this:

# file: Makefile
CC    := gcc
CFLAGS  := -std=c23 -Wall -Wextra -O2
LDFLAGS :=
TARGET  := app
SRCS  := main.c util.c
OBJS  := $(SRCS:.c=.o)

$(TARGET): $(OBJS)
	$(CC) $(OBJS) $(LDFLAGS) -o $(TARGET)

%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@

.PHONY: run clean
run: $(TARGET)
	./$(TARGET)

clean:
	$(RM) $(OBJS) $(TARGET)

Tabs are required before recipe lines. The pattern rule builds any .o from a matching .c. The run target executes the program on Unix-like systems.

Using Windows

With MSYS2 or Git Bash, the above Makefile works as written. On native Windows shells you may use mingw32-make instead of make, and replace the run recipe with a line that invokes $(TARGET).exe.

⚠️ If your project grows, consider a generator such as CMake. You keep a single project description and produce platform-native build systems.

Working with IDEs and editors

Choose an editor that respects your command-line workflow. You can keep gcc, clang, and make at the core, while the editor provides IntelliSense, code navigation, and debugging.

Using VS Code

Install the C/C++ extension. Use a simple tasks.json to call your Makefile or compiler directly. For cross-platform projects, pair VS Code with CMake Tools to configure and build out of source.

Using CLion

CLion uses CMake as the project model. You write a CMakeLists.txt, then build and debug with the integrated toolchains. CLion can target WSL, MinGW, or remote toolchains.

Other solid choices

A list of other popular options:

EditorNotes
Visual Studio (MSVC)Great Windows debugger; projects use cl and MSBuild
Code::BlocksLightweight IDE; supports GCC and Clang
Vim, Neovim, EmacsPair with clangd or ccls for completion; keep builds in make or cmake
💡 No matter the IDE, keep a working command-line build. It prevents vendor lock-in and simplifies continuous integration.