makemake
This repository contains a makefile for C projects. It is configured out-of-the-box for C17 using GCC, enforces extremely strict compilation standards (treating all warnings as errors), manages out-of-source builds, and includes automatic dependency tracking and versioning.
Setup Tutorial
Follow these steps to bootstrap your project from scratch using this Makefile:
1. Initialize the Project
Place the Makefile in the root of your new (and empty) project directory. Note that the output executable will be named after your root directory.
Run the following command to scaffold the required directory structure:
make init
What this does: Creates the config/, includes/, output/, and source_code/ directories. It also generates a starter main.c and initializes the versioning and file list configuration files.
2. Write Your Code
- Place all your
.cfiles inside thesource_code/directory (or subdirectories within it). - Place all your
.hfiles inside theincludes/directory.
3. Synchronize the Build System
Whenever you add, rename, or delete a .c or .h file, you must tell the Makefile to update its tracking lists:
make synch
What this does: Scans your directories and updates config/source_code_list and config/header_list.
4. Build the Project
Compile your code for the first time in debug mode:
make debug
Your compiled executable will be located in the output/ directory, named <your_folder_name>_00.000.00.0000 (or whatever the current version string is).
Project Structure
After running make init and building, your project will look like this:
my_project/ # Root folder (dictates the executable name)
├── Makefile # The build script
├── config/ # Build tracking files (auto-generated)
│ ├── header_list
│ ├── source_code_list
│ └── version
├── includes/ # Place all your .h files here
├── source_code/ # Place all your .c files here
│ └── main.c
└── output/ # Build artifacts (ignored by git ideally)
├── obj_debug/ # .o and .d files for debug builds
├── obj_release/ # .o and .d files for release builds
└── my_project_version # The final compiled executables
Configuration & Defaults
This Makefile is heavily configured for safety and strictness. Here is how to modify the defaults to suit your needs:
1. Changing the C Standard
The project defaults to C17. To change this to C11, C99, or C2x:
- Open the
Makefile. - Locate the
CFLAGS = -std=c17 \line. - Change
-std=c17to-std=c11(or your preferred standard).
2. Changing the Compiler
The default compiler is GCC. To use Clang (which is highly recommended for macOS users or for its excellent static analyzer):
- Locate
CC = gccat the top of the file. - Change it to
CC = clang.
3. Modifying Warning Strictness (Fixing Compilation Blocks)
By default, this Makefile includes -Werror, which treats all warnings as errors and halts compilation. It also includes an extensive list of strict warnings (like -Wconversion, -Wshadow, -Wpadded, etc.).
- To allow warnings to pass without failing the build: Remove the
-Werror \line from theCFLAGSblock. - To remove specific strict checks: Simply delete or comment out the specific flag (e.g.,
-Wmissing-prototypes \) from theCFLAGSlist.
4. Modifying Debug and Release Flags
You can tweak optimization levels and sanitizers at the top of the file:
- Debug (
DEBUG_FLAGS): Defaults to-g3 -O0 -fsanitize=undefined -fno-omit-frame-pointer. You can add Address Sanitizer by appending-fsanitize=address. - Release (
RELEASE_FLAGS): Defaults to-O2 -D NDEBUG. (NDEBUGstrips outassert()calls). If you want maximum optimization, you can change-O2to-O3or-Ofast(use-Ofastwith caution as it breaks strict IEEE compliance for math).