GNUmakefile handles echo in ifeq - gnu-make

Say I have the following in the GNUmakefile
ifeq ($(MODELS), abc)
#echo PASS <== line 45
endif
How come I keep on getting the following error?
GNUmakefile:45: * missing separator. Stop.
Pls note, the echo works fine if it is NOT in the ifeq clause

ah I know why. You need to make sure there is NO space/TAB before "ifeq", "endif" and NO space before the $echo.For the echo line, it can only be TABs. Why do GNUmakefile is so picky on spaces/tabs, these invisible rules are really not institutive.

Related

zsh function only runs once

I'm fairly new to zsh (oh-my-zsh) and i'm trying to write a custom theme.
I ran into a problem and reduced it to the following testcase
PROMPT='$RANDOM > '
works as expected, it produces a random number on each command.
But when using a function
PROMPT='$(my_random) > '
function my_random(){
echo $RANDOM
}
it always returns the same number, even after source ~/.zshrc still the same number. only when i close the terminal window and open it again, i get a new number which stays the same for the complete session.
only when i do:
PROMPT='$RANDOM $(my_random) > '
function my_random(){
echo $RANDOM
}
i get two random numbers as expected... any explanation for this behaviour?
btw, i'm using kde's konsole on a fresh arch install.
Edit
fwiw i found using /dev/urandom directly works well. I would still like to know whats going on.
function my_random() {
echo $(cat /dev/urandom | tr -dc '0-9' | head -c5)
}
$()-expansion happens in a subshell, and changes to $RANDOM in a subshell don’t affect the parent. From zshparam(1):
The values of RANDOM form an intentionally-repeatable pseudo-random sequence; subshells that reference RANDOM will result in identical pseudo-random values unless the value of RANDOM is referenced or seeded in the parent shell in between subshell invocations.
You don’t need to turn to setting the prompt to reproduce it:
% echo $(echo $RANDOM)
17454
% echo $(echo $RANDOM)
17454
bash doesn’t share zsh’s behaviour here.
The annoying bit is that prompt expansion also happens in a subshell, so you can’t just fix this by referencing $RANDOM in, say, precmd. The best way I can find is to do it in an empty expansion:
PROMPT='${RANDOM##*}$(my_random) > '
As said in a comment by chepner, you can fix this by putting : $RANDOM; in your precmd. This causes the value of $RANDOM to be taken and a new one to be generated.
e.g.
precmd() {
: $RANDOM;
...
}

Using shebang in a spec file without it being a comment

I need to make a small wrapper script around the binary I'm packing in an RPM. That wrapper script needs to say "#!/bin/sh" at the top. But when I do that, the "#..." is treated like a comment. No, don't comment that.
Is there any way to use a predefined variable or escape sequence to make a shebang (on the first line)?
Here's my little code in the .spec file:
%build
echo #!/bin/bash > foobar
echo export LD_LIBRARY_PATH=/opt/foobar/foobar/lib >> foobar
echo /opt/foobar/lib/foobar >> foobar
echo exit $? >> foobar
... where the result of the 1st line in the %build cycle is simply "+ echo."
Must I take a different approach? If so, what approach?
Just coming back to my question.
Quote the hash-bang. 'nuff said.Thanks.

compiling a ICC binary [duplicate]

I am getting the following error running make:
Makefile:168: *** missing separator. Stop.
What is causing this?
As indicated in the online manual, the most common cause for that error is that lines are indented with spaces when make expects tab characters.
Correct
target:
\tcmd
where \t is TAB (U+0009)
Wrong
target:
....cmd
where each . represents a SPACE (U+0020).
Just for grins, and in case somebody else runs into a similar error:
I got the infamous "missing separator" error because I had invoked a rule defining a function as
($eval $(call function,args))
rather than
$(eval $(call function,args))
i.e. ($ rather than $(.
This is a syntax error in your Makefile. It's quite hard to be more specific than that, without seeing the file itself, or relevant portion(s) thereof.
For me, the problem was that I had some end-of-line # ... comments embedded within a define ... endef multi-line variable definition. Removing the comments made the problem go away.
My error was on a variable declaration line with a multi-line extension. I have a trailing space after the "\" which made that an invalid line continuation.
MY_VAR = \
val1 \ <-- 0x20 there caused the error.
val2
In my case, I was actually missing a tab in between ifeq and the command on the next line. No spaces were there to begin with.
ifeq ($(wildcard $DIR_FILE), )
cd $FOLDER; cp -f $DIR_FILE.tpl $DIR_FILE.xs;
endif
Should have been:
ifeq ($(wildcard $DIR_FILE), )
<tab>cd $FOLDER; cp -f $DIR_FILE.tpl $DIR_FILE.xs;
endif
Note the <tab> is an actual tab character
In my case error caused next. I've tried to execute commands globally i.e outside of any target.
UPD. To run command globally one must be properly formed. For example command
ln -sf ../../user/curl/$SRC_NAME ./$SRC_NAME
would become:
$(shell ln -sf ../../user/curl/$(SRC_NAME) ./$(SRC_NAME))
In my case, this error was caused by the lack of a mere space. I had this if block in my makefile:
if($(METHOD),opt)
CFLAGS=
endif
which should have been:
if ($(METHOD),opt)
CFLAGS=
endif
with a space after if.
In my case, the same error was caused because colon: was missing at end as in staging.deploy:. So note that it can be easy syntax mistake.
I had the missing separator file in Makefiles generated by qmake. I was porting Qt code to a different platform. I didn't have QMAKESPEC nor MAKE set. Here's the link I found the answer:
https://forum.qt.io/topic/3783/missing-separator-error-in-makefile/5
Just to add yet another reason this can show up:
$(eval VALUE)
is not valid and will produce a "missing separator" error.
$(eval IDENTIFIER=VALUE)
is acceptable. This sort of error showed up for me when I had an macro defined with define and tried to do
define SOME_MACRO
... some expression ...
endef
VAR=$(eval $(call SOME_MACRO,arg))
where the macro did not evaluate to an assignment.
I had this because I had no colon after PHONY
Not this,
.PHONY install
install:
install -m0755 bin/ytdl-clean /usr/local/bin
But this (notice the colon)
.PHONY: install
...
Following Makefile code worked:
obj-m = hello.o
all:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
$(MAKE) -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
So apparently, all I needed was the "build-essential" package, then to run autoconf first, which made the Makefile.pre.in, then the ./configure then the make which works perfectly...

ifeq issue: compare 2 strings with a dot included

I am trying to implement a simple string comparison to get the type of a file (using its extension) like this:
extract_pkg: $(PKG)
$(eval EXT := $(suffix $(PKG)))
#echo $(EXT)
ifeq ($(EXT), .zip)
#echo "is zip file"
else
#echo "is not a zip file"
endif
extract_pkg : PKG = mypkg.zip
However, when I run it it goes into the else branch. My guess is, it has to do with the dot, but I dont find a solution. Thanks for your help !
Edit 1: the essential code would be actually somewhat like the following, and it works as expected:
test_cmp:
ifeq (.zip,.zip)
#echo ".zip==.zip"
endif
ifeq (zip,zip)
#echo "zip==zip"
endif
thus the problem is somewhere else !
One thing to be careful about -- spaces in if constructs are significant. So if you have something like:
ifeq ($(EXT), .zip)
it will only match if $(EXT) expands to exactly ".zip" -- including the space before the period. So your first example will always print is not a zip file, since $(EXT) will never contain the space.
You cannot use ifeq() etc. inside recipes. ifeq() are preprocessor statements: they are interpreted immediately as the makefile is read in. Recipes are not run until much later, after all makefiles are parsed and make decides that this target needs to be updated. So trying to set a variable in a recipe using eval, etc. then test that variable using ifeq() cannot work.
You have to use shell constructs for this; something like:
extract_pkg: $(PKG)
#EXT=$(suffix $<); \
echo $$EXT; \
if [ $$EXT = .zip ]; then \
echo "is zip file"; \
else \
echo "is not a zip file"; \
fi

Unix ksh loop and put the result into variable

I have a simple thing to do, but I'm novice in UNIX.
So, I have a file and on each line I have an ID.
I need to go through the file and put all ID's into one variable.
I've tried something like in Java but does not work.
for variable in `cat myFile.txt`
do
param=`echo "${param} ${variable}"`
done
It does not seems to add all values into param.
Thanks.
I'd use:
param=$(<myFile.txt)
The parameter has white space (actually newlines) between the names. When used without quotes, the shell will expand those to spaces, as in:
cat $param
If used with quotes, the file names will remain on separate lines, as in:
echo "$param"
Note that the Korn shell special-cases the '$(<file)' notation and does not fork and execute any command.
Also note that your original idea can be made to work more simply:
param=
for variable in `cat myFile.txt`
do
param="${param} ${variable}"
done
This introduces a blank at the front of the parameter; it seldom matters. Interestingly, you can avoid the blank at the front by having one at the end, using param="${param}${variable} ". This also works without messing things up, though it looks as though it jams things together. Also, the '${var}' notation is not necessary, though it does no harm either.
And, finally for now, it is better to replace the back-tick command with '$(cat myFile.txt)'. The difference becomes crucial when you need to nest commands:
perllib=$(dirname $(dirname $(which perl)))/lib
vs
perllib=`dirname \`dirname \\\`which perl\\\`\``/lib
I know which I prefer to type (and read)!
Try this:
param=`cat myFile.txt | tr '\n' ' '`
The tr command translates all occurrences of \n (new line) to spaces. Then we assign the result to the param variable.
Lovely.
param="$(< myFile.txt)"
or
while read line
do
param="$param$line"$'\n'
done < myFile.txt
awk
var=$(awk '1' ORS=" " file)
ksh
while read -r line
do
t="$t $line"
done < file
echo $t

Resources