Make: syntax error near unexpected token `--initialization' - makefile

I am trying to write 'if' check in define directive in one of our make file.
Actually I am trying to check platform and proceed with environment setting.
define templ_32
mkdir -p $(#D)
if [ "$(PLAT)" = "x86_64" ]; then env PERLLIB=$(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/5.10.0 --template $<; fi
if [ "$(PLAT)" = "aarch64" ]; then env PERLLIB=$(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/5.8.0 --template $<; fi
endef
I am using above define directive in one of my target recipe as follows.
some/%.c: test/tmpl-%.c $(NEW_DATA32)
$(templ_32) --initialization $(NEW_DATA32)
When I run the build with above changes. I am getting error :
/bin/sh: -c: line 0: syntax error near unexpected token `--initialization'
And also from the log I am seeing whole 'if' condition as follows.
if [ "aarch64" = "x86_64" ]; then env PERLLIB=$(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/5.8.0 --template /test/deploy/tmpl-kt.c ; fi --initialization /work/deploy/test.pl
From my success log which has no conational 'if' statements I can see only
env PERLLIB=$(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/5.8.0 --template /test/deploy/tmpl-kt.c --initialization /work/deploy/test.pl
I don't want to get the 'if' checks along with 'env' command.. I am only interested in
env PERLLIB=$(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/5.8.0 --template
How can I fix this issue?

You could use make conditionals instead of shell if statements:
ifeq ($(PLAT),x86_64)
PERLVERSION = 5.10.0
else ifeq ($(PLAT),aarch64)
PERLVERSION = 5.8.0
else
$(error "Unknown arhictecture: $(PLAT)")
endif
And then:
PERLLIB = $(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/$(PERLVERSION)
some/%.c: test/tmpl-%.c $(NEW_DATA32)
mkdir -p $(#D); \
env PERLLIB=$(PERLLIB) --template $< --initialization $(NEW_DATA32)

You should just use constructed macro names for this. For example:
PLATFORMS := x86_64 aarch64
$(or $(filter $(PLAT),$(PLATFORMS)),$(error Unknown architecture: $(PLAT)))
x86_64_PERLVER := 5.10.0
aarch64_PERLVER := 5.8.0
PERLLIB = $(EXTLIBS)/$(PLAT32)/lib/perl5/site_perl/$($(PLAT)_PERLVER)
More on this here.

Related

Makefile ifeq always true

I have the following Makefile target:
target1:
$(eval count_abc := $(shell grep -c "ABC" myFileA))
$(eval count_def := $(shell grep -c "DEF" myFileB))
echo $(count_abc)
echo $(count_def)
ifeq ($(count_abc),$(count_def))
echo "TRUE"
else
echo "FALSE"
endif
But the output is always TRUE, e.g.:
echo 22
22
echo 21
21
echo TRUE
TRUE
What am I doing wrong here? What I want is INSIDE the target do 2 greps and compare their outputs and do something or something else based on the result. Please note that the greps must be done within the target since myFileA and myFileB get created on the target before and don't exist at the beginning when running make.
Thanks,
Amir
The rule file for "make" is declarative in nature - the makefile defines rules and targets, and then the make program evaluate the rules, and decide which action to take based on the target. As a result, execution is not always in the order the lines are entered into the file.
More specifically, the "ifeq" is evaluated at the rule definition stage, but the actions for building the target (eval count_abc ...) are executed when the target is built. As a result, when the ifeq is processed, both count_abc and count_def are still uninitialized, expanded to empty strings.
For the specific case you described - building a target that will compare the grep -c output from the two files, you can try something like below, effectively using shell variables (evaluated when target is evaluated), and not make variables (which are mostly declarative, evaluated when makefile is read)
target1:
count_abc=$(grep -c "ABC" myFileA) ; \
count_def=$(grep -c "DEF" myFileB) ; \
echo $(count_abc) ; \
echo $(count_def) ; \
if [ "$count_abc" -eq "$count_def" ] ; then echo TRUE ; else echo FALSE ; fi
Disclaimer: I did not run the revised makefile, not having access to desktop at this time.

make on ubuntu vs Mingw32-make on windows -- unable to execute ! and other commands

The following structure works fine on a native ubuntu machine:
Makefile
Makefile-Debug
Makefile-impl
I call make with make CONF=Debug
Contents of Makefile are:
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin
build: .build-post
.build-pre:
.build-post: .build-impl
clean: .clean-post
.clean-pre:
.clean-post: .clean-impl
clobber: .clobber-post
.clobber-pre:
.clobber-post: .clobber-impl
all: .all-post
.all-pre:
.all-post: .all-impl
build-tests: .build-tests-post
.build-tests-pre:
.build-tests-post: .build-tests-impl
test: .test-post
.test-pre: build-tests
.test-post: .test-impl
help: .help-post
.help-pre:
.help-post: .help-impl
include Makefile-impl.mk <<----this file gets executed
include Makefile-variables.mk
Now, Makefile-impl.mk has the following line where it is checked whether the makefile corresponding to the Debug configuration -- Makefile-Debug -- actually exists:
.validate-impl:
#if [ ! -f Makefile-${CONF}.mk ]; \ <<------ this line produces an error in MinGW
then \
echo ""; \
echo "Error: can not find the makefile for configuration '${CONF}' in project ${PROJECTNAME}"; \
echo "See 'make help' for details."; \
echo "Current directory: " `pwd`; \
echo ""; \
fi
#if [ ! -f Makefile-${CONF}.mk ]; \
then \
exit 1; \
fi
The above works perfectly fine on the native ubuntu machine.
When mingw32-make.exe processes the above on a windows machine, I obtain an error:
! was unexpected at this time.
mingw32-make: *** [Makefile-impl.mk:90: .validate-impl] Error 255
Is there any workaround for this? I also obtain other errors, such as for -n on the following different line in Makefile-impl.mk
#if [ -n "${MAKE_VERSION}" ]; then \
Here the error is:
-n was unexpected at this time.
mingw32-make: *** [Makefile-impl.mk:78: .depcheck-impl] Error 255

Function for rendering text in makefile

I create a function rendering input text(argument)
#Color renderning
define GPrint
kColorRed := "\x1b[0;31m"
kColorGreen := "\x1b[0;32m"
kColorEnd := "\x1b[0m"
#echo -e "${kColorGreen}${1}${kColorEnd}"
endef
when I call this funtion
.PHONY : create_odir
create_odir:
$(call GPrint "create output dir")
mkdir ./output_dir
I got this error message
kColorRed := "\x1b[0;31m"
/bin/sh: line 1: kColorRed: command not found
make: *** [../src/sw/makefile:51: create_odir] Error 127
How do I solved it?
Please see below code which will help you fix this issue.
Method 1: Using global variables
# Regular Colors
kColorRed ='\e[0;31m' # Red
kColorGreen ='\e[0;32m' # Green
kColorEnd='\e[0m' # Text Reset
# Color renderning
define GPrint
echo -e ${kColorRed}$(1)${kColorEnd}
echo -e ${kColorGreen}$(1)${kColorEnd}
endef
create_odir:
$(call GPrint ,"create output dir")
Output :
Method 2:
If you want to use local variables inside the function.
# Color renderning
define GPrint
$(eval kColorRed := '\e[0;31m')
$(eval kColorGreen := '\e[0;32m')
$(eval kColorEnd := '\e[0m')
echo -e $(kColorRed)$(1)$(kColorEnd)
echo -e $(kColorGreen)$(1)$(kColorEnd)
endef
create_odir:
$(call GPrint ,"create output dir")

Eiffel compilation through Makefile and `dpkg-buildpackage -us -uc` generating an error

Am trying to create a debian package of my Eiffel application.
Either make or make -j4 (which is the called one from dpkg-buildpackage) within the root structure does the job without error
but when called from dpkg-buildpackage -us -uc which calls the Makefile it exits with an error
In file included from big_file_C7_c.c:40:0:
lo322.c: In function ‘inline_F425_4447’:
lo322.c:97:5: error: format not a string literal and no format arguments [-Werror=format-security]
syslog(arg1, arg2);
^~~~~~
cc1: some warnings being treated as errors
My makefile for info is as following:
#Build variables
MY_EC = $(shell which ec)
BUILT_TARGET = EIFGENs/$(TARGET_NAME)/F_code/$(APP_NAME)
# This target will compile all files
all: build
build:
# Checks eiffel compiler
# #echo "MY EC IS: ${MY_EC}"
#if [ -z "${MY_EC}" ]; then
echo "Compiler not found";
else
echo "Eiffel compiler found";
fi
# Compilation
echo '---------->finalizing'
ec -finalize -config $(APP_NAME).ecf -target $(TARGET_NAME) || (echo "last command failed $$="; exit 1)
cd $(FINAL_EXE_DIR); \
echo '---------->Finish freezing';\
finish_freezing || (echo "A problem occured during finish_freezing!!!"; exit 1)
The issue is caused by the feature c_logging_write_log of the class LOG_WRITER_SYSTEM in EiffelStudio 18.11 and earlier that makes the following call:
syslog($priority, $msg);
Replacing it with
syslog($priority, "%s", (char *) $msg);
(in $ISE_EIFFEL/library/runtime/logging/writers/log_writer_system.e) and recompiling the system (from scratch, if the logging library is marked as read-only) should fix the problem.

GNU override target?

I'm wondering if it's possible to override a target in a makefile! The environment I'm working in does not allow me to do this due to auto generation! I was wondering if I coded the same rule above or below the static target would this achieve an override?
%_emul.flist: $(if ${GEN_FLIST},%_synth.flist,) ${rdlh_file_deps}
${QUIET}if test ${SYN_DEBUG} -eq 1 ; then set -xv ; fi; \
$(if ${TOOL_VERILOG},rm -f $#; touch $#,$(if ${TOOL_BBOX_LIBS},echo ${TOOL_BBOX_LIBS} > $#,rm -f $#; touch $#))
/bin/sed -e '/\/libs\//d' -e '/\/place\//d' $(foreach mod,$(filter %.vhd,$^),-e 's%^\(.*\/\)\{0,1\}$(basename $(notdir ${mod}))\.v$$%${mod}%') $*_synth.flist >> $#
Yes , i think that would work .... but you need to be a bit more careful in the way you code things. You don't want to override something that might be useful!
GNU make would take the most recent of the target it encounters. So, the following works (but not as i would have liked it to work :( )
Output: I think you are looking for something like this --
Kaizen ~/make_prac $ make -nf mk.name
mk.name:20: warning: overriding recipe for target `name'
mk.name:17: warning: ignoring old recipe for target `name'
arg1="Kaizen" ;
echo "hello "" ;" ;
hello ;
Code: Here the target "name" appears twice and is overridden.
Kaizen ~/make_prac $ cat mk.name
##
## make to accept name and display hello name
##
arg1="" ;
.PHONY : name \
hello
#.DEFAULT :
# hello
hello : name
+ echo "hello $(arg1)" ;
name :
echo "name given is : $(arg1)" ;
name :
arg1="Kaizen" ;
PS: Take note of the use of : -- if you use :: then both rules get executed.
Explanation for the arg1 .... not showing in the output: The variable arg1, even though it gets assigned in the first parsing, it gets ignored, since its assignment is target dependent. If you would have had a variable declaration elsewhere -- e.g. like arg1 is defined at the start -- there would not be any dereferencing issues.

Resources