gnu make - force a script to run at the beginning of a makefile, and display its output -


i have script generates version.h file various details particular build

the script runs various commands, such as:

readonly version=$(git describe --always --dirty --long --tags) readonly num_commits=$(git rev-list head | wc -l | bc) readonly branch=$(git rev-parse --abbrev-ref head) readonly ahead_by=$(git log --oneline origin/${branch}..${branch} | wc -l | bc) readonly num_untracked=$(git ls-files --exclude-standard --others --full-name -- . | wc -l | bc) readonly hostname=$(hostname) 

it writes temporary file, checks against pre-existing generated file, , if different, overwrites old version.h new one.

#pragma once  /*  * version information  *  * - generated file - not edit  */  namespace foo { namespace app {  static const char version[]       = "26b75cd"; static const char num_commits[]   = "224"; static const char branch[]        = "master"; static const char ahead_by[]      = "0"; static const char num_untracked[] = "0"; static const char user[]          = "steve"; static const char hostname[]      = "steve-linux"; static const char build_variant[] = "debug"; static const char build_date[]    = __date__ " "  __time__;  }} 

it prints stdout when file updated

version updated: 26b75cd 

the version script should first thing run, , should run every time makefile invoked.

currently achieve using simply expanded variable in makefile

new_ver := $(shell ./app/gen_version.sh $(build)) 

it works, output script captured in new_var, , unable display output.

it's acceptable trade-off (not displaying new version), in ideal world display script output.

i'm unsure whether .phony target added default all target work, because every app has own target can build that.

define do-make-bin     binaries += $(addprefix $(bin_dir),$1)     bin_sources += $2      # target users can call 'make <bin-name>' , build bin , dependencies     $1: $(addprefix $(bin_dir),$1)      # target build actual binary     $(addprefix $(bin_dir),$1): $(call src_to_obj,$2) $(addsuffix .so,$(addprefix $(lib_dir)lib,$3)) $(addsuffix .a,$(addprefix $(lib_dir)lib,$4))     @$(cxx) $(call src_to_obj,$2) -l/usr/lib -l$(sdk_lib_dir) -l$(lib_dir) $(target_link_flags) -wl$(,)-bstatic $(addprefix -l,$4) $(addprefix -l,$6) -wl$(,)-bdynamic -wl$(,)-rpath$(,)$(rpath) $(linkpath) -l$(lib_dir) $(sdk_libs) $(tcmalloc_libs) -lpthread -lrt $(addprefix -l,$3) $(addprefix -l,$5) -rdynamic -o $$@ endef 

calling make foo should still check whether version.h needs updated

the way ensure runs before every target, if restrict normal makefile methods, put content in recipe , make target builds content prerequisite of every target in makefile. while can done in such way doesn't cause rebuild every time, it's gross. plus, won't let put output variable new_ver (you want display don't whether need in variable well).

however, if problem aren't displaying value of new_ver, that's trivially solved:

new_ver := $(shell ./app/gen_version.sh $(build)) $(info $(new_ver)) 

Comments