【问题标题】:Using conditional rules in a makefile在生成文件中使用条件规则
【发布时间】:2012-02-07 08:26:30
【问题描述】:

我用伪代码捕捉 Makefile 的意图,然后指出我遇到的问题。我正在寻找一个在测试环境中对用户更友好的 Makefile。 Makefile 的正确用法是以下之一。

    make CATEGORY=parser TEST=basic.
    make ALL

如果用户给出“JUST”如下所示的命令,它应该打印一条消息“CATEGORY defined TEST undefined”,反之亦然

    make CATEGORY=parser
    make TEST=basic

我尝试通过以下方式编写 Makefile,但出现错误:

    help:
        echo"Usage: make CATEGORY=<advanced|basic> TEST=<test-case>
        echo"       make ALL

    ifdef CATEGORY
        ifdef TEST
            CATEGORY_TEST_DEFINED = 1
        else
             echo "TEST not defined"
    else
        echo "CATEGORY not defined"
    endif



    ifeq ($(CATEGORY_TEST_DEFINED), 1)
    $(CATEGORY):
        cd $(PROJ)/$(CATEGORY)
        make -f test.mk $(TEST)
    endif

    ifdef ALL
    $(ALL):
         for i in `ls`
         cd $$(i)
         make all
    endif

我的问题是:

  1. Makefile 中的规则是否可以选择性(使用 ifdef 选择规则和目标)。

  2. 回显不起作用。 echo 应该可以帮助用户正确使用。

【问题讨论】:

标签: makefile conditional-compilation


【解决方案1】:

这里最大的问题是所有ifdef/ifndef/ifeq/... 语句必须在第0 列,否则会导致错误。与缩进问题相比,回声是一个小问题。

【讨论】:

    【解决方案2】:

    这些行是可疑的:

    help:
        echo"Usage: make CATEGORY=<advanced|basic> TEST=<test-case>
        echo"       make ALL
    

    echo和字符串之间需要一个空格,字符串需要终止:

    help:
        echo "Usage: make CATEGORY=<advanced|basic> TEST=<test-case>"
        echo "       make ALL"
    

    这些行是可疑的:

    ifdef CATEGORY
        ifdef TEST
            CATEGORY_TEST_DEFINED = 1
        else
             echo "TEST not defined"
    else
        echo "CATEGORY not defined"
    endif
    

    在第二个else 之前肯定需要endif? (即使它在语法上不是强制性的,我也会推荐它。)

    ifdef CATEGORY
        ifdef TEST
            CATEGORY_TEST_DEFINED = 1
        else
             echo "TEST not defined"
        endif
    else
        echo "CATEGORY not defined"
    endif
    

    此外,make 只执行诸如echo 之类的命令,在处理目标(规则)时应该是这样。它不会在那里执行echo;它只会反对您无法定义命令而不将它们作为目标的操作。尽管 GNU Make 向 makefile 添加了所有内容,但 makefile 中的语言是一种声明性语言,而不是一种过程性语言。


    另一种处理方式是为宏定义默认值:

    CATEGORY = advanced
    TEST     = all
    

    定义做一些半合理的事情的默认值;如果他们愿意,让用户覆盖默认值。你可以有这样的规则:

    ${CATEGORY}/${TEST}: ...dependencies...
        ...actions...
    

    您可以将help 作为第一条规则。我有一些目录,其中第一条规则是:

    null:
        @echo "You must specify a target with this makefile!"
    

    这等同于你所拥有的(除了make 在运行它之前不回显命令,所以我只看到消息而不是回显命令行和消息;那是@ 在工作)。这个来自的makefile也有一个规则all,否则通常是最明智的第一(默认)规则。

    【讨论】:

      【解决方案3】:

      问题是echo属于shell; Make 可以在命令中将它传递给 shell,但 Make 不能执行它。请改用info

      ifdef CATEGORY
      $(info CATEGORY defined)
      else
      $(info CATEGORY undefined)
      endif
      

      如果您希望规则是有条件的:

      ifdef CATEGORY
      ifdef TEST
      $(CATEGORY):
          whatever
      else
      $(info TEST not defined)
      else
      $(info CATEGORY not defined)
      endif
      

      【讨论】:

      • 感谢您的意见。如果 Make 无法执行 shell 命令,那么我已经看到 Makefiles 有(这里很难缩进)例如,hello: @echo "Hello There"。做你好输出->你好
      • @Mike:是的,在这种情况下,echohello 规则中的命令中。当你“打招呼”时,Make 将该命令发送到 shell。如果您想这样做,则必须将“未定义”消息与某些目标相关联,这看起来很不整洁。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      • 2011-05-14
      • 1970-01-01
      相关资源
      最近更新 更多