Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- There isn't one "official" standard dictated by `gcc`, but the C community has coalesced around a clean, conventional directory structure that scales well from small tools to massive projects.
- Here is the standard, production-ready project structure:
- ```text
- my_c_project/
- ├── bin/ # Compiled binary executables (ignored by git)
- ├── build/ # Intermediate object files (.o, .d) (ignored by git)
- ├── include/ # Public header files (.h)
- │ └── my_project/ # Optional namespace folder for headers
- │ └── utils.h
- ├── src/ # Source code (.c files) and private internal headers
- │ ├── main.c
- │ └── utils.c
- ├── tests/ # Test scripts and source files
- │ └── test_main.c
- ├── .gitignore
- ├── LICENSE
- ├── Makefile # Build script at the root
- └── README.md
- ```
- ---
- ## 1. Where should `main.c` go?
- **Put `main.c` inside `src/`.** Keep your root directory clean for build configs, documentation, and configuration files (`Makefile`, `README.md`, `.gitignore`).
- * **`src/`**: Houses all implementation files (`.c`), including `main.c`.
- * **`include/` vs `src/` for headers**:
- * Put **public headers** (interfaces meant to be shared or exported) in `include/`.
- * Put **private headers** (internal headers only used by code inside `src/`) right alongside the `.c` files inside `src/`.
- ---
- ## 2. Where should the `Makefile` go?
- **Place the `Makefile` in the project root.**
- Having the Makefile at the root lets you build the entire project by just typing `make` from the main directory. A clean Makefile will compile objects into a `build/` directory and place the final output in `bin/`.
- Here is a robust, production-ready starter `Makefile` using `gcc` that handles auto-creating directories and tracking header dependencies:
- ```makefile
- # Compiler and Flags
- CC := gcc
- CFLAGS := -Wall -Wextra -std=c11 -pedantic -Iinclude
- DEPFLAGS := -MMD -MP
- # Directories
- SRC_DIR := src
- BUILD_DIR := build
- BIN_DIR := bin
- # Target Binary Name
- TARGET := $(BIN_DIR)/my_program
- # Discover all .c files in src/ and map them to .o files in build/
- SRCS := $(wildcard $(SRC_DIR)/*.c)
- OBJS := $(SRCS:$(SRC_DIR)/%.c=$(BUILD_DIR)/%.o)
- DEPS := $(OBJS:.o=.d)
- # Default Rule
- all: $(TARGET)
- # Link the executable
- $(TARGET): $(OBJS) | $(BIN_DIR)
- $(CC) $(OBJS) -o $@
- # Compile source files to object files
- $(BUILD_DIR)/%.o: $(SRC_DIR)/%.c | $(BUILD_DIR)
- $(CC) $(CFLAGS) $(DEPFLAGS) -c $< -o $@
- # Create directories if they don't exist
- $(BUILD_DIR) $(BIN_DIR):
- mkdir -p $@
- # Clean build artifacts
- clean:
- rm -rf $(BUILD_DIR) $(BIN_DIR)
- # Include automatically generated dependency files (.d)
- -include $(DEPS)
- .PHONY: all clean
- ```
- ---
- ## 3. Important Tips for `gcc`
- 1. **`-Iinclude` Flag:** When invoking `gcc`, use the `-Iinclude` flag so your `#include` directives search the `include/` directory automatically. Inside your source files, write `#include "utils.h"` instead of relative paths like `#include "../include/utils.h"`.
- 2. **Auto-Dependencies (`-MMD -MP`):** The Makefile snippet above generates `.d` files automatically. This ensures that if you edit a `.h` file, `make` re-compiles only the `.c` files that depend on it.
- 3. **Ignore Build Artifacts:** Add `bin/` and `build/` to your `.gitignore` so generated binaries aren't pushed to source control.
Advertisement
Add Comment
Please, Sign In to add comment