thecodingidiot.com

The InfiniteSetup

Setup

Install SDL2, write the Makefile, and get a window open before any math. Confirm the toolchain works before touching the iteration.


Install SDL2

sudo apt install libsdl2-dev

Verify the installation:

sdl2-config --version

A version string appears (2.0.x or later). If the command is not found, the package did not install — check with apt list --installed | grep libsdl2.


Makefile

NAME    = infinite
 
CC      = gcc
CFLAGS  = -Wall -Wextra -Werror -std=c99 $(shell sdl2-config --cflags)
LDFLAGS = $(shell sdl2-config --libs) -lm
 
SRCS    = main.c mandelbrot.c julia.c view.c colour.c render.c
OBJS    = $(SRCS:.c=.o)
 
all: $(NAME)
 
$(NAME): $(OBJS)
	$(CC) $(OBJS) $(LDFLAGS) -o $(NAME)
 
%.o: %.c
	$(CC) $(CFLAGS) -c $< -o $@
 
clean:
	rm -f $(OBJS)
 
fclean: clean
	rm -f $(NAME)
 
re: fclean all
 
.PHONY: all clean fclean re

sdl2-config --cflags expands to the include path SDL2 needs (-I/usr/include/SDL2 -D_REENTRANT). sdl2-config --libs expands to the linker flags (-lSDL2). Using the config script instead of hardcoding paths keeps the Makefile portable across SDL2 installations.


game.h

Create game.h with the shared constants and struct forward declarations. No function prototypes yet — add those as each file is written.

#ifndef GAME_H
#define GAME_H
 
#include <stdint.h>
 
#define WIDTH    800
#define HEIGHT   600
#define MAX_ITER 100
 
typedef struct s_view  view_t;
typedef struct s_state state_t;
 
#endif

WIDTH and HEIGHT control the window size and pixel buffer. Adjust downward if renders feel slow; the math does not change.

Struct and typedef. typedef struct s_view view_t; creates an alias: view_t means struct s_view. The full definition — the member fields — comes later, in view.h. Declaring the name here without defining its contents is a forward declaration: other headers can reference view_t in a pointer or member without knowing its internals, which prevents circular include dependencies.

game.h includes nothing from SDL2 and nothing from <math.h>. That is the platform separation rule in practice: every file that includes game.hview.c, mandelbrot.c, julia.c, colour.c — stays SDL2-free and compiles without a display server. SDL2 belongs only in render.h (which includes it explicitly) and in main.c. Files that use floating-point math functions include <math.h> directly; the -lm in LDFLAGS above tells the linker to bring in the math library at link time regardless of which source file pulls the header.


Window stub

Create main.c with a minimal SDL2 program that opens a window, renders it black, and exits cleanly on SDL_QUIT (closing the window or pressing Escape):

#include <SDL2/SDL.h>
#include "game.h"
 
int main(void)
{
    SDL_Window   *win;
    SDL_Renderer *ren;
    SDL_Event     ev;
    int           running;
 
    if (SDL_Init(SDL_INIT_VIDEO) != 0) {
        SDL_Log("SDL_Init: %s", SDL_GetError());
        return (1);
    }
    win = SDL_CreateWindow("infinite", SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED, WIDTH, HEIGHT, 0);
    if (!win) {
        SDL_Log("SDL_CreateWindow: %s", SDL_GetError());
        SDL_Quit();
        return (1);
    }
    ren = SDL_CreateRenderer(win, -1, SDL_RENDERER_ACCELERATED);
    if (!ren) {
        SDL_Log("SDL_CreateRenderer: %s", SDL_GetError());
        SDL_DestroyWindow(win);
        SDL_Quit();
        return (1);
    }
    running = 1;
    while (running) {
        while (SDL_PollEvent(&ev)) {
            if (ev.type == SDL_QUIT)
                running = 0;
            if (ev.type == SDL_KEYDOWN
                    && ev.key.keysym.sym == SDLK_ESCAPE)
                running = 0;
        }
        SDL_SetRenderDrawColor(ren, 0, 0, 0, 255);
        SDL_RenderClear(ren);
        SDL_RenderPresent(ren);
    }
    SDL_DestroyRenderer(ren);
    SDL_DestroyWindow(win);
    SDL_Quit();
    return (0);
}
make
./infinite

A black 800 × 600 window opens. Pressing Escape or closing the window exits cleanly. If the compile fails with SDL2/SDL.h: No such file or directory, SDL2 is not installed or sdl2-config is not finding it.

The pattern — init, create window, create renderer, event loop, clean shutdown — is the foundation. Every SDL2 chapter reuses it.