Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game. |
| Notices |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
 |
GNU/Linux Basic Guide
This 255-page guide will provide you with the keys to understand the philosophy of free software, teach you how to use and handle it, and give you the tools required to move easily in the world of GNU/Linux. Many users and administrators will be taking their first steps with this GNU/Linux Basic guide and it will show you how to approach and solve the problems you encounter.
Click Here to receive this Complete Guide absolutely free. |
|
 |
04-05-2011, 05:50 PM
|
#1
|
|
Member
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92
Rep:
|
Makefile index of list element
So I have been trying for 8 hours to try to get the index of an element from a list in a Makefile. The problem is that after I get the index using all the methods I have tried, the index cant be used in the "word" function:
for instance:
$(OUTPUT2) : INDEX = $(shell echo $(OUTPUT2) | sed -r -e "s/[ \t]+/\n/g" | grep -n $@ | sed 's/^\([0-9]*\):.*/\1/')
will create a variable INDEX defined specifically for each member of OUTPUT2, so that each output knows its index. Unfortunately, when I pass this $(INDEX) into word, it doesn't work:
$(OUTPUT2) : $(word $(INDEX), $(INPUT1)) $(word $(INDEX), $(INPUT2))
echo $(INAME) $(TMPBASE) $@
and I get the error:
Makefile:16: *** non-numeric first argument to `word' function: 'num'. Stop.
Any ideas out there? I feel like if I could just convert a string to a Makefile acceptable number this would just work....
|
|
|
|
04-08-2011, 05:17 PM
|
#2
|
|
Senior Member
Registered: Nov 2005
Distribution: Debian
Posts: 2,015
|
The problem is the order of evaluation: the prerequisite is exanded in the first phase so INDEX is not defined, consider the following example:
Code:
~/tmp$ cat Makefile
target : VAR := Makefile
target : $(VAR)
@echo $@ depends on '"$<"'
~/tmp$ make target
target depends on ""
You'll need to use .SECONDARYEXPANSION to get this to work:
Code:
~/tmp$ cat Makefile
.SECONDEXPANSION:
target : VAR := Makefile
target : $$(VAR)
@echo $@ depends on '"$<"'
~/tmp$ make target
target depends on "Makefile"
See How make Reads a Makefile and Secondary Expansion.
|
|
|
|
04-11-2011, 05:23 PM
|
#3
|
|
Member
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92
Original Poster
Rep:
|
I've posted an example here: http://paste.pocoo.org/show/369981/
but the .SECONDEXPANSION doesn't fix the problem. There is a fundamental problem in the fact that sed doens't provide an integer to make. Hence the continued warning:
Makefile:21: *** non-numeric first argument to `word' function: ''. Stop.
|
|
|
|
04-11-2011, 07:51 PM
|
#4
|
|
Senior Member
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,383
|
<post removed>
Last edited by dwhitney67; 04-11-2011 at 11:05 PM.
|
|
|
|
04-11-2011, 08:18 PM
|
#5
|
|
Member
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92
Original Poster
Rep:
|
The problem is that I have multiple inputs and multiple outputs to the makefile that correspond with each other. I am actually trying to use this for grid jobs, because I got tired of manually writing scripts to check to see prerequisite were up to date. So I might have two sets of 3 inputs, and 2 two sets of 4 outputs:
inputA1 + inputA2 => outputA1 => outputA2 + outputA3
inputB1 + inputB2 => outputB1 => outputB2 + outputB3
but none of this have names that are consistent. So I need to be able to refer to the corresponding members of the input, or intermediate values by index, so I don't have to repeat:
outputA3 outputA2: outputA1
...
outputA1: inputA1 inputA2
...
for each group. ie, I wouldn't have to also write
outputB3 outputB2: outputB1
...
outputB1: inputB1 inputB2
...
again for group B, and of course for group C etc
|
|
|
|
04-11-2011, 09:19 PM
|
#6
|
|
Senior Member
Registered: Nov 2005
Distribution: Debian
Posts: 2,015
|
Quote:
There is a fundamental problem in the fact that sed doens't provide an integer to make. Hence the continued warning:
Makefile:21: *** non-numeric first argument to `word' function: ''. Stop.
|
The error message indicates that sed is providing an empty string to make, which is because it's getting an empty string as input, which is because $(INDEX) isn't defined at the time the prerequisite is expanded.
Quote:
Originally Posted by shamgar03
|
It's not enough to just put .SECONDEXPANSION you also have to escape the expression to prevent it from getting evaluated the first time:
Code:
$$(word $$(INDEX), $$(INPUT1)) $$(word $$(INDEX), $$(INPUT2))
|
|
|
|
04-12-2011, 02:10 PM
|
#7
|
|
Member
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92
Original Poster
Rep:
|
Thanks that really helped. For some reason I find Makefiles to be extremely confusing.
Code:
#!/usr/bin/make
#space separated inputs and corresponding outputs
TMPDIR = /tmp/maketmp/
.SECONDEXPANSION:
INPUT1 = test1A.txt test2A.txt
INPUT2 = test1B.txt test2B.txt
OUTPUT1 = test1A_out.txt test2A_out.txt
OUTPUT2 = test1B_out.txt test2B_out.txt
HASHES = $(shell md5sum $(INPUT1))
all: $$(OUTPUT1) $$(OUTPUT2)
$(OUTPUT1) : INDEX = $(shell echo $(OUTPUT1) | sed -r -e "s/[ \t]+/\n/g" | grep -n $@ | sed 's/^\([0-9]*\):.*/\1/')
$(OUTPUT1) : $$(word $$(INDEX), $$(INPUT1)) $$(word $$(INDEX), $$(INPUT2))
echo $(word $(INDEX), $(INPUT1)) + $(word $(INDEX), $(INPUT2)) > $@
$(OUTPUT2) : INDEX = $(shell echo $(OUTPUT2) | sed -r -e "s/[ \t]+/\n/g" | grep -n $@ | sed 's/^\([0-9]*\):.*/\1/')
$(OUTPUT2) : $$(word $$(INDEX), $$(INPUT1)) $$(word $$(INDEX), $$(INPUT2))
echo $(word $(INDEX), $(INPUT1)) - $(word $(INDEX), $(INPUT2)) > $@
|
|
|
|
04-29-2013, 09:06 AM
|
#8
|
|
LQ Newbie
Registered: Apr 2013
Posts: 1
Rep: 
|
There's maybe a shorter and clearly stuff that I made when I read this old post.
I put here the contribution for future readers.
In my example seems that you can use "index" directly in the "word" function. Regards.
Code:
list1='a b c d e f g'
list2='A B C D E F G'
index = $(words $(shell a="$(2)";echo $${a/$(1)*/$(1)} ))
swap = $(word $(call index,$(1),$(2)),$(3))
all:
echo f is $(call swap,f,$(list1),$(list2))
|
|
|
|
| Thread Tools |
Search this Thread |
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
All times are GMT -5. The time now is 05:54 AM.
|
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|