LinuxQuestions.org
Go Job Hunting at the LQ Job Marketplace
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
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

Reply
 
Search this Thread
Old 04-05-2011, 06:50 PM   #1
shamgar03
Member
 
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92

Rep: Reputation: 15
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....
 
Old 04-08-2011, 06:17 PM   #2
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,541

Rep: Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878
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.
 
Old 04-11-2011, 06:23 PM   #3
shamgar03
Member
 
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92

Original Poster
Rep: Reputation: 15
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.
 
Old 04-11-2011, 08:51 PM   #4
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,523

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
<post removed>

Last edited by dwhitney67; 04-12-2011 at 12:05 AM.
 
Old 04-11-2011, 09:18 PM   #5
shamgar03
Member
 
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92

Original Poster
Rep: Reputation: 15
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
 
Old 04-11-2011, 10:19 PM   #6
ntubski
Senior Member
 
Registered: Nov 2005
Distribution: Debian
Posts: 2,541

Rep: Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878Reputation: 878
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 View Post
I've posted an example here: http://paste.pocoo.org/show/369981/
but the .SECONDEXPANSION doesn't fix the problem.
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))
 
Old 04-12-2011, 03:10 PM   #7
shamgar03
Member
 
Registered: Jul 2004
Distribution: Gentoo, CentOS
Posts: 92

Original Poster
Rep: Reputation: 15
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)) > $@
 
Old 04-29-2013, 10:06 AM   #8
zub7
LQ Newbie
 
Registered: Apr 2013
Posts: 1

Rep: Reputation: Disabled
Lightbulb

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))
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
get index of an element in array in bash mangatmodi Programming 4 11-20-2009 08:45 AM
type of list element in Perl ? thelonius Programming 2 06-20-2006 09:49 AM
index of an element in the array ? thelonius Programming 1 09-24-2005 01:41 PM
Inserting element to a list of list in C suwandy_chandra Programming 2 03-09-2004 04:08 AM
return index of element in java multidimensional array dave bean Programming 8 11-28-2003 12:00 PM


All times are GMT -5. The time now is 08:47 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration