--- title: Compiling [MAKE / GCC] description: draft: false tags: - c - programming author: TrudeEH showToc: true --- A compiler converts `C` code into machine code in 4 steps: 1. **Preprocessing** (Convert all preprocessor instructions (`#…`) to C code.) 2. **Compiling** (Convert `C` code to assembly.) 3. **Assembling** (Compile the necessary libraries.) 4. **Linking** (Merge the compiled code with the compiled libraries.) ## Libraries Libraries are pre-written collections of code that can be reused in other programs. On *UNIX* systems, they are usually located in the `/lib/` and `/usr/include` directories. ### Math.h For example, `math.h` is very useful to implement complex arithmetic operations. ```C #include double A = sqrt(9); double B = pow(2, 4); int C = round(3.14); int D = ceil(3.14); int E = floor(3.99); double F = fabs(-100); double G = log(3); double H = sin(45); double I = cos(45); double J = tan(45); ``` ### Using Libraries To use a library, we first have to include it in the `C` code. ```C #include // cs50.h library will be included. ``` Then, the library must be linked at compile time (unless it is part of the C standard). ```Shell gcc -o hello hello.c -lcs50 ./hello ``` ## Optimization Flags - `-O2` Optimize for speed - `-O3` Optimize for speed aggressively - `-Os` Optimize for size - `-Og` Optimize for debugging - `-Oz` Optimize for size aggressively ## Make `Make` Is a build automation tool that automates the process of compiling, linking and building executables. An example `Makefile` (for an app using `GTK4`) could be as follows: ```Makefile CC = gcc CFLAGS = $(shell pkg-config --cflags gtk4) LIBS = $(shell pkg-config --libs gtk4) hello: hello.c $(CC) $(CFLAGS) -o hello hello.c $(LIBS) -O2 debug: hello.c $(CC) $(CFLAGS) -o hello hello.c $(LDFLAGS) -Wall -Wextra -Og -g clean: rm -f hello ``` ```Shell make # Compiles hello.c make debug # Compiles hello.c using debug flags make clean # Removes the executable (hello) generated by the make command. ``` ## Meson While `make` automates compiling, on larger projects, makefiles can grow hard to read quickly, and dependency resolution has to be done using external tools (such as `pkg-config`). Meson is a more modern alternative, which is faster, and uses declarative syntax (describe *what* to build, instead of *how* to build it). Meson can automatically manage dependencies, header files, and compiler flags. When `meson` is executed, it generates a `ninja.build` file, which is then parsed by `ninja`, a lower-level build tool. ```meson.build project('hello', 'c') gtk4_dep = dependency('gtk4') executable('hello', 'hello.c', dependencies: gtk4_dep) ``` ```bash mkdir build meson setup build # Generate files for Ninja in the build dir meson compile -C build # Compile the project (same as `ninja -C build`) ./build/hello ninja clean -C build # Clean executable files in the build directory ```