看看隐含规则目录,有几个陈述让我想知道:
默认后缀列表为:.out、.a、.ln、.o、.c、.cc、.C、.cpp、.p、.f、.F、.m、.r、.y、.l 、.ym、.lm、.s、.S、.mod、.sym、.def、.h、.info、.dvi、.tex、.texinfo、.texi、.txinfo、.w、.ch .web 、.sh、.elc、.el。下面描述的所有先决条件具有这些后缀之一的隐式规则实际上都是后缀规则。
嗯,不是吗?
$ make -p -f/dev/null | grep '%.o: %\.c$' -A2
%.o: %.c
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
Run Code Online (Sandbox Code Playgroud)
后缀.c在列表中但它被定义为模式规则?
好吧,它还定义了一个后缀规则:
make -p -f/dev/null | grep '^.c.o:' -A5
.c.o:
# Implicit rule search has not been done.
# Modification time never checked.
# File has not been updated.
# recipe to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
Run Code Online (Sandbox Code Playgroud)
但为什么?
后缀规则在模式规则之后定义。那么模式规则应该优先,对吧?
但既然行动是平等的,那还有什么意义呢?
应用列出的模式规则。后缀规则仅列出但未使用。
\n\n当您转储 Make\ 的内部数据库时,make -p -f /dev/null它会打印预定义的规则和变量。输出被分为不同的部分。例如,我的 Make (v3.81) 返回以下内容:
# GNU Make 3.81\n# Copyright (C) 2006 Free Software Foundation, Inc.\n# This is free software; see the source for copying conditions.\n# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A\n# PARTICULAR PURPOSE.\n\n# This program built for i686-pc-linux-gnu make: *** No targets. Stop.\n\n# Make data base, printed on Fri May 31 12:48:50 2013\n\n# Variables \n...\n# Directories \n...\n# Implicit Rules \n...\n# Pattern-specific variable values \n...\n# Files \n...\n# VPATH Search Paths\n....\nRun Code Online (Sandbox Code Playgroud)\n\n使用 GNU Make 管理项目和 GNU Make 手册解释了不同的部分,如下所示:
\n\n\n\n\n变量部分列出了每个变量以及描述性注释。不过,自动变量并未列出。
\n\n目录部分对于 Make 开发人员比 Make\n 用户更有用。它列出了 Make 检查的目录,包括可能存在但通常不存在的 SCCS\n 和 RCS 子目录。对于每个目录,Make 都会显示实现详细信息,例如设备编号、索引节点以及文件模式匹配的统计信息。
\n\n隐含规则部分如下。这包含 make\xe2\x80\x99s 数据库中的所有内置和\n 用户定义的模式规则。
\n\n下一节对 makefile 中定义的特定于模式的变量进行分类。回想一下,特定于模式的变量是变量定义,其范围恰好是其关联模式规则的执行时间。
\n\n随后的“文件”部分列出了与特定文件相关的所有显式规则和后缀规则。[在此上下文中的文件意味着目标]
\n\n最后一部分标记为 VPATH。它包含搜索路径并列出 VPATH 的值和所有 vpath 模式。
\n
因此应用的规则列在“隐式规则”部分中。后缀规则作为“文件”部分的一部分列出。
\n\n每个人都知道源代码是唯一真实的文档;)因此,秉承 GNU 精神,我冒险进入 Make 的源代码,试图弄清楚它正在发生什么。\n免责声明:我只浏览了大约两个小时 - 足以大致了解 Make 的架构。
\n\n初始化阶段: \nmain.c:第 1600 行(我只是删除了一些处理不同平台的#ifdef ):
\n\n/* Define the initial list of suffixes for old-style rules. */\nset_default_suffixes (); \n\n/* Define the file rules for the built-in suffix rules. These will later\n be converted into pattern rules. We used to do this in\n install_default_implicit_rules, but since that happens after reading\n makefiles, it results in the built-in pattern rules taking precedence\n over makefile-specified suffix rules, which is wrong. */\ninstall_default_suffix_rules ();\n\n/* Define some internal and special variables. */\ndefine_automatic_variables ();\n\n/* Set up the MAKEFLAGS and MFLAGS variables\n so makefiles can look at them. */\ndefine_makeflags (0, 0);\n\n/* Define the default variables. */\ndefine_default_variables ();\n\ndefault_file = enter_file (strcache_add (".DEFAULT"));\n\ndefault_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0);\n\n// I removed the block that evalutes user input entered \n// through the `--eval` switch for brevity\n[...]\n\n/* Read all the makefiles. */\nread_makefiles = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);\n\n/* Set up MAKEFLAGS and MFLAGS again, so they will be right. */\ndefine_makeflags (1, 0);\n\n/* Make each `struct dep\' point at the `struct file\' for the file\n depended on. Also do magic for special targets. */\nsnap_deps ();\n\n/* Convert old-style suffix rules to pattern rules. It is important to\n do this before installing the built-in pattern rules below, so that\n makefile-specified suffix rules take precedence over built-in pattern\n rules. */\nconvert_to_pattern ();\n\n/* Install the default implicit pattern rules.\n This used to be done before reading the makefiles.\n But in that case, built-in pattern rules were in the chain\n before user-defined ones, so they matched first. */\ninstall_default_implicit_rules ();\n\n/* Compute implicit rule limits. */\ncount_implicit_rule_limits ();\n\n/* Construct the listings of directories in VPATH lists. */\nbuild_vpath_lists ();\nRun Code Online (Sandbox Code Playgroud)\n\n-f /dev/null。构建阶段:
\n\n稍后,当 Make 尝试构建目标时,它仅搜索规则数据库。规则搜索在implicit.c 中实现。
\n\n最后我研究了开关背后的逻辑--print-database。
main.c:第 3078 行:
\n\n/* Print a bunch of information about this and that. */\n\nstatic void\nprint_data_base ()\n{\n time_t when;\n\n when = time ((time_t *) 0);\n printf (_("\\n# Make data base, printed on %s"), ctime (&when));\n\n print_variable_data_base ();\n print_dir_data_base ();\n print_rule_data_base ();\n print_file_data_base ();\n print_vpath_data_base ();\n strcache_print_stats ("#");\n\n when = time ((time_t *) 0);\n printf (_("\\n# Finished Make data base on %s\\n"), ctime (&when));\n}\nRun Code Online (Sandbox Code Playgroud)\n\nprint_rule_data_base() 函数只是简单地打印所有“活动”规则。所有现有后缀规则之前也已转换为模式规则。
\n\nprint_file_data_base() 函数列出所有目标。后缀规则仍然在那里。实际上,似乎没有从数据库中删除目标的功能。然而,根据我收集的信息,后缀目标在其他情况下未被使用。
\n