【问题标题】:Controlling verbosity of make控制 make 的详细程度
【发布时间】:2012-03-08 00:44:10
【问题描述】:

我正在使用 makefile 编译由许多 .c 文件组成的程序,并且任何时候调用 make 它只会编译那些在上次运行后修改的文件(在此之前没有什么特别的)。

为避免屏幕混乱,我在每个$(CC) 调用的开头添加@,并在它之前打印一条自定义的echo 消息。例如:

%.o: %.c $(h1) $(h3) %.h
    @echo -e "\tCompiling <" $< 
    @$(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS)

我的问题是:如何以更“动态的方式”控制make 的详细程度,以便能够:

  1. 正常行为:只为每个执行的 makefile 规则打印一条自定义消息。
  2. 详细行为:打印每个 makefile 规则实际执行的命令(好像根本没有使用 @)。

【问题讨论】:

    标签: makefile verbosity


    【解决方案1】:

    我会像 automake 那样做:

    V = 0
    ACTUAL_CC := $(CC)
    CC_0 = @echo "Compiling $<..."; $(ACTUAL_CC)
    CC_1 = $(ACTUAL_CC)
    CC = $(CC_$(V))
    
    %.o: %.c $(h1) $(h3) %.h
            $(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS)
    

    如果你需要在你的规则中执行其他命令,我喜欢下面的sn-p。写$(AT)而不是@,当V=0时它会静音,但当V=1时打印。

    AT_0 := @
    AT_1 := 
    AT = $(AT_$(V))
    

    【讨论】:

    • 在你的第一部分我想你还需要覆盖CC = $(CC_$(V))
    • 是的。它的缺席是我现在要解决的脑放屁。我还应该指出,递归变量扩展已被广泛实施,但目前在 POSIX 中尚未实现(但在未来的修订版中会有所改变)。
    • 很好的解决方案@JackKelly。创建AT 变量的方法既简单又有效!
    • 您的代码对我不起作用。我得到gist.github.com/JasonGross/7103651
    • 我不得不做 CC := $(CC_$(V))(注意冒号)来阻止 make 抱怨“递归变量 CC 引用自身”。我是不是做错了什么?
    【解决方案2】:

    另一种解决方案(我喜欢它,因为它很灵活)

    ifeq ("$(BUILD_VERBOSE)","1")
    Q :=
    vecho = @echo
    else
    Q := @
    vecho = @true
    endif
    
    %.o: %.c
        $(vecho) "-> Compiling $@"
        $(Q)$(CC) $(CFLAGS) -c $< -o $@
    

    你可以跳过 vecho 的东西,但它有时会派上用场。

    【讨论】:

      【解决方案3】:

      您可以省略“@”并将“-s”选项传递给您的 make 命令,而不是使用“@gcc”进行编译。 (保持“@echo”不变。)然后“make -s”将是您的简短 make 命令,而“make”将是冗长的。

      “-s”或“--silent”标志可防止所有回显,就好像所有食谱都以“@”开头。

      From the GNU Make manual pages

      (其他答案更好地回答了您的问题,但这种方法值得一提。)

      【讨论】:

        【解决方案4】:

        我会创建一个函数,它接受一个命令来执行并决定是否回显它。

        # 'cmd' takes two arguments:
        #   1. The actual command to execute.
        #   2. Optional message to print instead of echoing the command
        #      if executing without 'V' flag.
        ifdef V
        cmd = $1
        else
        cmd = @$(if $(value 2),echo -e "$2";)$1
        endif
        
        %.o: %.c $(h1) $(h3) %.h
            $(call cmd, \
                $(CC) $(CFLAGS) -c $< -o $(libDir)$@$(MATHOPTS), \
                Compiling $<)
        

        那么简单的make 调用的结果将是这样的:

        Compiling foo.c
        

        make V=1 会给出:

        gcc -Wall -c foo.c -o foo.o ...
        

        【讨论】:

        • 感谢@Eldar!您的建议非常好,但是按照 Jack 的建议重新定义“@”更简单。顺便说一句,我根本不知道你可以这样定义一个函数。
        【解决方案5】:

        由于我无法评论 AT = $(AT_$(V)) 的建议,请注意 Automake 确实提供了一个与 AT 执行相同操作的标准宏,称为 AM_V_at

        您还会发现它还有另一个非常有用的 AM_V_GEN 变量,根据详细程度,它要么解析为空,要么解析为 @echo " GEN " $@;

        这允许您编写如下代码:

        grldr.mbr: mbrstart
            $(AM_V_GEN)
            $(AM_V_at)-rm -f grldr.mbr
            $(AM_V_at)cat mbrstart > grldr.mbr
        

        其输出将是(禁用冗长):

          GEN    grldr.mbr
        

        或(启用详细信息):

        rm -f grldr.mbr
        cat mbrstart > grldr.mbr
        

        非常方便,无需定义自己的宏。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-29
          • 1970-01-01
          • 2020-01-21
          • 2023-03-28
          相关资源
          最近更新 更多