Leading whitespaces in makefile variable - makefile

I need to declare a makefile variable with a leading white space, and I used the following code, but it doesn't work
SPACE :=
SPACE +=
VIU_DIAG_SW_VERSION :=$(SPACE)AJ

Try:
NULL :=
VIU_DIAG_SW_VERSION := $(NULL) AJ
Demo:
$ cat Makefile
NULL :=
VIU_DIAG_SW_VERSION := $(NULL) AJ
.PHONY: all
all:
#echo "X$(VIU_DIAG_SW_VERSION)X"
$ make
X AJX
And if you want a variable containing just one space:
SPACE := $(NULL) $(NULL)

Related

Accessing Makefile variable in compile time shell

I have a makefile, 1.mk with following content:
#!make
aa := x
bb := y
cc := z
export
include abc.mk
all:
#echo $(chk1)
And another makefile, abc.mk with following content:
#!make
chk1 := $(shell set -o posix; set | awk -F "=" 'BEGIN{ORS=" "}1 $$1~/[a-zA-Z_][a-zA-Z0-9_]*/ {print $$1}')
chk2 := $(shell env &> pqr)
export
When I check, none has the makefile-variables:
> make all -f 1.mk | grep aa
> grep 'aa' pqr
Thus I can say, compile time shell does not have makefile variables. I want a way to access all makefile variables in compile-time shell.
Constraint: I do not know variable names beforehand to write code in following manner:
chk2 := $(shell export aa=$(aa); env &> pqr)
As far as I understand the way make exports make variables, it does so only in recipes, not in the shells invoked with the shell function. You can test this with, for instance:
$ cat Makefile
aa := x
export
chk := $(shell echo $$aa)
.PHONY: all
all:
#printf 'in shell function: aa = $(chk)\n'
#printf 'in recipe: aa = %s\n' "$$aa"
$ make
in shell function: aa =
in recipe: aa = x

In Makefile: read version from other text file and put the result into a variable in the Makefile

I have an file named "Version.h" with the content of:
#define APP_VERSION_MAJOR 5
#define APP_VERSION_MINOR 6
#define APP_VERSION_PATCH 0
I have a Makefile, and I want to assign a variable in the Makefile, according to the "Version.h" file, in this case:
MY_APP_VERSION = 5.6.0
I managed to find the line with the following command:
#echo "The result is: $$(grep "#define APP_VERSION_MINOR " Version.h)"
Output:
The result is: #define APP_VERSION_MINOR 6
So, how can I put the version in a variable in the Makefile?
Thanks!
To set a make variable you can do something like this:
getnum = $(shell sed -n 's/.*$1 *\([0-9*]\)/\1/p' Version.h)
MY_APP_VERSION := $(call getnum,MAJOR).$(call getnum,MINOR).$(call getnum,PATCH)
This does invoke sed 3 times though.
Try putting this is your makefile:
all:
#echo The result is: \
$$(grep '#define APP_VERSION_MAJOR' Version.h | cut -d' ' -f5).\
$$(grep '#define APP_VERSION_MINOR' Version.h | cut -d' ' -f5).\
$$(grep '#define APP_VERSION_PATCH' Version.h | cut -d' ' -f5)
Then a simple make gives you
$ make
The result is: 5.6.0
Try something like:
APP_VERSION_MAJOR := $(shell awk '// { if ($$2 = 'APP_VERSION_MAJOR) { print $$3 } }' < Version.h)
The := inhibits repeated expansion of the shell command, and the awk command extracts the the value of the assignment.
With more recent GNU make versions, this should work as well (assuming Version.h doesn't use tabs):
$(foreach i, \
$(shell sed 's/#define \([^ ]*\) *\([^ ]*\)/\1:=\2/' < Version.h), \
$(eval $i))
It has the advantage that it will translate many preprocessor defines in one go, no matter what the specifics are, but it can easily go very wrong if Version.h contains unexpected text.
If you manage to read in the file into a variable (my version of make fails to read with $(file < version.h) but yours may work) then you can use the GNU make table toolkit. It was designed exactly for this purpose:
include gmtt.mk
tbl := 3 $(strip $(file < version.h)) # make a table with 3 columns from the file
versions := $(strip $(call select,3,$(tbl),t)) # select 3rd column from table, t(rue) as where-clause
MY_APP_VERSION := $(subst $(space),.,$(versions))
The file must obey the format that you displayed above so that it can be interpreted as a table with three columns. It has the additional benefit that you don't have to care for which shell (e.g. on Windows) is available.

Remove single spaces from lines, but leave multiple spaces alone

I have the following input:
a a f aa
aa aa a h o
f j
The above input has single spaces as well as multiple spaces. I need to remove only the single ones, not the others, i.e. the output should be
aaf aa
aa aaaho
f j
Perl to the rescue!
perl -pe 's/(?<! ) (?! )//g' < input
(?<! ) is a negative look-behind assertion. It matches if the preceding string is not matched, i.e. in this case, it's not a space.
(?! ) is a negative look-ahead assertion. Similar to the above, but looks to the right.
Lex to the rescue!
$ cat x.l
%%
" "" "+ ECHO;
" " /* do nothing = don't echo */
%%
int yywrap(void)
{
return 1;
}
int main(void)
{
yylex();
return 0;
}
$ lex x.l
$ cc lex.yy.c -o spacedel
$ ./spacedel < in
aaf aa
aa aaaho
f j
This lex specification says to create a C program that echoes all sequences of two or more spaces; ignore single spaces; and the default rule for unmatched characters is to echo them, which is exactly what we want.
(You could append . ECHO; if you want to make this explicit).
This might work for you (GNU sed):
sed 's/\b\s\b//g' file
This removes a single white space surrounded by word boundaries.

How do I prefix a gmake variable

I have a Makefile that includes another makefile, say CommonMakefile. There is a variable that I want to prefix with a value (cf. appending using +=) keeping rest of the value intact.
V = value1 # set in CommonMakefile that is included
V = value0 $(V) # I want to prefix value0 to V
# rule defined in CommonMakefile that is included
whatsV:
echo $V # first char is a <TAB> here
How can I do that?
Expecting:
$ gmake whatsV
value0 value1
Actual:
$ gmake whatsV
Makefile:3: *** Recursive variable `V' references itself (eventually). Stop.
PS: I can-not/do-not-want to change CommonMakefile.
This won't work:
V = value0 $(V)
because here V is a recursively expanded variable, and it can't be defined in terms of itself. But change it to a simply expanded variable:
V := value0 $(V) # <-- Note the colon
and it will work as intended.

Create comma-separated lists in GNU Make

I have a Makefile with a set of booleans which must be used to control the flags for an external application. The problem is that the flag must be passed as a comma-separated string.
Something like this (non-working pseudo code):
WITH_LIST = ""
WITHOUT_LIST = ""
ifeq ($(BOOL_A),y)
# Append A to list "WITH_LIST"
else
# Append A to list "WITHOUT_LIST"
endif
ifeq ($(BOOL_B),y)
# Append B to list "WITH_LIST"
else
# Append B to list "WITHOUT_LIST"
endif
ifeq ($(BOOL_C),y)
# Append C to list "WITH_LIST"
else
# Append C to list "WITHOUT_LIST"
endif
Now assuming BOOL_A == y, BOOL_B == n and BOOL_C == y, I need to run the following command:
./app --with=A,C --with-out=B
How can I generate these string using Gnu Make?
First you create the two white-space separated lists, either using your method, or thiton's.
Then you use the little trick from the end of section 6.2 of the GNU make manual to create a variable holding a single space, and one holding a comma. You can then use these in $(subst ...) to change the two lists to comma-separated.
PARTS := A B C
BOOL_A := y
BOOL_B := n
BOOL_C := y
WITH_LIST := $(foreach part, $(PARTS), $(if $(filter y, $(BOOL_$(part))), $(part)))
WITHOUT_LIST := $(filter-out $(WITH_LIST), $(PARTS))
null :=
space := $(null) #
comma := ,
WITH_LIST := $(subst $(space),$(comma),$(strip $(WITH_LIST)))
WITHOUT_LIST := $(subst $(space),$(comma),$(strip $(WITHOUT_LIST)))
all:
./app --with=$(WITH_LIST) --with-out=$(WITHOUT_LIST)
A construct like
OPTIONS+=$(if $(filter y,$(BOOL_A)),--with=A,--with-out=A)
should work.
Edit: Sorry, overlooked the necessary collation.
PARTS=A B C
YESSES=$(foreach i,$(PARTS),$(if $(filter y,$(BOOL_$(i))),$(i)))
all:
echo with=$(shell echo $(YESSES) | tr ' ' ',')
The idea is to check for each possible part X whether it's set to yes and insert it into a list if it is yes. This list is whitespace-separated and hard to comma-separate with make, but easy to do this in shell.
Or just use sed: ugly (and untested) but straightforward
WITH_LIST = $(shell echo A$(BOOL_A) B$(BOOL_B) C$(BOOL_C) | sed -e 's/[ABC][^yABC]*//g' -e 's/y//g' -e 's/ /,/g')
WITHOUT_LIST = $(shell echo A$(BOOL_A) B$(BOOL_B) C$(BOOL_C) | sed -e 's/[ABC]y[^ABC]*//g' -e 's/[^ABC ]//g' -e 's/ /,/g')

Resources