For loop variable is empty in gmake - gnu-make

I have a list of header files created thus:
expand=$(1)/$(1).h
HDRS=$(foreach x, $(DIRS), $(call expand,$(x)))
Which yields a list like a/a.h b/b.h ...
but when I use this in a for loop:
for i in $(HDRS) ; do \
echo $$i \
cp $$i $(some_dir) \
done
$$i is empty. And the cp fails, having only one argument.
The usual variants of $$i ( $i, $$i, $(i), ${i} ), don't change anything, nor do the usual variants of $(HDRS) ("$(HDRS)", etc.).
gmake echos the for-loop as
for i in a.h b.h ; \
do \
echo $i \
cp $i somedir \
done
Which looks correct.
But the implicit bash shell emits an error "/bin/sh -c: line 5: syntax error: unexpected end of file"
gmake then exits due to the failed command.

Due to the \, make emits the recipe as a single line. This confuses the shell. Try this instead, using ; in place of the line terminator:
for i in a.h b.h ; \
do \
echo $i ; \
cp $i somedir ; \
done

Related

error while running a R script in a bash script

e made a bash script as follows:
#! /bin/bash
OUTDIR=".//DATA/share/pipelines/results/"
INDIR="./DATA/share/pipelines/test_data/infile/"
projectname=$1
input_bam=$2
bins=$3
mkdir OUTDIR || true
of="${OUTDIR}"
ind="${INDIR}"
./DATA/share/pipelines/script.R \
-b "${bins}" \
-c "${projectname}" \
-o "${of}" \
-i "${ind}"
echo "first step is done"
when I run the script using the following command:
bash first.sh 30 beh
I will get this error:
mkdir: cannot create directory ‘OUTDIR’: File exists
first.sh: line 17: ./DATA/share/pipelines/script.R: No such file or directory
first step is done
do you know how to solve the problem?
When you call
bash first.sh 30 beh
$1 holds 30, $2 holds beh and $3 is not defined.
input_bam ist set to $2 but is never used.
With [ ! -d ${OUTDIR} ] you should be able to test if the directory exists.
#! /bin/bash
#Please check if it should be
# relative to the current working directory (starting with './')
# or absolute (starting with '/')
BASEDIR="/DATA/share/pipelines/" #"./DATA/share/pipelines/"
OUTDIR=${BASEDIR}"results/"
INDIR=${BASEDIR}"test_data/infile/"
projectname=$1
input_bam=$2 #This is never used
bins=$3 #This is not defined when callin >bash first.sh 30 beh<
[ ! -d ${OUTDIR} ] && mkdir ${OUTDIR} #Think you would create ${OUTDIR}
of="${OUTDIR}"
ind="${INDIR}"
./DATA/share/pipelines/script.R \
-b "${bins}" \
-c "${projectname}" \
-o "${of}" \
-i "${ind}"
echo "first step is done"

Calling export in foreach loop

I am tying to pass variables to sub makefiles via export
The main Makefile contains a list of components COMPONENT_LIST that will be compiled. In the rule of the target all I exported the USE_COMP_1, USE_COMP_2and USE_COMP_3 variables using foreach function:
COMPONENT_LIST:=\
COMP_1\
COMP_2\
COMP_3
all:
$(foreach comp,$(COMPONENT_LIST),export USE_$(comp)=y;)
#for comp in $(COMPONENT_LIST) ; do \
make -C $$comp all; \
if [ ! $$? -eq 0 ]; then \
echo "component \"$$comp\" not found. Please make sure that folder \"$$comp\" exist";\
exit 1; \
fi \
done
But in the sub Makefile The value of USE_COMP_1, USE_COMP_2and USE_COMP_3 is empty.
Is there any explanation to this ?
I have found the solution.
every sub-command is run in its own shell
So I missed the the \
all:
$(foreach comp,$(COMPONENT_LIST),export USE_$(comp)=y;)\
for comp in $(COMPONENT_LIST) ; do \
make -C $$comp all; \
if [ ! $$? -eq 0 ]; then \
echo "component \"$$comp\" not found. Please make sure that folder \"$$comp\" exist";\
exit 1; \
fi \
done
In this case the export and the following for loop are run in the same shell

ZSH Completion based on previous flag

I am trying to create a completion where one of my completions will be dynamically generated depending on the values of the other flags. For example
local state
_arguments \
'-f[fabric]:fabric:->fabrics' \
'-c[containers/application where log resides]:container:->containers' \
'-l[name of log file]:log:->logs'
case "$state" in
(fabrics)
_values 'fabrics' \
'fab1' \
'fab2'
;;
(containers)
_values 'containers' \
'container1' \
'container2'
;;
(logs)
# show A B C if "-c container1" was entered
# show D E F if "-c container2" was entered
# show G if "-c" was not provided yet
esac
I am having trouble getting the "-l" flag to be dynamically generated.
We could inspect the $words:
Completion Special Parameters
...
Inside completion widgets, and any functions called from them, some parameters have special meaning;
...
words
This array contains the words present on the command line currently being edited.
-- zshcompwid(1): Completion Special Parameters, Completion Widgets
We could do the stuff like this:
(logs)
local -i index=${words[(I)-c]}
local -i ret=0
if ((index == 0)); then
_values 'logs' F
ret=$?
elif [[ "$words[index+1]" == container1 ]]; then
_values 'logs' A B C
ret=$?
elif [[ "$words[index+1]" == container2 ]]; then
_values 'logs' D E F
ret=$?
fi
return ret
To inspect arrays, it is usefull to use the array Subscript Flags:
Subscript Flags
If the opening bracket, or the comma in a range, in any subscript expression is directly followed by an opening parenthesis, the string up to the matching closing one is considered to be a list of flags, as in name[(flags)exp].
-- zshparam(1), Subscript Flags, Array Subscripts, Array Parameters
So,$words[(I)-c] means I "flag" + -c as "exp" for $words which is "Last matching element's index for "-c" in the array $word". For example:
$ tmp=(my-test-command -f flag -c container1 -l)
$ echo $tmp[(I)-c]
4
$ echo $tmp[(I)container1]
5
$ tmp=(my-test-command -f flag -c container1 -c container2 -l)
$ echo $tmp[(I)-c]
6

How to run Ag asynchronously with vimproc and quickrun - VIM?

I'm using Ag, vimproc, quickrun
I'm able to run .php asynchronously with this settings in my .vimrc
nnoremap <leader>r :QuickRun<CR>
let g:quickrun_config = get(g:, 'quickrun_config', {})
let g:quickrun_config = {
\ "_" : {
\ 'runner': 'vimproc',
\ 'runner/vimproc/updatetime': 60,
\ 'outputter/quickfix': ':quickrun-module-outputter/quickfix',
\ 'outputter/buffer/split': ':rightbelow 8sp',
\ },
\}
Does anyone know how can I run ag asynchronously?
Ag settings in .vimrc
if executable("ag")
let g:ctrlp_user_command = 'ag %s -i --nocolor --nogroup --hidden
\ --ignore .git
\ --ignore .svn
\ --ignore .hg
\ --ignore .DS_Store
\ --ignore "**/*.pyc"
\ -g ""'
endif
nnoremap <leader>a :Ag!<Space>
nnoremap <leader>aa :Ag! <C-r>=expand('<cword>')<CR>
nnoremap <leader>aaa :Ag! <C-r>=expand('<cword>')<CR><CR>
A generic solution to use asynchronous command with Vim is using a plugin called vim-dispatch, you can launch command in the background with :Start!
Alternatively, this is also a fork of vim called neovim, which is trying to address that issue. At the time of this post, it is not necessarily mature enough, but this is something to consider as well for the future.

Problem in using shell for loop inside gnu make?

consider the below make file
all:
#for x in y z; \
do \
for a in b c; \
do \
echo $$x$$a >> log_$$x; \
done; \
done
While executing this make file, two file got created log_y and log_z. log_y is having data "yb" and "yc". similarly log_z is having data"zb" and "zc".
Actually I want to create four files(log_y_b, log_y_c, log_z_b, log_z_c). For this i have modified the above make file as,
all:
#for x in y z; \
do \
for a in b c; \
do \
echo $$x$$a >> log_$$x_$$a; \
done; \
done
But its creating only one file log_. What should i have to do to create four files.
Perhaps put braces around the variable names: it works on my system.
all:
#for x in y z; \
do \
for a in b c; \
do \
echo $$x$$a >> log_$${x}_$${a}; \
done; \
done
You can also use foreach:
all:
#$(foreach x,y z,$(foreach a,b c,echo $(x)$(a) >> log_$(x)_$(a);))
log_$$x_$$a in the Makefile turns into log_$x_$a for the shell which is equivalent to log_${x_}${a}. The variable $x_ is undefined, however, so the shell substitutes it by the empty string.
Solution: Properly write the $x variable with curly braces around the name (${variablename}), i.e. for consistency's sake write log_${x}_${a} (or in Makefile style: log_$${x}_$${a}).

Resources