make: Circular b <- b dependency dropped - makefile

For the example Makefile below, I was expecting and output of
Expected Output:
x/x_a
x/x_b
x/x_c
x/x_d
Code:
letters= a b c d
default:$(letters)
$(letters):x/x_$(letters)
x/x_$(letters):
echo $#
But what I got was
echo x/x_a
x/x_a
make: Circular b <- b dependency dropped.
make: Circular c <- b dependency dropped.
make: Circular c <- c dependency dropped.
make: Circular d <- b dependency dropped.
make: Circular d <- c dependency dropped.
make: Circular d <- d dependency dropped.
echo d
d
echo c
c
echo b
b
I am not sure what is causing
The circular dependency. It looks linear to me.
Printing of b,c,d instead of x/x_b,x/x_c,x/x_d

These lines don't do what you seem to think they do:
$(letters):x/x_$(letters)
x/x_$(letters):
Make variables are straight substitutions. You are assuming that x/x_$(letters) will apply a prefix of x/x_ to every word in $(letters), but that's not true. It's simple text substitution so the expansion of that is x/x_a b c d, so the above lines are:
a b c d:x/x_a b c d
x/x_a b c d:
which explains the behavior you see. If you want to apply the prefix to each word you need a function (since you're using GNU make):
letters := a b c d
xletters := $(addprefix x/x_,$(letters))
$(letters): $(xletters)
$(xletters):

Related

Calling string manipulation functions in Makefile returns empty variable [duplicate]

This is a silly question, but.... with GNU Make:
VAR = MixedCaseText
LOWER_VAR = $(VAR,lc)
default:
#echo $(VAR)
#echo $(LOWER_VAR)
In the above example, what's the correct syntax for converting VAR's contents to lower case? The syntax shown (and everything else I've run across) result in LOWER_VAR being an empty string.
you can always spawn off tr
LOWER_VAR = `echo $(VAR) | tr A-Z a-z`
or
LOWER_VAR = $(shell echo $(VAR) | tr A-Z a-z)
The 'lc' functions you trying to call is from GNU Make Standard Library
Assuming that is installed , the proper syntax would be
LOWER_VAR = $(call lc,$(VAR))
You can do this directly in gmake, without using the GNU Make Standard Library:
lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
VAR = MixedCaseText
LOWER_VAR = $(call lc,$(VAR))
all:
#echo $(VAR)
#echo $(LOWER_VAR)
It looks a little clunky, but it gets the job done.
If you do go with the $(shell) variety, please do use := instead of just =, as in LOWER_VAR := $(shell echo $VAR | tr A-Z a-z). That way, you only invoke the shell one time, when the variable is declared, instead of every time the variable is referenced!
To handle capital letters with accents:
LOWER_VAR = $(shell echo $VAR | tr '[:upper:]' '[:lower:]')
Results:
$ VAR="Éclipse"
$ echo $VAR | tr A-Z a-z
Éclipse
$ echo $VAR | tr '[:upper:]' '[:lower:]'
éclipse
I find this slightly cleaner...
$(shell tr '[:upper:]' '[:lower:]' <<< $(VAR))
If Python is installed this runs even on Windows:
$(shell python -c "print('$(VAR)'.lower())")
GNU make doesn't include string functions for case conversion. Thus, there is no lc function defined, by default.
But GNU Make usually comes with GNU Guile support enabled (e.g. this is the case on Fedora 33).
Thus, you can just call a Guile function for converting the case:
VAR = MixedCaseText
LOWER_VAR = $(guile (string-downcase "$(VAR)"))
default:
#echo $(VAR)
#echo $(LOWER_VAR)
Or if you want to encapsulate the Guile call:
VAR = MixedCaseText
LOWER_VAR = $(call to_lower,$(VAR))
define to_lower
$(guile (string-downcase "$(1)"))
endef
default:
#echo $(VAR)
#echo $(LOWER_VAR)
I wrote this while looking for a solution.
It is a bit verbose but believe it explains the steps and keeps really long lines out on the Makefile.
You can easily be modify it to perform any substitution you may want.
Hope it helps someone.
# set the separator for the *_TABLE variables, needed as otherwise `$(addprefix ...)` fails
luc_JOIN ::= ,
# define the upper and lower cased characters
lc_CHARS ::= a b c d e f g h i j k l m n o p q r s t u v w x y z
uc_CHARS ::= A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
# join the above to create the *_TABLE variables (i.e `a,A b,B ...`, `A,a B,b ...`)
lc_TABLE ::= $(join $(uc_CHARS),$(addprefix $(luc_JOIN),$(lc_CHARS)))
uc_TABLE ::= $(join $(lc_CHARS),$(addprefix $(luc_JOIN),$(uc_CHARS)))
# an internal macro to recursively create `$(subst ...)` from provided *_TABLE and string, (e.g. `$(subst a,A,$(subst b,B,...))`)
luc_internal = $(if $1,$$(subst $(firstword $1),$(call luc_internal,$(wordlist 2,$(words $1),$1),$2)),$2)
# the actual macros to $(call ...), which calls the luc_internal with the correct *_TABLE
lc = $(eval lc_RESULT ::= $(call luc_internal,$(lc_TABLE),$1))$(lc_RESULT)
uc = $(eval uc_RESULT ::= $(call luc_internal,$(uc_TABLE),$1))$(uc_RESULT)
# a mixed case value
VAR = SOME text
default:
#echo $(call lc,$(VAR))
#echo $(call uc,$(VAR))
Being impressed by the Eric Melski answer, I was curious how make handles recursion (I'm looking at you C preprocessor). Somewhat more involved, than original answer, but it's fascinating what a 50 years old tool can do. Not saying you should use this code, but I guess you could.
pop2 = $(wordlist 3,$(words $(1)),$(1))
sub1 = $(subst $(word 1,$(1)),$(word 2,$(1)),$(2))
map = $(if $(1),$(call sub1,$(1),$(call map,$(call pop2,$(1)),$(2))),$(2))
upperMap := a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
upper = $(call map,$(upperMap),$(1))
lowerMap := A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z
lower = $(call map,$(lowerMap),$(1))
#Usage:
x := $(call upper,AaBbCcDdEe)

Compilation - LL1 Grammar

I am studying the magic of compilers and I don't understand a result.
Here is the grammar :
S -> A #
A -> B G D E
B -> + | - | EPSILON
C -> c C | EPSILON
G -> c C
D -> . C | EPSILON
E -> e B G | EPSILON
When I try to find the "first" and "follow" sets, I get different results than the one I get when I do it with an online predictor.
Here are the results given:
Non-terminal Symbol / Follow Set
S $
A #
B c
C e, ., #
G ., #
D e, #
E #
Why isn't the follow set of G {e, ., #} ?
Because what I understand is that according to the A rule, D follow the G, so we add ., but it could also have been EPSILON, so we move to the E and it can be a e, but it could also have been EPSILON, so we move to the #, in respect with the S rule.
What am I missing here ?
I used the tool at http://hackingoff.com/compilers/predict-first-follow-set
Your computation of the FOLLOW set of G is correct.
The hackingoff tool is buggy. Here is a shorter grammar which exhibits the same error:
S -> a B C a
B -> b
C -> EPSILON
It's obvious that a is in the FOLLOW set for B but the tool reports that set as empty.

Expansion in makefiles

In the context of makefiles I often see in documentation/forums the term expansion thrown around quite a bit though it is rarely defined. What exactly does it mean to expand a variable or parameter when talking about makefiles?
To expand a string means to replace references to variables or function calls within the string, (e.g. $(NAME)), with the values of those things.
Consider:
FOO = a b c
BAR = $(FOO) d e
BAZ = $(BAR) f g
The value of BAZ is $(BAR) f g. If you try to use it:
$(info $(BAZ))
then Make expands the variable, which is to say it replaces $(BAZ) with the value of BAZ:
$(info $(BAR) f g)
then $(BAR) with the value of BAR:
$(info $(FOO) d e f g)
then $(FOO) with the value of FOO:
$(info a b c d e f g)
and with nothing left to expand it executes the info function and prints out "a b c d e f g".
Note that some things expand variables and others don't. For example, the assignment BAR = $(FOO) d e does not expand the $(FOO) on the right-hand side. The other kind of assignment, BAR := $(FOO) d e, does.

temp mark off some targets in makefile

I wish to compile partial targets which is $(APPS) but excluding targets in $(OFF) in the makefile:
APPS = a b c d e f g
OFF = d e
all: $(APPS)
partial: $(APPS) - $(OFF)
How can I do this?
I'd probably just take a slightly different approach:
ON = a b c f g
OFF = d e
APPS = $(ON) $(OFF)
partial: $(ON)
But if this is too simplistic for your needs, there is a filter-out function that can provide the exact operation you want:
objects=main1.o foo.o main2.o bar.o
mains=main1.o main2.o
$(filter-out $(mains),$(objects))
I think re-writing your example in this format would be:
APPS = a b c d e f g
OFF = c d
partial: $(filter-out $(APPS),$(OFF))

string pattern match,the suffix array can solve this or have more solution?

i have a string that random generate by a special characters (B,C,D,F,X,Z),for example to generate a following string list:
B D Z Z Z C D C Z
B D C
B Z Z Z D X
D B Z F
Z B D C C Z
B D C F Z
..........
i also have a pattern list, that is to match the generate string and return a best pattern and extract some string from the string.
string pattern
B D C [D must appear before the C >> DC]
B C F
B D C F
B X [if string have X,must be matched.]
.......
for example,
B D Z Z Z C D C Z,that have B and DC,so that can match by B D C
D B Z C F,that have B and C and F,so that can match by B C F
D B Z D F,that have B and F,so that can match by B F
.......
now,i just think about suffix array.
1.first convert a string to suffix array object.
2.loop each a pattern,that find which suffix array can be matched.
3.compare all matched patterns and get which is a best pattern.
var suffix_array=Convert a string to suffix array.
var list=new List();
for (int i=0;i<pattern length;i++){
if (suffix_array.match(pattern))
list.Add(pattern);
}
var max=list[0];
for (int i=1;i<list.length;i++){
{
if (list[i]>max)
max=list[i];
Write(list[i]);
}
i just think this method is to complex,that need to build a tree for a pattern ,and take it to match suffix array.who have a more idea?
====================update
i get a best solution now,i create a new class,that have a B,C,D,X...'s property that is array type.each property save a position that appear at the string.
now,if the B not appear at the string,we can immediately end this processing.
we can also get all the C and D position,and then compare it whether can sequential appear(DC,DCC,CCC....)
I'm not sure what programming language you are using; have you checked its capabilities with regular expressions ? If you are not familiar with these, you should be, hit Google.
var suffix_array=Convert a string to suffix array.
var best=(worst value - presumably zero - pattern);
for (int i=0;i<pattern list array length;i++){
if (suffix_array.match(pattern[i])){
if(pattern[i]>best){
best=pattern[i];
}
(add pattern[i] to list here if you still want a list of all matches)
}
}
write best;
Roughly, anyway, if I understand what you're looking for that's a slight improvement though I'm sure there may be a better solution.

Resources