Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 18 additions & 20 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
name: C++ Build
name: C++ CI

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build:
build-and-run:
runs-on: ubuntu-latest

strategy:
matrix:
compiler: [g++]

env:
ASAN_OPTIONS: detect_leaks=1 # automatically detect memory leaks
steps:
- name: Checkout repo
# 1. Checkout repo
- name: Checkout code
uses: actions/checkout@v4

# 2. Install build tools
- name: Install build tools
run: |
sudo apt-get update
sudo apt-get install -y build-essential

- name: Build all examples
run: |
make
sudo apt-get install -y build-essential g++ clang

- name: Run examples
# 3. Build and run all examples dynamically
- name: Build and Run
run: |
for dir in */ ; do
if [ -f "$dir/Makefile" ]; then
echo "Running $dir"
(cd "$dir" && make run || true)
fi
for san in address thread undefined; do
echo "=== Building all examples with sanitizer $san ==="
make SANITIZE=$san
echo "=== Running all examples with sanitizer $san ==="
make run
done

- name: Clean
- name: Clean up build artifacts
run: |
make clean
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
.o
# Object files
*.o

# Executable
thread_safe_queue
unique_ptr_basics
*.out

# Backup files
*~
*.swp

# CMake / IDE files
CMakeFiles/
CMakeCache.txt
*.idea/
*.vscode/
30 changes: 27 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,37 @@
# ======================================
# Top-level Makefile for cpp-coding-exercise
# ======================================

# Auto-detect all subdirectories that contain a Makefile
SUBDIRS := $(dir $(wildcard */Makefile))

.PHONY: all clean $(SUBDIRS)
# Default sanitizer (can be overridden)
SANITIZE ?= address

.PHONY: all clean run $(SUBDIRS)

# --------------------------
# Build all examples
# --------------------------
all: $(SUBDIRS)

$(SUBDIRS):
$(MAKE) -C $@
@echo "=== Building $@ with SANITIZE=$(SANITIZE) ==="
$(MAKE) -C $@ SANITIZE=$(SANITIZE)

# --------------------------
# Run all examples (optional)
# --------------------------
run:
@for dir in $(SUBDIRS); do \
echo "=== Running $$dir ==="; \
(cd $$dir && $(MAKE) SANITIZE=$(SANITIZE) run) || exit 1; \
done

# --------------------------
# Clean all examples
# --------------------------
clean:
for dir in $(SUBDIRS); do \
@for dir in $(SUBDIRS); do \
$(MAKE) -C $$dir clean; \
done
25 changes: 22 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ Runnable examples expose a `run` target:
make run
```

This keeps CI safe (build-only by default) while allowing local execution.
`make run` on top level will run all built targets.

---

Expand All @@ -97,11 +97,11 @@ make clean

## Shared build configuration

Common compiler settings live in `common.mk`:
Common compiler settings live in [common.mk](./common.mk):

```make
CXX := g++
CXXFLAGS := -std=c++20 -O2 -Wall -Wextra
CXXFLAGS := -std=c++20 -Wall -Wextra
```

Individual examples may extend this, e.g.:
Expand All @@ -112,6 +112,25 @@ CXXFLAGS += -pthread

---

## Address Sanitizer Check
The Address Sanitizer is enabled by default to ensure there is no memory leaks or other memory problems.

```make
# Builds with AddressSanitizer automatically
make

# ThreadSanitizer
make SANITIZE=thread

# UndefinedBehaviorSanitizer
make SANITIZE=undefined

# No sanitizers
make SANITIZE=
```

---

## Continuous Integration

GitHub Actions automatically builds all examples on:
Expand Down
48 changes: 47 additions & 1 deletion common.mk
Original file line number Diff line number Diff line change
@@ -1,2 +1,48 @@
# ======================================
# common.mk - shared compiler flags
# ======================================

CXX := g++
CXXFLAGS := -std=c++20 -O2 -Wall -Wextra
OPTFLAGS ?= -O1 -g # Safe for ASAN/TSAN (default)

# --------------------------
# Sanitizer selection
# --------------------------
# Default: AddressSanitizer
SANITIZE ?= address

ifeq ($(SANITIZE),address)
SAN_FLAGS := -fsanitize=address
else ifeq ($(SANITIZE),thread)
SAN_FLAGS := -fsanitize=thread
else ifeq ($(SANITIZE),undefined)
SAN_FLAGS := -fsanitize=undefined
else ifeq ($(SANITIZE),)
SAN_FLAGS :=
else
$(error Unknown SANITIZE=$(SANITIZE))
endif

# --------------------------
# Compiler / Linker flags
# --------------------------
CXXFLAGS := -std=c++20 -Wall -Wextra $(OPTFLAGS) $(SAN_FLAGS)
LDFLAGS := $(SAN_FLAGS)

# --------------------------
# Usage notes
# --------------------------
# Local build (default): ASAN enabled
# $ make
#
# Override for ThreadSanitizer:
# $ make SANITIZE=thread
#
# Override for UBSAN:
# $ make SANITIZE=undefined
#
# Disable sanitizers (rare):
# $ make SANITIZE=
#
# LDFLAGS are automatically applied in example Makefiles:
# $(CXX) $(CXXFLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS)