initial commit

This commit is contained in:
Gilles Grandou 2020-02-23 15:53:52 +01:00
commit 89d561e5b7
10 changed files with 375 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.build.mak
build

79
Makefile Normal file
View File

@ -0,0 +1,79 @@
######################################################################
# Makefile
#
# This makefile is the one called by user, but it's only a trampoline
# to create the build directory and call the real Makefile.build
#
# make can be invoqued with 'make build=<your_build_directory> ...'
# all other options and target are passed to the real makefile.
#
# As an exception to the rule of not modifying source directory, a
# .build.mak file is created to cache the configured build directory.
# Subsequent invocations of make could be done without passing
# 'build=...' parameter.
#
# distclean target is catched to destroy both the .build.mak and
# the whole build directory.
#
######################################################################
# build directory is cached in BUILD_MAK file between make invocations
BUILD_MAK = .build.mak
ifneq ($(wildcard $(BUILD_MAK)),)
include $(BUILD_MAK)
endif
# default build directory 'build'
build ?= build
# ($call quiet-command,CMD,MSG)
# execute CMD and display MSG
# if verbose mode is enabled (with 'make V=1`) print full CMD instead of MSG
quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
# if the target is distclean, skip allmost rules
# to doing anything which will be immediately
# deleted after
ifeq ($(filter distclean,$(MAKECMDGOALS)),)
# default target (when one invokes 'make' without target)
# so we have a non-empty target which could be catched by
# the catch-all target below.
default-all:
# The catch-all target, which pass build to the main
# makefile in the build directory.
# strip-out 'default-all' for targets' list
%: | $(build)
$(call quiet-command, \
$(MAKE) -C $(build) $(filter-out default-all,$@) \
, "MAKE $(filter-out default-all,$@)")
# Creates the buld directory
# and populates it with a link to the build makefile
$(build): | $(BUILD_MAK)
$(call quiet-command,\
mkdir -p $@; \
ln -sf $(CURDIR)/Makefile.build $@/Makefile \
, "MKBUILD $@")
# always create BUILD_MAK to cache build configuration
# but don't update it if not changed
$(BUILD_MAK): FORCE
@echo build=$(build) > $@.tmp
@cmp -s $@.tmp $@ || (mv $@.tmp $@ && echo "GEN $@")
@rm -f $@.tmp
else # if distclean
distclean:
$(call quiet-command, rm -rf $(build) $(BUILD_MAK), "DISTCLEAN $(build)")
endif # distclean
.PHONY: distclean FORCE
#ifndef V
#.SILENT:
#endif

213
Makefile.build Normal file
View File

@ -0,0 +1,213 @@
######################################################################
# Some helper functions
#
######################################################################
# $(call inspect,LIST)
# dump list of variables printing their values and their attributes
inspect = $(foreach v,$(1),$(info $(v) [$(origin $(v)),$(flavor $(v))] = $($(v))))
# $(call undefine_default,LIST)
# undefine default variables given in LIST)
undefine_default = $(foreach v,$(1),$(if $(filter default,$(origin $(v))),$(eval undefine $(v)),))
# $(call setdef_ifdef,VAR,DEFVAR)
# if DEFVAR exists, set default value of VAR to $(DEFVAR)
setdefault_ifdef = $(if $(filter undefined,$(origin $(2))),,$(eval $(1) ?= $($(2))))
# $(call clean_bool_true,VALUE)
# $(call clean_bool_false,VALUE)
# $(call clean_bool,VALUE)
# clean_bool,clean_bool_true:
# if VALUE is identified as true (true, on, yes, enable, 1, ...) returns 1
# clean_bool,clean_bool_false:
# if VALUE is identified as false (false, off, no, disable, 0, ...) returns an empty string
clean_bool_true = $(if $(filter true TRUE on ON yes YES enable ENABLE,$(1)),1,$(1))
clean_bool_false = $(if $(filter false FALSE off OFF no NO disable DISABLE 0,$(1)),,$(1))
clean_bool = $(call clean_bool_false,$(call clean_bool_true,$(1)))
# $(call quote_spaces,STR)
# return STR, surrounded by double quotes if it contains spaces
quote_spaces = $(if $(filter 0 1,$(words $1)),$1,"$1")
# $(call pathsearch,EXEC)
# returns the full path of EXEC if it exists somewhere in $PATH
# if not found, returns the unmodified EXEC
pathsearch = $(if $(filter 1,$(words $(1))),$(firstword $(wildcard $(1) $(addsuffix /$(1),$(subst :, ,$(PATH)))) $(1)),$(1))
# $(call prepend_ccache,PREFIX,EXEC)
# return 'ccache EXEC' if ccache is not already detected in EXEC
prepend_ccache = $(if $(filter ccache,$(subst /, ,$(1))),$(1),ccache $(1))
# $(call clean_path,PATH)
# return a sanitized path: remove //, trailing /
clean_path = $(subst //,/,$(patsubst %/,%,$1))
# ($call quiet-command,CMD,MSG)
# execute CMD and display MSG
# if verbose mode is enabled (with 'make V=1`) print full CMD instead of MSG
quiet-command = $(if $(V),$1,$(if $(2),@echo $2 && $1, @$1))
######################################################################
# Cached configuration support
#
# variables listed in CONFIG_VARS are stored in CONFIG_MAK file
# containing lines `cache_VAR=value`
# This file is read on subsequent invocation and set default values
# of these variables.
#
# The file is automatically generated but can be hand-edited.
#
######################################################################
CONFIG_MAK = config.mak
CONFIG_VARS = max
CONFIG_STRING = $(foreach var,$(CONFIG_VARS),$(var)=$(call quote_spaces,$($(var))))
# undefine variables which have a default value set by make itself
# (mainly CC and CXX)
$(call undefine_default,$(CONFIG_VARS))
# read the cached variables
-include $(CONFIG_MAK)
# for all undefined variables set their default values from ones
# stored in included CONFIG_MAK.
$(foreach var,$(CONFIG_VARS),$(call setdefault_ifdef,$(var),cache_$(var)))
#default (non false) values
# max ?= 10
# cleanup "False" boolean values, set them to empty value
$(foreach var,$(CONFIG_VARS),$(eval override $(var):=$(call clean_bool_false,$($(var)))))
# print out user configuration
# (only once in case the makefile has been reloaded)
ifndef MAKE_RESTARTS
$(info CONF $(CONFIG_STRING))
endif
######################################################################
# Flags generation
#
######################################################################
CFLAGS =
ifdef max
CFLAGS += -DFIBO_MAX=$(max)
endif
######################################################################
# Source and objects collection
#
######################################################################
.SUFFIXES:
.SUFFIXES: .c .o
ifdef srcdir
srcdir := $(patsubst %/,%,$(srcdir))
else
srcdir := $(patsubst %/,%,$(dir $(realpath $(firstword $(MAKEFILE_LIST)))))
endif
INCLUDES := src \
src/version \
src/fibo
SRCS := src/main.c \
src/version/version_tools.c \
src/fibo/fibo.c
OBJS += src/version/version.o
OBJS += $(SRCS:%.c=%.o)
VPATH += $(srcdir)
VPATH += .
CFLAGS += $(addprefix -I$(srcdir)/,$(INCLUDES))
GENERATED += $(OBJS)
GENERATED += $(DEPDIR)
GENERATED += src/version/version.c
GENERATED += fibo
######################################################################
# Dependencies tracking
#
######################################################################
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td #generate dependency file in a temporary file
#Rename the generated temporary dependency file to the real dependency file.
#We do this in a separate step so that failures during the compilation wont leave a corrupted dependency file
#in some rare cases dep file can end up beeing newer than object, final touch ensures that object will always
#be newer.
POSTCOMPILE = @mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d && touch $@
CFLAGS += $(DEPFLAGS)
######################################################################
# Targets
#
######################################################################
.SECONDEXPANSION:
all: fibo
fibo: $(OBJS)
$(call quiet-command, $(CC) $^ -o $@, "LINK $@")
%.c: %.c.in FORCE
@mkdir -p $(@D)
@sed -e 's#@@GIT_SHA1@@#$(shell git describe --all --long --dirty)#' $< > $@.tmp
@cmp -s $@.tmp $@ || (echo "GEN $@"; mv $@.tmp $@)
@rm -f $@.tmp
.PRECIOUS: src/version/version.c
%.o: %.c | $(DEPDIR)/$$(@D)/
$(call quiet-command, $(CC) $(CFLAGS) $(IFLAGS) -o $@ -c $<, "CC $@")
$(POSTCOMPILE)
%/:
@mkdir -p $@
# Generate the cached configuration make script
# - always generated
# - file is written out only if modified
$(CONFIG_MAK): FORCE
@echo "# automatically generated" > $@.tmp
@$(foreach var,$(CONFIG_VARS),echo cache_$(var)=$($(var)) >> $@.tmp;)
@cmp -s $@.tmp $@ || (echo "GEN $@"; mv $@.tmp $@)
@rm -f $@.tmp
$(OBJS): $(MAKEFILE_LIST)
inspect:
$(call inspect,srcdir)
$(call inspect,SRCS)
$(call inspect,OBJS)
$(call inspect,SHELL)
clean:
$(call quiet-command, rm -rf $(GENERATED), "CLEAN")
distclean:
$(call quiet-command, rm -rf $(GENERATED) $(CONFIG_MAK) Makefile, "DISTCLEAN")
.PHONY: FORCE clean inspect
# include all potential dependencies files
-include $(patsubst %,$(DEPDIR)/%.d,$(basename $(SRCS)))

37
src/fibo/fibo.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdlib.h>
#include <stdio.h>
#include "fibo.h"
static int *fibo;
static u_int64_t fibo_size;
void fibo_init(int size)
{
fibo = calloc(size, sizeof(u_int64_t));
if (fibo == NULL) {
fprintf(stderr, "ERROR: cannot allocate memory\n");
exit(1);
}
fibo_size = size;
}
void fibo_compute(void)
{
fibo[0] = 1;
fibo[1] = 1;
for (int i = 2; i < fibo_size; i++)
fibo[i] = fibo[i-2] + fibo[i-1];
}
void fibo_print()
{
printf("fibo:");
for (int i=0; i<fibo_size; i++)
printf(" %lu", fibo[i]);
printf("\n");
}

5
src/fibo/fibo.h Normal file
View File

@ -0,0 +1,5 @@
void fibo_init(int size);
void fibo_compute(void);
void fibo_print(void);

21
src/main.c Normal file
View File

@ -0,0 +1,21 @@
#include "version_tools.h"
#include "fibo.h"
#ifdef FIBO_MAX
#define MAIN_FIBO_MAX FIBO_MAX
#else
#define MAIN_FIBO_MAX 10
#endif
int main(int argc, char *argv[])
{
print_version();
fibo_init(MAIN_FIBO_MAX);
fibo_compute();
fibo_print();
return 0;
}

3
src/version/version.c.in Normal file
View File

@ -0,0 +1,3 @@
const char* git_sha1 = "@@GIT_SHA1@@";

4
src/version/version.h Normal file
View File

@ -0,0 +1,4 @@
extern const char *git_sha1;

View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include "version.h"
void print_version(void)
{
printf("version: %s\n", git_sha1);
}

View File

@ -0,0 +1,3 @@
void print_version(void);