How to check if a make var is set inside a target? - unix

Inside a Makefile recipe, I want to check if a variable was set. Essentially, I want a "flag" to control flow.
Something like the following (though this does not work):
foo:
do_something
#if [ -z $(FLAG) ]; then\
do_something_else; \
fi
And I would call it like: make foo FLAG=1
How do I do this?

Related

bjam - cannot assign a literal to a variable?

Well, this must be the most stupid and idiotic behavior I've seen from a programming language.
https://www.bfgroup.xyz/b2/manual/release/index.html says:
Syntactically, a Boost.Jam program consists of two kinds of
elements—keywords (which have a special meaning to Boost.Jam) and
literals. Consider this code:
a = b ;
which assigns the value b to the variable a. Here, = and ; are
keywords, while a and b are literals.
⚠ All syntax elements, even
keywords, must be separated by spaces. For example, omitting the space
character before ; will lead to a syntax error.
If you want to use a literal value that is the same as some keyword,
the value can be quoted:
a = "=" ;
OK, so far so good. So I have this in my Jamroot:
import path : basename ;
actions make_mytest_install
{
echo "make_mytest_install: MY_ROOT_PATH $(MY_ROOT_PATH) PWD $(PWD:E=not_set)" ;
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
ename = basename ( $(epath) ) ;
echo "epath $(epath) ename $(ename)" ;
}
explicit install-gettext ;
make install-mytest : : #make_mytest_install ;
... and I try this:
bjam install-mytest
...updating 1 target...
Jamfile</home/USER/src/myproject>.make_mytest_install bin/install-mytest
make_mytest_install: MY_ROOT_PATH /home/USER/src/myproject PWD not_set
[ SHELL pstree -s -p 2720269 && echo PID 2720269 PWD /home/USER/src/myproject ]
/bin/sh: 13: epath: not found
/bin/sh: 14: Syntax error: "(" unexpected
.....
...failed Jamfile</home/USER/src/myproject>.make_mytest_install bin/install-mytest...
...failed updating 1 target...
Now - how come that the SIMPLEST assignment to a string, EXACTLY AS in the manual:
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
... fails, and this variable cannot be found anymore?
What is the logic in this? How the hell is this supposed to work? I would get it if MY_ROOT_PATH was undefined - but the echo before it, shows that it is not? What is this lunacy?
So I cannot believe I'm asking something this trivial, but:
How do you assign a string to a variable in bjam language?
Well, the error gives somewhat of a hint: /bin/sh: -> so apparently inside actions, it is sh that runs - then again, if it was really sh I could have assigned variables, but I can't. So best I could do, was to remove the assignments OUT of actions:
import path : basename ;
epath = "$(MY_ROOT_PATH)/projects/mytest/bin/gcc-9/release/qt5client" ;
# ename = basename ( $(epath) ) ; # nope, causes target install-mytest to not be found :(
# calling a shell for basename works - but adds a damn NEWLINE at end!?!?!?!
ename = [ SHELL "basename $(epath)" ] ;
actions make_mytest_install
{
echo "make_mytest_install: MY_ROOT_PATH $(MY_ROOT_PATH) PWD $(PWD:E=not_set)" ;
echo "epath $(epath) ename $(ename)" ;
}
explicit install-mytest ;
make install-mytest : : #make_mytest_install ;
So, assignment kind of passes, but you still can't get the basename ?!
I still don't understand, who thought this kind of variable management is a good idea ... I don't even understand, how people managed to build stuff with this system

How to initialize array from array in zsh?

My script test.zsh:
args=$#
argss=($#)
echo ${#:2}
echo ${args:2}
echo ${argss:2}
The output:
$ ./test.zsh foo bar foobar
bar foobar
o bar foobar
o
It looks like args is being initialized as the string of $# instead of as an array. How do I initialize args as an array? ($#) does not seem to work either
You need to put parentheses around $# to make args an array:
args=($#)
In other shells, you should also put quotes around it (args=("$#")) to avoid word splitting, but this is disabled by default in zsh (see the option SH_WORD_SPLIT).
Note that ${#:2} will give you $1 $2 $3 ..., while ${args:2} will give $2 $3 ..., because zsh prepends $0 to $# when you use that form of parameter subscripting for compatibility with other shells.
The preferred zsh way to subscript arrays is ${arr[start,end]}, where end is inclusive and may be negative.
${args[1,-1]} and ${args[#]} will expand to the same thing.

What is it called when you have multiple data structures, but not connected with json in jq?

For instance, I might have something coming out of my jq command like this:
"some string"
"some thing"
"some ping"
...
Note that there is no outer object or array and no commas between items.
Or you might have something like:
["some string"
"some thing"
"some ping"]
["some wing"
"some bling"
"some fing"]
But again, no commas or outer object or array and no commas between them to indicate that this is JSON.
I keep thinking the answer is that it is called "raw", but I'm uncertain about this.
I'm specifically looking for a term to look for in the documentation that allows you to process the sorts of examples above, and I am at a loss as how to proceed.
To start with, the jq manual.yml describes the behavior of filters this way:
Some filters produce multiple results, for instance there's one that
produces all the elements of its input array. Piping that filter
into a second runs the second filter for each element of the
array. Generally, things that would be done with loops and iteration
in other languages are just done by gluing filters together in jq.
It's important to remember that every filter has an input and an
output. Even literals like "hello" or 42 are filters - they take an
input but always produce the same literal as output. Operations that
combine two filters, like addition, generally feed the same input to
both and combine the results. So, you can implement an averaging
filter as add / length - feeding the input array both to the add
filter and the length filter and then performing the division.
It's also important to keep in mind that the default behavior of jq is to run the filter you specify once for each JSON object. In the following example, jq runs the identity filter four times passing one value to it each time:
$ (echo 2;echo {}; echo []; echo 3) | jq .
2
{}
[]
3
What is happening here is similar to
$ jq -n '2, {}, [], 3 | .'
2
{}
[]
3
Since this isn't always what you want, the -s option can be used to tell jq to gather the separate values into an array and feed that to the filter:
$ (echo 2;echo {}; echo []; echo 3)| jq -s .
[
2,
{},
[],
3
]
which is similar to
$ jq -n '[2, {}, [], 3] | .'
[
2,
{},
[],
3
]
The jq manual.yml explains how the --raw-input/-R option can be included for even more control over input handing:
Don't parse the input as JSON. Instead, each line of text is passed to the filter as a string. If combined with --slurp,then the entire input is passed to the filter as a single long string.
You can see using the -s and -R options together in this example produces a different result:
$ (echo 2;echo {}; echo []; echo 3)| jq -s -R .
"2\n{}\n[]\n3\n"

How can I access the current value of an environment variable in a zsh prexec function?

I have a simple function like
function clearit() {
REM=$(($LINENO % $LINES))
DIV=$(($LINENO / $LINES))
if [[ $DIV -gt 0 && $REM -lt 3 && $DIV ]]; then
clear
fi
echo $LINENO, $LINES
}
add-zsh-hook preexec clearit
In the above function a static value of $LINE and $LINES is added to the prehook function. I want to get the current value when the prexec is executed. How can I do that ?
For normal shell variables, you will get the current value:
% x=1
% function test_hook() { echo $x; }
% add-zsh-hook preexec test_hook
% true
1
% x=2
1
% true
2
However, $LINENO is a very special variable. From the documentation:
LINENO <S>
The line number of the current line within the current script, sourced file, or shell function being executed, whichever was started most recently. Note that in the case of shell functions the line number refers to the function as it appeared in the original definition, not necessarily as displayed by the functions builtin.
When your hook function is executing, it is by definition the most recently started shell function, script or sourced file. So $LINENO always gives you the current line within your hook function. There is no way to access the $LINENO for the outer scope.
However, even if you could access the outer $LINENO in your hook, it would lead to very strange behaviour in my opinion. Let's say your terminal is 30 lines high ($LINES is 30), it would clear the terminal before executing the 30th, 31st and 32nd command, then nothing for the next 27 commands, then again clearing before the 60th, 61st and 62nd, and so on. I don't think this is remotely what you are trying to achieve...

side effect of zsh echo?

For some reason this script will work with all of the 'echo's at the end, but without them $wall is an empty string. This seems like really odd behaviour.
#!/bin/zsh
if [ ! -n "$1" ] ; then
files=(~/pictures/backgrounds/*jpg)
else
while [ $1 ] ; do
files+=(`echo $1/*jpg`)
shift
done
fi
echo $files
N=${#files}
echo $N
((N=RANDOM%N))
echo $N
wall=${files[$N]}
echo $wall
cp $wall ~/wall.jpg
This code will sometimes fail because RANDOM%N can result in zero and zsh array indexes start with 1. You should use RANDOM%N+1 instead.
You can:
setopt ksharrays
to enable zero-based indexing.
From man zshoptions:
Emulate ksh array handling as closely as possible. If this
option is set, array elements are numbered from zero, an array
parameter without subscript refers to the first element instead
of the whole array, and braces are required to delimit a sub‐
script (${path[2]}' rather than just$path[2]').

Resources