From 89d561e5b78044ddbd36938206f8d86c27543ae1 Mon Sep 17 00:00:00 2001 From: Gilles Grandou Date: Sun, 23 Feb 2020 15:53:52 +0100 Subject: [PATCH] initial commit --- .gitignore | 2 + Makefile | 79 +++++++++++++ Makefile.build | 213 ++++++++++++++++++++++++++++++++++++ src/fibo/fibo.c | 37 +++++++ src/fibo/fibo.h | 5 + src/main.c | 21 ++++ src/version/version.c.in | 3 + src/version/version.h | 4 + src/version/version_tools.c | 8 ++ src/version/version_tools.h | 3 + 10 files changed, 375 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 Makefile.build create mode 100644 src/fibo/fibo.c create mode 100644 src/fibo/fibo.h create mode 100644 src/main.c create mode 100644 src/version/version.c.in create mode 100644 src/version/version.h create mode 100644 src/version/version_tools.c create mode 100644 src/version/version_tools.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e15c464 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.build.mak +build diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d4cf5aa --- /dev/null +++ b/Makefile @@ -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= ...' +# 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 diff --git a/Makefile.build b/Makefile.build new file mode 100644 index 0000000..b0ee594 --- /dev/null +++ b/Makefile.build @@ -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))) + + diff --git a/src/fibo/fibo.c b/src/fibo/fibo.c new file mode 100644 index 0000000..6a52bb4 --- /dev/null +++ b/src/fibo/fibo.c @@ -0,0 +1,37 @@ +#include +#include +#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 +#include "version.h" + + +void print_version(void) +{ + printf("version: %s\n", git_sha1); +} diff --git a/src/version/version_tools.h b/src/version/version_tools.h new file mode 100644 index 0000000..b579900 --- /dev/null +++ b/src/version/version_tools.h @@ -0,0 +1,3 @@ + +void print_version(void); +