Makefile appending string to variable - makefile

I want to generate the command:
taskset -c 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14 ./myprogram
First try: I use echo:
taskset 0$(shell for n in $(shell seq 1 14);do echo ",$$n";done) ./myprogram
But echo gives additional trailing space between iterations
taskset -c 0,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 ,11 ,12 ,13 ,14 ./myprogram
,which is not recognizable for taskset function. So, I tried to append the string by my self,
taskset -c $(shell CORE_NUM=0; for n in $(shell seq 1 14); do CORE_NUM:=$(CORE_NUM)","$$n;done;echo $(CORE_NUM)) ./myprogram
However, I'm not familiar with Makefile, I got an error:
/bin/sh: 1: CORE_NUM:=0,1: not found
/bin/sh: 1: CORE_NUM:=0,2: not found
/bin/sh: 1: CORE_NUM:=0,3: not found
/bin/sh: 1: CORE_NUM:=0,4: not found
....
/bin/sh: 1: CORE_NUM:=0,14: not found
taskset -c 0 ./myprogram
Can someone help to fix it?

Don't use $(shell) here at all. There's no point. The $(shell) function is for running shell commands in make context. But you aren't in make context at this point. You are in shell context in the recipe so just use normal shell command substitution.
taskset -c "0$$(printf ,%s $$(seq 1 14))" ./myprogram

Related

bash quoting issue when using bash -c with more than one argument

first I want to apologize for the bad title, my problem is best illustrated through the following example:
This command works fine, although it doesn't make a lot of sense to do so.
sudo bash -c 'pwd 2>/dev/null'
but when I put it in an variable, and do :
COMMAND="sudo bash -c 'pwd 2>/dev/null'"
(set -xv; ${COMMAND})
I get the quoting unmatching error:
+ sudo bash -c ''\''pwd' '2>/dev/null'\'''
2>/dev/null': -c: line 0: unexpected EOF while looking for matching `''
2>/dev/null': -c: line 1: syntax error: unexpected end of file
The problem here seems to be the space between pwd and 2>/dev/null, the following works:
COMMAND="sudo bash -c 'pwd'"
(set -xv; ${COMMAND})
The problem appears even when I just put a tailing whitespace after pwd
What am i doing wrong here? and how do I solve it ? Thanks in advance.
You should at least use an array, which acts as a second layer of proper quoting, instead of a flat string:
my_command=(sudo bash -c 'pwd 2>/dev/null')
"${my_command[#]}"
However, you should rethink why you feel it necessary to store a command like this in the first place. A function is a better idea:
my_command () {
sudo bash -c 'pwd 2> /dev/null'
}
my_command
The comment above is correct, you can probably find a better way to do this. But, playing devil's advocate, have you tried eval to run the command?
COMMAND="sudo bash -c 'pwd 2>/dev/null'"
(set -xv; eval $COMMAND)

Variable that allows override and "simply expandable"?

I have the following in my GNU Makefile around Line 73:
RELEASE ?= $(shell $(UNAME) -r)
IS_FEDORA22_i686 = $(shell echo $(RELEASE) | $(EGREP) -i -c "fc22.i686")
It runs fine on BSDs, Linux (Ubuntu and Fedora), OS X and Solaris. However, on Cygwin and MinGW, it produces the following (thanks cxw). Cygwin and MinGW use the Bash shell:
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `echo 2.0.4(0.287/5/3) | egrep -i -c "fc22.i686"'
From the manual and 6.2 The Two Flavors of Variables, I think I need a variable like:
RELEASE ?::= $(shell $(UNAME) -r)
How do I make a variable both optional an "simply expandable"?
One way would be:
RELTEXT:=$(<whatever command>)
RELEASE?=$(RELTEXT)
Even though RELEASE isn't simply expandable, you know it will always expand to fixed text.

Unexpected '(' in bash [duplicate]

This question already has answers here:
Bash: Syntax error: redirection unexpected
(9 answers)
Closed 8 years ago.
I have the following script:
#!/bin/sh
# Use the PhiPack software on our two aligned sets of sequences...
mkdir FcFeABC
cd FcFeABC
../bin/PhiPack/Phi -f ../../Data/Real_Sequences_and_Networks/FcFeABC_alignment.fas -o -v -w 10 -g
cd -
mkdir FcL10
cd FcL10
../bin/PhiPack/Phi -f ../../Data/Real_Sequences_and_Networks/FcL10_alignment.fas -o -v -w 10 -g
cd -
# Use the PhiPack software on the simulated Datasets...
cd ../Data/Simulated_Sequences_and_Networks/Constant_Sex/Theta\ =\ 0.066/Theta\ =\ 0.066/Medium/CutSequences/;
rmus=($(ls -d *.fas))
cd -
absfiles=(../Data/Simulated_Sequences_and_Networks/Constant_Sex/Theta\ =\ 0.066/Theta\ =\ 0.066/Medium/CutSequences/*.fas)
if [ ${#rmus[#]} = ${#absfiles[#]} ]
then
mkdir ${rmus[#]}
for ((i=0; i<${#absfiles[#]}; i++));
do
cd ${rmus[$i]}
.../bin/PhiPack/Phi -f ${absfiles[$i]} -o -v -w 10 -g
cd -
done
else
echo "Error, Number of files created and files to be read differs"
fi
Which hit's an error at line 16:
./runPhiTests.sh: 16: ./runPhiTests.sh: Syntax error: "(" unexpected
Which is this line:
rmus=($(ls -d *.fas))
I don't understand why the '(' is unexpected - it's a simple assignment of the results of ls to an array.
Thanks,
Ben W.
You aren't running it with bash. You are running with /bin/sh from your shebang line #!/bin/sh.
Either run with bash explicitly bash runPhiTests.sh or fix your shebang line #!/bin/bash.
Try to use #!/bin/bash instead of sh.

What is $# means?

I am referring this link for installing cdh4.6.0. I don't understand the following command.
hdfs namenode $#
And, when i try it in my machine, it keeps on running. I can't able to see the completion of execution with command prompt.
Any Suggestions?
$# are the command line parameter of the program.
if you call a program named test.sh in this way: test.sh 1 2 3
$# contains 1 2 3

Makefile - how to differentiate between a variable assignment and a command

I have the following code in my Makefile, but I get the error mentioning that O?=2 is not a command that sh -c can run. What am I doing wrong here?
gcc:
O?=2
#if test -z "$(DEBUG)" ; then \
g++ -O${O} *.c -o palindrome ; \
fi
I am trying to set O to 2 if the user did not provide it, and then build my palindrome executable.
Exact error:
$ make gcc
O?=2
/bin/sh: O?=2: command not found
make: *** [gcc] Error 127
$
Move it outside the command, so that it gets processed by "make" instead of the shell:
O?=2
gcc:
#if test -z "$(DEBUG)" ; then \
g++ -O${O} *.c -o palindrome ; \
fi
The line O?=2 is not an assignment, but a command executed to rebuild target gcc. This means it is fed to $(SHELL), which doesn't know a thing about it. If you want a variable assingment, put it on line by itself and not as a part of commands:
O?=2
gcc:
#if test -z "$(DEBUG)" ; then \
g++ -O${O} *.c -o palindrome ; \
fi
You can just use O = 2. When the user provides a value on the command line it will override it:
make O=1
will use -O1 for optimization.

Resources