Simplest way to reverse the order of strings in a make variable
-
09-06-2019 - |
Question
Let's say you have a variable in a makefile fragment like the following:
MY_LIST=a b c d
How do I then reverse the order of that list? I need:
$(warning MY_LIST=${MY_LIST})
to show
MY_LIST=d c b a
Edit: the real problem is that
ld -r some_object.o ${MY_LIST}
produces an a.out
with undefined symbols because the items in MY_LIST
are actually archives, but in the wrong order. If the order of MY_LIST
is reversed, it will link correctly (I think). If you know a smarter way to get the link order right, clue me in.
Solution
A solution in pure GNU make:
default: all
foo = please reverse me
reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1)))) $(firstword $(1))
all : @echo $(call reverse,$(foo))
Gives:
$ make
me reverse please
OTHER TIPS
Doh! I could have just used a shell script-let:
(for d in ${MY_LIST}; do echo $$d; done) | tac
You can also define search groups with ld:
ld -r foo.o -( a.a b.a c.a -)
Will iterate through a.a, b.a, and c.a until no new unresolved symbols can be satisfied by any object in the group.
If you're using gnu ld, you can also do:
ld -r -o foo.o --whole-archive bar.a
Which is slightly stronger, in that it will include every object from bar.a regardless of whether it satisfies an unresolved symbol from foo.o.
An improvement to the GNU make solution:
reverse = $(if $(wordlist 2,2,$(1)),$(call reverse,$(wordlist 2,$(words $(1)),$(1))) $(firstword $(1)),$(1))
- better stopping condition, original uses the empty string wasting a function call
- doesn't add a leading space to the reversed list, unlike the original
Playing off of both Ben Collins' and elmarco's answers, here's a punt to bash which handles whitespace "properly"1
reverse = $(shell printf "%s\n" $(strip $1) | tac)
which does the right thing, thanks to $(shell)
automatically cleaning whitespace and printf
automatically formatting each word in its arg list:
$(info [ $(call reverse, one two three four ) ] )
yields:
[ four three two one ]
1...according to my limited test case (i.e., the $(info ...)
line, above).