Makefile wait if the file exists - makefile

I am trying this command:
if [ -f "${FOO}"]; then \
sleep 5; \
fi
But I see an error like this:
/bin/sh: line 0: [: missing `]'
Can someone explain this to me.
Thanks in advance.

Looks like I was missing a space:
OLD: if [ -f "${FOO}"]; then \
NEW: if [ -f "${FOO}" ]; then \

Related

Makefile: write conditional statement for the shell

I used this post as a basis for how to pass arguments to a make target.
I would like to perform a string comparison on this command line arg, using this post as inspiration for doing string equality comparisons in a makefile.
Update using the suggested answer below:
%:
#:
test:
if [ '$(filter-out $#,$(MAKECMDGOALS))' = hi ]; \
echo "WON"; \
else \
echo "LOST"; \
fi
where I do 8 spaces instead of indents, nothing prints. When I do tabs instead of spaces, I get the following errors:
if [ 'hi' = hi ]; \
echo "WON"; \
else \
echo "LOST"; \
fi
/bin/sh: -c: line 0: syntax error near unexpected token `else'
/bin/sh: -c: line 0: `if [ 'hi' = hi ]; echo "WON"; else echo "LOST"; fi'
make: *** [test] Error 2
Original attempt:
%:
#:
test:
ifeq ($(filter-out $#,$(MAKECMDGOALS)),hi)
echo "WON"
else
echo "LOST"
endif
However, when I run, make test hi, I get
arg="hi"
ifeq (hi,hi)
/bin/sh: -c: line 0: syntax error near unexpected token `hi,hi'
/bin/sh: -c: line 0: `ifeq (hi,hi)'
make: *** [test] Error 2
What is the unexpected token ?
ifeq is a make directive. By indenting it with a TAB, you have put it into the recipe, and all commands in the recipe are passed to the shell. The shell has no idea what an ifeq command is, and can't understand all the parens here, so you get these errors.
If you want to conditionalize on an automatic variable like $#, which are only available in the recipe, you have to write a shell conditional statement you can't use a make conditional statement:
test:
if [ '$(filter-out $#,$(MAKECMDGOALS))' = hi ]; then \
echo "WON"; \
else \
echo "LOST"; \
fi
Leaving this answer as the one posted doesn't work as it is missing a then
test:
if [ '$(filter-out $#,$(MAKECMDGOALS))' = hi ]; then \
echo "WON"; \
else \
echo "LOST"; \
fi
shell conditionals go if [] then ... else ... fi

Makefile: Syntax error /bin/sh: -c: syntax error: unexpected end of file

I have a simple Makefile:
git_repo := some_git_repo
repo:
if [ -v $(git_repo) ]; then \
echo "exists!" \
else \
echo "not exist!" \
fi;
clean: repo
Running make clean gives me an error:
/bin/sh: -c: line 4: syntax error: unexpected end of file
make: *** [repo] Error 2
I'm not quite sure what's the cause for this error. I've double checked the syntax countless times, checked many different StackOverflow questions and even tried running the bash code under the repo rule separately and it works fine. What am I doing wrong here?
You need semicolons. The "\" effect is to put everything on the same line.
repo:
if [ -v $(git_repo) ]; then \
echo "exists!"; \
else \
echo "not exist!"; \
fi;
See the echo ends with a semicolon now.
The backslashes cause all the shell lines to be concatenated into one long line, which means you need semi-colons at the end of each line to separate the statements.
if [ -v $(git_repo) ]; then \
echo "exists!"; \
else \
echo "not exist!"; \
fi
After the backslashes and newlines are removed (and $(git_repo) is substituted) the shell sees:
if [ -v some_git_repo ]; then echo "exists!"; else echo "not exist!"; fi

Is conditional statement in Makefile valid syntax

I have the following Makefile
~/w/i/craft-api git:develop ❯❯❯ cat Makefile ⏎ ✱ ◼
test:
echo "TODO: write tests"
generate-toc:
if ! [ -x "$(command -v doctoc)" ]; then
echo "Missing doctoc. Run 'npm install doctoc -g' first"
else
doctoc ./README.md
fi
I'm encountering this error
~/w/i/craft-api git:develop ❯❯❯ make generate-toc ✱ ◼
if ! [ -x "" ]; then
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [generate-toc] Error 2
What is incorrect in my Makefile syntax / usage?
edit 1
Adding line-continuing backslashes doesn't appear to fix the issue:
~/w/i/craft-api git:develop ❯❯❯ cat Makefile ⏎ ✱ ◼
test:
echo "TODO: write tests"
generate-toc:
if ! [ -x "$(command -v doctoc)" ]; then \
echo "Missing doctoc. Run 'npm install doctoc -g' first" \
else \
doctoc ./README.md \
fi
~/w/i/craft-api git:develop ❯❯❯ make generate-toc ✱ ◼
if ! [ -x "" ]; then \
echo "Missing doctoc. Run 'npm install doctoc -g' first" \
else \
doctoc ./README.md \
fi
/bin/sh: -c: line 1: syntax error: unexpected end of file
make: *** [generate-toc] Error 2
Every line is treated as a separate command and is passed to a different shell instance. You can use \ continuations to combine all of the lines so make knows to pass them as one long string to a single shell. This removes the newlines so you also need to add ; at the end of each command.
if ! [ -x "$$(command -v doctoc)" ]; then \
echo "Missing doctoc. Run 'npm install doctoc -g' first"; \
else \
doctoc ./README.md; \
fi
You'll also want to escape the $, otherwise make will interpret it rather than the shell.

Makefile multiline dash command run executable in a detached process

I have the following target in my makefile: (I'd like to run python http server in a detached process and when bash script is done kill the server)
TEST_PORT = 17777
test::
$(ENV_VARS) \
python -m SimpleHTTPServer $(TEST_PORT); \
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); \
echo $(PID); \
if [ -n "$$PID" ]; \
then \
python test.py; \
fi; \
function finish { \
if [ -n "$$PID" ]; \
then \
kill -9 $$PID; \
fi \
} \
trap finish EXIT;
However when I put a & after the line python ... I get an error
/bin/dash: Syntax error: ";" unexpected
How can this be done in a proper way?
EDIT
I have changed my makefile to do the following:
test::
python -m SimpleHTTPServer $(TEST_PORT) &
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); \
if [ -n "$$PID" ]; \
then \
$(ENV_VARS) python test.py; \
fi \
function finish { \
if [ -n "$$PID" ]; \
then \
kill -9 $$PID; \
fi \
} \
echo $$PID; \
trap finish EXIT;
However I am getting an error: (without the line number)
/bin/dash: Syntax error: word unexpected
The important thing to remember here is that your line breaks don't actually exist when the shell sees the command.
So your first command becomes:
$(ENV_VARS) python -m SimpleHTTPServer $(TEST_PORT); PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); echo $(PID); if [ -n "$$PID" ]; then python test.py; fi; function finish { if [ -n "$$PID" ]; then kill -9 $$PID; fi } trap finish EXIT;
And your second command becomes:
PID=$$(lsof -t -i #localhost:$(TEST_PORT) -sTCP:listen); if [ -n "$$PID" ]; then $(ENV_VARS) python test.py; fi function finish { if [ -n "$$PID" ]; then kill -9 $$PID; fi } echo $$PID; trap finish EXIT;
Now those are both very hard to read so I don't expect you to spot the problem but the problem is that you are missing statement terminators in a few places.
Specifically:
Braces ({}) are word elements and so need spaces around them (and a terminator before, and after, the closing brace). You are missing those terminators here fi } trap and here fi } echo.
fi is also not a statement terminator and so it needs one between it and the next statement. You are missing one here test.py; fi function (as well as the ones in the braces from the first point).

GNUMAKE: find if a string is present in a file before updating it

I am trying to add "description" to $(#)/etc/release file only if its not there already
$(PROJECTDIR)/projectroot:
if [ grep -q "description" "$(#)/etc/release" ]; then \
echo "description :" $(PLATFORM) >> $(#)/etc/release; \
fi
but it throws error "/bin/sh: line 0: [: too many arguments" and not doing anything with release file. can you please help. Thanks a lot.
As per my comment (and an edit I was about to make but couldn't). What you want is:
$(PROJECTDIR)/projectroot:
if ! grep -q description '$(#)/etc/release'; then \
echo 'description :' $(PLATFORM) >> '$(#)/etc/release'; \
fi
or (assuming you don't have whitespace you want echo to normalize for you inside the value of $(PLATFORM)):
$(PROJECTDIR)/projectroot:
if ! grep -q description '$(#)/etc/release'; then \
echo 'description : $(PLATFORM)' >> '$(#)/etc/release'; \
fi

Resources