makefilecshflock

Having a multi line if condition inside a flock command in a Makefile target


I have that following target in my Makefile

target: config
     mkdir -p results; \
     cd results; \
     flock . -c ' if ( ! -f "FINISHED_build" )  \
          ln -s $(OUTDIR) output ; \
          rm -rf work; \
          # some other commands \
          touch FINISHED_build; \
          endif ;\
     '

although I know that my if condition is evaluation to false and even if I replace the if expression with a 0, the commands inside my if condition are still executed except for the ln command. I expected that my if condition is treated as a single line statement as mentioned here Cannot get if statement to work, so I changed my if condition to be

flock . -c ' if ( ! -f "FINISHED_build" ) then  \

to add a then. But the behavior doesn't change and I get if: Improper then. I know that might be related to using backslashes but I am not sure how to fix it. Any help is really appreciated.


Solution

  • As noted above in comment, csh is not the ideal tool for scripting. Wrapping it inside a make target will make things even more challenging with respect to quoting, using multi line statements, or shell control commands. When entering commands for make rule, they are evaluated by the result shell. Can be very confusing to maintain.

    One specific "trap" is the escaped characters (the escaped new lines - in the context of "Makefile", the backquote will sometime used to hide special characters from make, which could have different meaning from escaping them to the shell).

    Also note that the multi-statement rule (mkdir ... ; cd ... ; flock ...) will execute the segments unconditionally - the 'cd' and the 'flock' will get executed even if the 'mkdir' failed. Usually better to keep them separate. This does not apply to the 'cd', which must be executed together with the flock

    Two possible path: switch to sh (recommended), or stick with csh and use multiple statements

    The "simple" solution is to flip to 'sh'. Relatively easy to delimit statements with ';' followed by escaped new-lines. Notice using "sh -c" as the command for flock, and not '-c'.

    flock . sh -c 'if [ ! -f "FINISHED_build" ] then ; \
              ln -s $(OUTDIR) output ; \
              rm -rf work; \
              # some other commands \
              touch FINISHED_build; \
              fi '
    

    If "csh" is desired, consider using csh explictly, The makefile will work even the the executing user that is not using csh by default. In this case, 'csh' consider the input to be 'interactive', and will NOT not allow comments ('#'). If comments are needed, the ':' can be used to hide then from execution.

    flock . csh -c 'if ( ! -f "FINISHED_build" ) then ; \
              ln -s $(OUTDIR) output ; \
              rm -rf work; \
              : COMMENTS ; \
              touch FINISHED_build; \
              endif '