My take on setting up a nice environment for developing C (no C++) on MacOS.
-
CMake
Like it or not, it's the most widely used tool for building C.
Without reinventing the wheel, I followed the project structure recommended by this book. -
googletest
Again, most popular tool, so I sticked to it.
The setup with CMake was a breeze.
Truth being told, the most popular unit-testing framework is "I don't write unit tests for C", followed by "I write unit tests, but I don't use any framework", which you may decide to believe. -
clang-tidy
Static-analysis tool that catches a good amount of mistakes at copmile-time.
Unfortunately, it doesn't come preinstalled on Mac, but you can work it around. -
Sanitizers
Address Sanitizer (ASan), Undefined Behaviour Sanitizer (UBSan), and Thread Sanitizer (TSan) for runtime analysis.
Here and here for more info. -
Remote-Containers
Thanks to the VSCode Remote Containers extension, you can try your application in a Docker container running Ubuntu
20.4
. -
valgrind, strace, ltrace
These tools aren't available on Mac, but you can use them inside the Docker container.
You may use that Docker image to play around withgcc
andgdb
too.
Install these programs on your machine:
- CMake
- Docker
- clang-tidy
PS: To install clang-tidy
, install llvm
with Homebrew first, then add this alias to the .bashrc
:
alias clang-tidy='/opt/homebrew/opt/llvm/bin/clang-tidy'
Then install these VSCode extensions:
- ms-vscode.cpptools
- ms-vscode.cmake-tools
- ms-vscode-remote.remote-containers
Everything should work out of the box: building, running, tests, and using the integrated debugger.
If you're not familiar with the VSCode extension cmake-tools,
this tutorial will help you with the first steps.
If you want to develop using the remote container, open the Command Palette and type Remote-Containers: Reopen in Container
(the Docker daemon should be running already).
Then delete the build
directory, and build the project again.
Finally, for strace, ltrace, and valgrind, open the remote container and:
valgrind path-to-executable
strace path-to-executable
ltrace path-to-executable
gdb path-to-executable
Indeed, but for most use cases it's all macros and doesn't look much different from regular C code.
-
A very good list of compiler warnings you may want to add:
http://fastcompression.blogspot.com/2019/01/compiler-warnings.html -
Here's a tiny program that you can use to try out the Address Sanitizer.
Copy it intoapps/main.c
, select theAsan
variant, build, and run it.
#include <stdlib.h>
int main()
{
int *x = malloc(10 * sizeof(int));
free(x);
return x[5];
}
// TODO LORIS: maybe link the STC library, useful for general purpose programs
// TODO LORIS: change the testing library, see the "Testing" section here: pikestyle