Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GNU make define implicit pattern and implicit suffix rules?

Looking at the Catalogue of Implicit Rules several statements make me wonder:

The default suffix list is: .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. All of the implicit rules described below whose prerequisites have one of these suffixes are actually suffix rules.

Hm, not really?

$ make -p -f/dev/null | grep '%.o: %\.c$' -A2
%.o: %.c
#  recipe to execute (built-in):
    $(COMPILE.c) $(OUTPUT_OPTION) $<

Suffix .c is in the list but it is defined as pattern rule?

Ok, it is also defines a suffix rule:

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) $<

But why?

The suffix rule is defined after the pattern rule. The pattern rule should take precedence then, right?

But since the actions are equal what is the point?

like image 906
maxschlepzig Avatar asked May 30 '13 17:05

maxschlepzig


People also ask

What is implicit rules in makefile?

Implicit rules tell make how to use customary techniques so that you do not have to specify them in detail when you want to use them. For example, there is an implicit rule for C compilation. File names determine which implicit rules are run.

What is a suffix rule makefile?

Suffix rules are the old-fashioned way of defining implicit rules for make . Suffix rules are obsolete because pattern rules are more general and clearer. They are supported in GNU make for compatibility with old makefiles. They come in two kinds: double-suffix and single-suffix.

What is a suffix rule in computer science?

In computer system file names, a suffix is a convention for having one or more characters appended to a file name (usually separated from the file name with a dot) so that it can be distinguished from other files or grouped together with similar types of files.

What is a makefile rule?

A rule appears in the makefile and says when and how to remake certain files, called the rule's targets (most often only one per rule). It lists the other files that are the prerequisites of the target, and the recipe to use to create or update the target.


2 Answers

Short answer:

The listed pattern rules are applied. The suffix rules are only listed but not used.

Long answer:

When you dump Make's internal database using make -p -f /dev/null it prints predefined rules and variables. The output is structured into different sections. For example my Make (v3.81) returns the following:

# GNU Make 3.81
# Copyright (C) 2006  Free Software Foundation, Inc.
# This is free software; see the source for copying conditions.
# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.

# This program built for i686-pc-linux-gnu make: *** No targets.  Stop.

# Make data base, printed on Fri May 31 12:48:50 2013

# Variables 
...
# Directories 
...
# Implicit Rules 
...
# Pattern-specific variable values 
...
# Files 
...
# VPATH Search Paths
....

Managing Projects with GNU Make and the GNU Make manual explains the different sections as follows:

The Variables section lists each variable along with a descriptive comment. Automatic variables aren't listed, though.

The Directories section is more useful to Make developers than to Make users. It lists the directories being examined by Make, including SCCS and RCS subdirectories that might exist, but usually do not. For each directory, Make displays implementation details, such as the device number, inode, and statistics on file pattern matches.

The Implicit Rules section follows. This contains all the built-in and user-defined pattern rules in make’s database.

The next section catalogs the pattern-specific variables defined in the makefile. Recall that pattern-specific variables are variable definitions whose scope is precisely the execution time of their associated pattern rule.

The Files section follows and lists all the explicit and suffix rules that relate to specific file. [A file in this context means a target]

The last section is labeled VPATH. It contains search paths and lists the value of VPATH and all the vpath patterns.

So the applied rules are listed in the 'Implicit Rules' section. The suffix rules are listed as part of the 'Files' section.

Really long answer:

Everybody knows that the source is the only true documentation ;) So, true to the GNU spirit, I ventured into Make's sources trying to figure out what it's going on. Disclaimer: I've only poked around for about two hours - just long enough to get a general overview of Make's architecture.

Initialization phase: main.c : line 1600 (I merely removed a couple of #ifdefs that deal with different platforms):

/* Define the initial list of suffixes for old-style rules.  */
set_default_suffixes ();  

/* Define the file rules for the built-in suffix rules.  These will later
 be converted into pattern rules.  We used to do this in
 install_default_implicit_rules, but since that happens after reading
 makefiles, it results in the built-in pattern rules taking precedence
 over makefile-specified suffix rules, which is wrong.  */
install_default_suffix_rules ();

/* Define some internal and special variables.  */
define_automatic_variables ();

/* Set up the MAKEFLAGS and MFLAGS variables
 so makefiles can look at them.  */
define_makeflags (0, 0);

/* Define the default variables.  */
define_default_variables ();

default_file = enter_file (strcache_add (".DEFAULT"));

default_goal_var = define_variable_cname (".DEFAULT_GOAL", "", o_file, 0);

// I removed the block that evalutes user input entered 
// through the `--eval` switch for brevity
[...]

/* Read all the makefiles.  */
read_makefiles = read_all_makefiles (makefiles == 0 ? 0 : makefiles->list);

/* Set up MAKEFLAGS and MFLAGS again, so they will be right.  */
define_makeflags (1, 0);

/* Make each `struct dep' point at the `struct file' for the file
 depended on.  Also do magic for special targets.  */
snap_deps ();

/* Convert old-style suffix rules to pattern rules.  It is important to
 do this before installing the built-in pattern rules below, so that
 makefile-specified suffix rules take precedence over built-in pattern
 rules.  */
convert_to_pattern ();

/* Install the default implicit pattern rules.
 This used to be done before reading the makefiles.
 But in that case, built-in pattern rules were in the chain
 before user-defined ones, so they matched first.  */
install_default_implicit_rules ();

/* Compute implicit rule limits.  */
count_implicit_rule_limits ();

/* Construct the listings of directories in VPATH lists.  */
build_vpath_lists ();
  1. The function set_default_suffixes() only defines the .SUFFIXES variable, nothing more.
  2. Next the default suffix rules are defined via the install_default_suffix_rules() function. It adds the built-in suffix rules as targets.
  3. I'm gonna skip over the next two function an jump right to define_default_variables(), which is also pretty self explanatory. It defines ARCH, AR, CC, CXX, etc. Basically Make's default environment is now setup.
  4. After that the .DEFAULT and .DEFAULT_GOAL targets are defined. They're documented in Special-Targets and Special-Variables, respectively.
  5. Then the Makefiles are evaluated by read_all_makefiles(). Make's evaluation can be tricky. However, the basic idea is simple: Loop over lines in the file. The strategy is to accumulate target names in FILENAMES, dependencies in DEPS and commands in COMMANDS. These are used to define a rule when the start of the next rule (or eof) is encountered. In our case, this step can be ignored because we invoked Make with -f /dev/null.
  6. Then snap_deps() associates target with it's dependencies. They're stored as linked list of dep structs (defined in dep.h).
  7. Now comes the interesting part. Convert_to_pattern() goes over the suffixes defined in the .SUFFIXES list, converts the to equivalent pattern rules and appends them to the chain of exiting pattern rules. This is exactly what as documented in the section you quoted. Since all user defined rules have already been included in step 5, they're given precedence of the converted built-in suffix rules.

Build phase:

Later, when Make tries to build a target, it searches the rules database only. Rule searching is implemented in implicit.c .

Why do rules appear double in print-database output?

Lastly I looked at the logic behind the --print-database switch.

main.c : line 3078:

/* Print a bunch of information about this and that.  */

static void
print_data_base ()
{
  time_t when;

  when = time ((time_t *) 0);
  printf (_("\n# Make data base, printed on %s"), ctime (&when));

  print_variable_data_base ();
  print_dir_data_base ();
  print_rule_data_base ();
  print_file_data_base ();
  print_vpath_data_base ();
  strcache_print_stats ("#");

  when = time ((time_t *) 0);
  printf (_("\n# Finished Make data base on %s\n"), ctime (&when));
}

The print_rule_data_base() function is simply pretty printing all "active" rules. All existing suffix rules have previously been converted to pattern rules as well.

The print_file_data_base() function is listing all targets. The suffix rules are still in there. Actually, there doesn't seem to be a function to remove targets from the database. However, from what I've gleaned the suffix-targets are otherwise unused.

like image 141
djf Avatar answered Oct 03 '22 19:10

djf


The very short answer is: the suffix rules are defined because POSIX make requires them to be built-in. See the section named "Default Rules". The pattern rules are (non-POSIX) GNU value-add.

like image 25
Jens Avatar answered Oct 03 '22 20:10

Jens