Learn C the Hard Way
General Project Structure
A general C project structure with a well-functioning Makefile, automated tests(unit test):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19.
├── bin
├── build
│ ├── libYOUR_LIBRARY.a
│ └── libYOUR_LIBRARY.so
├── LICENSE
├── Makefile
├── README.md
├── src
│ ├── libex29.c
│ └── libex29.o
└── tests
├── libex29_tests
├── libex29_tests.c
├── minunit.h
├── runtests.sh
└── tests.log
5 directories, 13 filesFor details inside of each file, see down below.
Makefile
1 |
|
This is quite a large Makefile, containing mechanisms which allow automatic build and test process.
In this blog, I will only focus on the important parts as I am too lazy to explain it thoroughly. It’s just doesn’t worth it.
Main Logic
- This Makefile automatically collects all C source files from the
src/
directory and its subdirectories, compiles them into object files, and bundles them into both static (.a) and shared (.so) library formats while also setting up a testing framework - all orchestrated through a hierarchy of targets whereall
builds everything. dev
provides a debug-friendly version, andclean
removes all generated files.
Tests
This Makefile contains logic for automatic tests, right after the build process.
The test process is actually written in
tests/runtests.sh
:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20# color definition(see folder down below)
# ...
echo -e "${BG_BLUE}${FG_ORANGE} Running unit tests:${NONE}"
for i in tests/*_tests
do
if test -f $i; then
if $VALGRIND ./$i 2 >> tests/tests.log; then
echo -e "${FG_GREEN} $i PASS${NONE}"
else
echo -e "${FG_RED}ERROR in test $i:${NONE}"
echo -e "${FG_RED}-----${NONE}"
tail tests/tests.log
exit 1
fi
fi
done
echo ""
Color_Definition
1 | # Foreground colors |
Stolen from debug.h
from PA :)
Note:
Variable $VALGRIND
in the script should be defined in the Makefile when running make valgrind
.
When running make
or make test
, $VALGRIND
will be empty/undefined, so the command simply runs ./$i
.
Also, the 2
in line if $VALGRIND ./$i 2 >> tests/tests.log; then
refers to file descriptor 2, which is stderr(standard error).
In Unix/Linux systems, there are three standard file descriptors:
0: stdin (standard input)
1: stdout (standard output)
2: stderr (standard error)
So 2 >>
means “append stderr output to the specified file”. This ensures that error messages and debugging information (which typically go to stderr) are captured in tests/tests.log.
Debug Helper
dbg.h/log.h
dbg.h
:
1 |
log.h
:
1 |
To Be Continued…
- Title: Learn C the Hard Way
- Author: Last
- Created at : 2024-10-30 17:14:52
- Link: https://blog.imlast.top/2024/10/30/Learn-C-the-Hard-Way/
- License: This work is licensed under CC BY-NC-SA 4.0.