在一个Makefile目标中,使用flock命令内的多行if条件。

huangapple go评论73阅读模式
英文:

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

问题

以下是翻译好的部分:

我在我的Makefile中有以下的目标:

target: config
     mkdir -p results; \
     cd results; \
     flock . -c ' if ( ! -f "FINISHED_build" )  \
          ln -s $(OUTDIR) output ; \
          rm -rf work; \
          # 一些其他命令 \
          touch FINISHED_build; \
          endif ;\
     ';

尽管我知道我的 if 条件评估为假,即使我用 0 替换 if 表达式,if 条件内的命令仍然会执行,除了 `ln` 命令。

我期望我的 if 条件被视为单行语句,就像这里提到的一样:https://stackoverflow.com/questions/43567344/cannot-get-if-statement-to-work,所以我将我的 if 条件更改为:

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

添加一个 then。但行为没有改变,我得到了

if: Improper then。我知道这可能与使用反斜杠有关,但我不确定如何修复它。非常感谢任何帮助。
英文:

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 https://stackoverflow.com/questions/43567344/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.

答案1

得分: 1

如上所述在评论中提到,csh 不是脚本编写的理想工具。将其包装在 make 目标中会使在引号、使用多行语句或 shell 控制命令方面变得更加具有挑战性。当输入 make 规则的命令时,它们由结果 shell 评估。这可能会让维护变得非常混乱。

一个具体的“陷阱”是转义字符(转义的换行符 - 在“Makefile”上下文中,反引号有时用于隐藏特殊字符,以防止其对 shell 产生不同于转义它们的含义)。

还要注意,多语句规则(mkdir ... ; cd ... ; flock ...)将无条件地执行这些段 - 即使“mkdir”失败,也会执行“cd”和“flock”。通常最好将它们分开。这不适用于“cd”,它必须与 flock 一起执行。

两种可能的路径:切换到 sh(推荐),或坚持使用 csh 并使用多个语句。

“简单”的解决方案是切换到 'sh'。使用 ';' 分隔语句相对容易,后面跟着转义的换行符。请注意,在 flock 的命令中使用 "sh -c",而不是 "-c"。

flock . sh -c 'if [ ! -f "FINISHED_build" ] then ; \
          ln -s $(OUTDIR) output ; \
          rm -rf work; \
          # 一些其他命令 \
          touch FINISHED_build; \
          fi '

如果需要使用 "csh",可以考虑明确使用 csh。即使执行用户默认不使用 csh,makefile 也能工作。在这种情况下,“csh”将输入视为“交互式”,并且不允许注释('#')。如果需要注释,可以使用 ':' 来隐藏它们,以防止执行。

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

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 '

huangapple
  • 本文由 发表于 2023年7月11日 00:13:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76655560.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定