【问题标题】:What is the variable $(MAKE) in a makefile?makefile 中的变量 $(MAKE) 是什么?
【发布时间】:2016-12-23 01:10:06
【问题描述】:

我目前正在学习如何编写 makefile。我有以下 makefile(它是为应该在 ARM 芯片上运行的 C 项目自动生成的),我正在尝试理解它:

    RM := rm -rf

    # All of the sources participating in the build are defined here
    -include sources.mk
    -include FreeRTOS/Supp_Components/subdir.mk
    -include FreeRTOS/MemMang/subdir.mk
    -...
    -include subdir.mk
    -include objects.mk

    ifneq ($(MAKECMDGOALS),clean)
    ifneq ($(strip $(S_UPPER_DEPS)),)
    -include $(S_UPPER_DEPS)
    endif
    ifneq ($(strip $(C_DEPS)),)
    -include $(C_DEPS)
    endif
    endif

    -include ../makefile.defs

    # Add inputs and outputs from these tool invocations to the build variables 

    # All Target
    all: FreeRTOS_T02.elf

    # Tool invocations
    FreeRTOS_T02.elf: $(OBJS) $(USER_OBJS)
        @echo 'Building target: $@'
        @echo 'Invoking: MCU GCC Linker'
        arm-none-eabi-gcc -mcpu=cortex-m7 -mthumb -mfloat-abi=hard -mfpu=fpv5-sp-d16 -specs=nosys.specs -specs=nano.specs -T LinkerScript.ld -Wl,-Map=output.map -Wl,--gc-sections -lm -o "FreeRTOS_T02.elf" @"objects.list" $(USER_OBJS) $(LIBS)
        @echo 'Finished building target: $@'
        @echo ' '
        $(MAKE) --no-print-directory post-build

    # Other Targets
    clean:
        -$(RM) *
        -@echo ' '

    post-build:
        -@echo 'Generating binary and Printing size information:'
        arm-none-eabi-objcopy -O binary "FreeRTOS_T02.elf" "FreeRTOS_T02.bin"
        arm-none-eabi-size "FreeRTOS_T02.elf"
        -@echo ' '

    .PHONY: all clean dependents
    .SECONDARY: post-build

    -include ../makefile.targets

我正试图绕开$(MAKE) --no-print-directory post-build 行在制作.elf 文件的规则中。

我找不到变量$(MAKE) 的定义,所以我假设它是内置的。这条线实际上在做什么?

【问题讨论】:

标签: makefile build


【解决方案1】:

这是对make 本身的递归调用,转发-t-n-q 选项。这是有道理的:您希望嵌套的 make 调用也与这些选项一起运行。

【讨论】:

  • 非常感谢您的回答。我有另一个(不是真正相关的)问题。为什么构建后的@echo 命令前面有- 字符?生成可执行文件的规则中的@echo 命令没有。
  • @K.Mulier, - 用于在命令失败时忽略错误(退出状态非零)。有关详细信息,请参阅this post。但是,我真的不明白为什么它在@echo 中。
【解决方案2】:

来自docs

这个变量的值是调用make时使用的文件名

在你必须调用 its makefile 的情况下,它很有用,但你正在使用-t (--touch)、@987654324 进行某种空运行@ (--just-print) 或 -q (--question) 标志。如果使用($MAKE),该行为将递归传播。

【讨论】:

  • “调用 make 的文件名”究竟是什么?
  • 文档中的剩余段落:如果此文件名为 /bin/make,则执行的配方为“cd subdir && /bin/make”。如果您使用特殊版本的 make 来运行顶级 makefile,则将对递归调用执行相同的特殊版本。
  • 所以,如果我通过双击文件C:\Apps\SysGCC\arm-eabi\bin\make.exe 来启动GNU make 程序,那么$(MAKE) 变量将扩展为字符串"C:\Apps\SysGCC\arm-eabi\bin\make.exe"?
  • 好吧,“双击”有点过于简单,因为这意味着没有给它任何选项。但你明白了;-)
  • > 如果我通过双击文件启动 GNU make 程序 是的,应该是。您可以尝试编写一个简单的 makefile 来执行 echo $(MAKE) 或类似的操作。
【解决方案3】:

请不要对前面提到的递归调用的答案感到困惑。 $MAKE 是被“make”替换的默认变量。

在您的场景中,$MAKE 用于 makefile 的命令部分(配方)。这意味着每当依赖关系发生变化时,make都会在你所在的目录中执行make --no-print-directory post-build命令

例如,如果我有一个案例在

test.o: test.c
      cd /root/
      $(MAKE) all

上面写着,如果test.c有变化,在/root目录下执行make all

【讨论】:

  • 这个例子演示了一个非常常见的错误。 make recipe 的每一行都独立传递给shell。因此,如果您想在目录/root 中执行某些操作,那么配方应该类似于cd /root/ && $(MAKE) all。如所写,cd /root/ 行将 cd 进入/root 并退出。然后$(MAKE) all在当前目录而不是/root/中执行。这在 GNU Make 文档中有介绍。
【解决方案4】:

Makefile中变量MAKE的含义

makefile 中的变量 $(MAKE) 是什么?

请参阅 make 手册(在本地运行 man make),第 5.7.1 节:https://www.gnu.org/software/make/manual/make.html#MAKE-Variable

让我强调它说的部分:“递归make命令应该始终使用变量MAKE,而不是显式命令名称make”这里的“递归”仅仅意味着你是在生成文件中调用make。因此,当您使用 make 调用外部 Makefile 时,它​​会通过 MAKE 特殊变量而不是直接通过 make 再次调用 make。请参阅下面的手册:

5.7.1 MAKE 变量的工作原理

递归 make 命令应始终使用变量 MAKE,而不是显式命令名称 make,如下所示:

subsystem:
        cd subdir && $(MAKE)

此变量的值是调用 make 时使用的文件名。如果此文件名为/bin/make,则执行的配方为cd subdir && /bin/make。如果您使用特殊版本的 make 来运行顶级 makefile,则会为递归调用执行相同的特殊版本。

作为一项特殊功能,在规则的配方中使用变量 MAKE 会改变 -t (--touch)、-n (--just-print) 或 -q (@987654342) 的效果@) 选项。使用MAKE 变量与在配方行开头使用+ 字符具有相同的效果。请参阅代替执行配方。仅当 MAKE 变量直接出现在配方中时才会启用此特殊功能:如果通过扩展另一个变量来引用 MAKE 变量,则它不适用。在后一种情况下,您必须使用+ 令牌来获得这些特殊效果。

【讨论】:

    猜你喜欢
    • 2011-04-24
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    • 2011-09-03
    • 2021-05-28
    • 2019-05-14
    • 1970-01-01
    相关资源
    最近更新 更多