/c-template

My useful and not-asked-for C project template.

Primary LanguageMakefileMIT LicenseMIT

Henrique’s useful C project template

Hello friend, and welcome to my C project template. It’s like the C++ one, but in C! Who would’ve guessed, right?

I’ve created this repo mainly to keep my awesome Makefile somewhere when I finally put the C++ version of my template thingy on CMake. So, enjoy.

Table of contents

Project structure

I’ve structured the template according to the following directories:

src/
The sources directory. Here lies all .c files and its private headers, organized inside this folder in sub-folders if the source-code belongs to a module or namespace. If the file rests in the root of this directory its considered a main file, which will be compiled as one of the target executables.
include/
The public headers directory. This is for later external project use, as shown by the folder with the same name as the project.
bin/
The .o directory. Here will be dumped all compiled objects.
build/
The executables directory. Here is the final resting place of the project targets.
lib/
The .a directory. Dump here any static library you may be using.
scripts/
The .sh directory. Any script that needs to be used during the compiling or dependency handling or whatever should stay here.

Build

To build, just run this single line in the root of this repository:

make

This is the case as the default target for my Makefile is the all rule.

To use all cores in your machine, just add the following flag:

make -j<NUMBER_OF_CORES>

# like
make -j4

In order to find out how many cores you have, run any of the following command in your shell:

# either
nproc
# or
lscpu
# or
cat /proc/cpuinfo

Also, here’s an example of all the rules you can target (and, therefore, call my Makefile with):

.DEFAULT_GOAL = all

all: deps $(TARGET)

clean:
    rm -f $(OBJ_DIR)/*.o $(INC_DIR)/*~ $(TARGET) *~ *.o

redo: clean all

help:
    @echo "c-template's project Makefile."
    @echo
    @echo "Utilization example:"
    @echo " make <TARGET> ['DEBUG=true']"
    @echo
    @echo "@param TARGET"
    @echo " Can be any of the following:"
    @echo " all - builds the project (DEFAULT TARGET)"
    @echo " clean - cleans up all binaries generated during compilation"
    @echo " redo - cleans up and then builds"
    @echo " help - shows the utilization example"
    @echo
    @echo "@param 'DEBUG=true'"
    @echo " When present, the build will happen in debug mode."

Dependency management

I currently handle this stuff inserting manually into the Makefile a line defining URLs to the headers (yes, headers! I don’t know how to support any bigger-than-an-one-file dependency), which then gets evaluated by the scripts/build.sh script, that curls them and adds them to the include folder.

Here is the script by the way:

cd include

for par in "$@"; do
    dep=($par)

    name=${dep[0]}
    dir="$name"
    target=("${dep[@]:1}")

    if [ ! -d $dir ]; then
        echo "=> Dependency '$name' not found!"
        mkdir $dir
        cd $dir

        for url in "${target[@]}"; do
            echo "==> Downloading $(basename $url)..."
            curl -O -L $url
            echo
        done

        echo "=> Finished downloading '$name'!"
        echo
        cd ..
    fi
done

cd ..

Contact

You can contact me at:

hcpsilva@inf.ufrgs.br