0

I need to add shell if-else statement to my Makefile, but the if expression always evaluates to false. For example the next code:

if [1 -eq 1]; then echo "yes"; else echo "no"

prints "no"

The only code that evaluated to true was:

if true; then echo "yes"; else echo "no"

Why all expressions in the code (except for "true") evaluates to false? :( I would really appreciate any help

** Please note - the statements work correctly when run from Shell

The code snippet from the original Makefile:

SIMULATION_RUN_CMD =  rm -rf $(TEST_DIR)/* && mkdir -p $(TEST_DIR) && cd $(TEST_DIR) && (cp -rf $(VIVADO_PROJ)/$(PROJECT)/export_for_sim/$(SIMULATOR)/{*.mem,.mif,design.dat,nocattrs.dat,cpm_data_sim.cdo} $(TEST_DIR) || true) && \
                                        ln -sf $(TEST_DIR)/simulation.log $(RUN_DIR)/simulation.log && \
                                        (timeout $(SIM_TIMEOUT) ${SIM_DIR}/simv +UVM_TESTNAME=$(UVM_TESTNAME) $(SIM_FLAGS) -l $(TEST_DIR)/simulation.log -do $(DO_FILE) ; \
                                        if [1 -eq 1]; then echo "if statement yes " >> $(TEST_DIR)/simulation.log; else echo "if statement no " >> $(TEST_DIR)/simulation.log; fi \
                                         || true) && \
                                        $(MODEL_POST_SIM_ACIONS)


$(SIMULATION_RUN_TAR):
    @echo -e "Make Command: $(SIMULATION_RUN_CMD)" $(PRINT_OUTPUT)
    ($(SIMULATION_RUN_CMD)) $(PRINT_OUTPUT)
Halona
  • 1,475
  • 1
  • 15
  • 26
  • No, `if [1 -eq 1]; then echo "yes"; else echo "no"` does _not_ run correctly when run at the shell (or, rather, emitting "no" is the _correct_ thing for it to do, as `[1` -- unlike `[` -- is not a valid command). – Charles Duffy Jul 26 '22 at 14:44
  • It does not "evaluate to false". In the shell `if` does not check a boolean expression. The command that you are running (`[1`) is failing. Almost certainly, it is failing because `[1` is not in your PATH. Stop thinking about "expressions". The syntax is `if command; then ...`. It is *not* `if expression; then ...` or `if boolean; then...` or `if condition; then ...` – William Pursell Jul 26 '22 at 14:49

1 Answers1

1

First, you have a syntax error in your command. If you type that exactly into bash you'll get an error:

[[1: command not found

You need spaces after the [[ and before the ]] tokens:

if [[ 1 -eq 1 ]]; then echo "yes"; else echo "no"

Second, the reason it doesn't work when run from make is that make doesn't invoke bash. Make invokes the POSIX standard shell /bin/sh. If you do this you'll see the same behavior you get with make:

$ /bin/sh -c 'if [[ 1 -eq 1 ]]; then echo yes; else echo no; fi'
/bin/sh: 1: [[: not found
no

The [[ operator is a bash-specific feature. If you want to write this using POSIX features you should use:

$ /bin/sh -c 'if [ 1 -eq 1 ]; then echo yes; else echo no; fi'
yes

If you really want make to invoke bash as its shell instead of sh, add this to your makefile:

SHELL := /bin/bash

Of course then your makefile will not work on any system that doesn't have /bin/bash available.

ETA

After seeing the very much more complicated, but still not complete, code you added, I will say the following:

As I said above, you have an error in your script. if [1 -eq 1] is completely illegal. You must have spaces after [ and before ]. Again, if you run this yourself at the shell prompt you will get the same failure. It has nothing to do with make.

Because of this error, the if-statement will ALWAYS fail and so this will ALWAYS run the "else" command and print "no".

You say you don't see any error message. I can't explain that, except that you run this recipe this way:

($(SIMULATION_RUN_CMD)) $(PRINT_OUTPUT)

You don't tell use what the value of the PRINT_OUTPUT variable is, so I can only assume that it throws away stderr into the bit-bucket (or possibly, both stdout and stderr). If you didn't do that, so you could see the output, you'd see the error message being printed. Or maybe that redirects to a log file in which case, you can look there for the message.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • Hey @MadSchientist, you are right - my Makefile invokes sh (I'll fix the question). But, I don't get an error with "[[" or "[". The problem is that the expression as you've wrote 'if [ 1 -eq 1 ]; then echo yes; else echo no; fi' prints "no" when executed from Makefile, at least in my case.. :( – Halona Jul 26 '22 at 11:49
  • Did you verify that it prints correctly from an interactive shell (make sure that you copy and paste it verbatim)? If it does, you would perhaps have to post the complete make rule here. – user1934428 Jul 26 '22 at 11:56
  • Yes - all the statements work correctly when I run them from the shell. I will add the Makefile snippet – Halona Jul 26 '22 at 12:09
  • Sorry but I don't believe you :). If you run this: `echo 'all: ; if [ 1 -eq 1 ]; then echo yes; else echo no; fi' | make -f-` and it prints "no" then I don't know what to say except you need to reload your operating system because it's completely corrupted in some unfathomable way. – MadScientist Jul 26 '22 at 14:34
  • @MadScientist, you were right with the spaces.. there was difference between Makefile code and my shell script code (and I was not familiar at all with "[" concept). Thank you for not believing me - this solve my issue! :) – Halona Jul 27 '22 at 07:09