From: Paul Smith Date: Fri, 25 Aug 2023 15:10:34 +0000 (-0400) Subject: make.texi: Add an appendix with troubleshooting tips X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9af3e60f4dd102541b3c457037c96a167ac390b1;p=thirdparty%2Fmake.git make.texi: Add an appendix with troubleshooting tips --- diff --git a/doc/make.texi b/doc/make.texi index d3003a8f..dc10fecf 100644 --- a/doc/make.texi +++ b/doc/make.texi @@ -108,6 +108,7 @@ Cover art by Etienne Suvasa. GNU programs. * Quick Reference:: A quick reference for experienced users. * Error Messages:: A list of common errors generated by @code{make}. +* Troubleshooting:: Advice on finding problems. * Complex Makefile:: A real example of a straightforward, but nontrivial, makefile. @@ -381,6 +382,16 @@ Sharing Job Slots with GNU @code{make} * POSIX Jobserver:: Using the jobserver on POSIX systems. * Windows Jobserver:: Using the jobserver on Windows systems. +Troubleshooting Make and Makefiles + +* Parse Error:: Syntax errors when parsing makefiles. +* Command Failure:: Recipe commands exit with error codes. +* Wrong Rule:: @code{make} chooses the wrong rule. +* No Rule Found:: No rule was found to build a target. +* Extra Rebuilds:: Targets are rebuilt unnecessarily. +* Missing Rebuilds:: Out-of-date targets are not rebuilt. +* Troubleshooting Strategies:: Strategies used for troubleshooting issues. + @end detailmenu @end menu @@ -465,6 +476,9 @@ others have. For a quick summary, see @ref{Options Summary}, @ref{Quick Reference}, and @ref{Special Targets}. +If you have a makefile already and it is not working as you expect, +@pxref{Troubleshooting, ,Troubleshooting Make and Makefiles}. + @node Bugs @section Problems and Bugs @cindex reporting bugs @@ -13612,6 +13626,381 @@ prerequisite can be suffix rule and this warning will be removed. @end table +@node Troubleshooting +@appendix Troubleshooting Make and Makefiles + +Troubleshooting @code{make} and makefiles can be tricky. There are two +reasons: first, makefiles are not procedural programs and many users are used +to procedural languages and scripts. Second, makefiles consist of two +different syntaxes in one file: makefile syntax, that @code{make} reads, and +shell syntax, which is sent to a shell program for parsing and execution. + +If you have problems with GNU Make, first consider the type of problem you are +having. Problems will generally be in one of these categories: + +@itemize @bullet +@item +A syntax or other error was reported when @code{make} attempted to parse your +makefiles. + +@item +A command that @code{make} invoked failed (exited with a non-0 exit code). + +@item +The command that @code{make} invoked was not the one you expected. + +@item +@code{make} was not able to find a rule to build a target. + +@item +@code{make} rebuilds a target that you didn't think was out of date. + +@item +Or, @code{make} did not rebuild a target that you expected it to build. +@end itemize + +The strategies for troubleshooting differ for different types of problems. +For issues related to how makefiles are parsed, strategies include: + +@itemize @bullet +@item +Using the @samp{-p} option to show the makefile database, after evaluation +(@pxref{Options Summary, ,Summary of Options}). + +@item +Using the @code{info} or @code{warning} functions to understand how elements +of the makefile are expanded (@pxref{Make Control Functions, ,Functions That +Control Make}). +@end itemize + +For issues related to how rules are applied, strategies include: + +@itemize @bullet +@item +Using the @samp{-n} or @samp{--trace} options to show the commands that +@code{make} ran, and to explain which rules @code{make} invokes and why +(@pxref{Options Summary, ,Summary of Options}). + +@item +Using the @samp{--debug=v,i} or full @samp{-d} options to show how @code{make} +is determining which recipes should be used, or why targets do not need to be +rebuilt (@pxref{Options Summary, ,Summary of Options}). +@end itemize + +@menu +* Parse Error:: Syntax errors when parsing makefiles. +* Command Failure:: Recipe commands exit with error codes. +* Wrong Rule:: @code{make} chooses the wrong rule. +* No Rule Found:: No rule was found to build a target. +* Extra Rebuilds:: Targets are rebuilt unnecessarily. +* Missing Rebuilds:: Out-of-date targets are not rebuilt. +* Troubleshooting Strategies:: Strategies used for troubleshooting issues. +@end menu + +@node Parse Error +@appendixsec Errors When Parsing Makefiles + +This type of error is the simplest to resolve. The error output you will see +will have a format like this: + +@example +Makefile:10: *** missing separator. Stop. +@end example + +This message gives you all the information you need to address the error: it +gives the name of the makefile (here @samp{Makefile}) and the line number +(here @samp{10}) in that makefile where GNU Make's parser failed. Following +that is a description of the error. Further explanations of these error +messages can be found in @ref{Error Messages, ,Errors Generated by Make}. + +@node Command Failure +@appendixsec Errors Reported by Commands + +If GNU Make parses the makefiles correctly and runs a command to rebuild a +target, it expects that command to exit with an error code of @samp{0} (for +success). Any other exit code will be reported by @code{make} as a failure +and will generate an error message with this form: + +@example +make: *** [Makefile:10: target] Error 2 +@end example + +All the information you need to find that command are given: the name of the +makefile (here @samp{Makefile}) and line number (here @samp{10}) of the +command make invoked, the target (here @samp{target}) that make was trying to +build, and finally the exit code of the command (here @samp{2}). + +The precise meaning of the error code is different for different commands: you +must consult the documentation of the command that failed to interpret it. +However there are some reasons for error codes: + +@table @samp +@item 2 +If the shell fails to parse your command (invalid shell syntax) it will exit +with a code of @samp{2}. On Windows this can also mean that the command was +not found. + +@item 127 +If the command you wanted to run was not found, the shell will exit with a +code of @samp{127}. +@end table + +To troubleshoot these errors (@pxref{Troubleshooting Strategies, ,Strategies +for Troubleshooting}), use the @samp{-n} or @samp{--trace} options so you can +see the complete command line being invoked. + +Than, examine the output of the command that @code{make} invoked to determine +what went wrong and why: this output will appear @emph{before} the above error +message. The error may be due to an incorrect command line in which case the +error is in the way your command was written in the makefile, but it's far +more likely to be a problem with something outside of the makefile (for +example, a syntax error in the code you are trying to compile). + +@node Wrong Rule +@appendixsec Choosing the Wrong Rule + +If @code{make} seems to be invoking a different command than the one you +intended, it could be that the wrong rule is being chosen. + +To troubleshoot these errors (@pxref{Troubleshooting Strategies, ,Strategies +for Troubleshooting}), add the @samp{--trace} option to the @code{make} +command line. This shows the rule that was chosen. + +You can also use the @samp{--debug=v,i} or the full @samp{-d} option to +determine how @code{make} decided to use that rule. + +@node No Rule Found +@appendixsec No Rule to Build A Target + +If @code{make} cannot locate a rule to build a target that you requested, +either via the command line or as a prerequisite of another target, it shows +an error such as: + +@example +make: *** No rule to make target 'aprogram'. Stop. +@end example + +If the makefile doesn't provide a rule for this target, you can add one. If +there is a rule which you intended @code{make} to use to build this target and +it wasn't used, the most common reasons for this are: + +@itemize @bullet +@item +The target was misspelled. You should consider following the @dfn{DRY} +principle (Don't Repeat Yourself) by assigning file names (targets and +prerequisites) to makefile variables and using those variables rather than +retyping the file names. + +@item +The target is in a different directory. @code{make} considers @samp{target} +and @samp{dir/target} (for example) to be different targets. If you are using +rules that create files outside of the current working directory, be sure you +correctly prefix them with their directories everywhere that they appear in +the makefile. + +@item +A pattern rule didn't match because one of its prerequisites cannot be built. +Pattern rules will only be used when @strong{all} prerequisites can be +satisfied: either they exist already or @code{make} can find a way to build +them. If any prerequisite cannot be created, then the pattern does not match +and @code{make} will continue looking for another matching pattern. If no +matching pattern can be found, then @code{make} will fail. +@end itemize + +To troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies +for Troubleshooting}), run @code{make} with the @samp{--debug=v,i} option, or +the full @samp{-d} option, and examine the detailed output. + +If the definition of the rule in your makefile is complicated, you can use the +@samp{-p} option to ask make to print its internal database of rules to ensure +they are correct, or as a last resort add invocations of the @code{info} or +@code{warning} functions to show what steps @code{make} is taking during +evaluation. + +@node Extra Rebuilds +@appendixsec Unwanted Rebuilding of Targets + +If @code{make} is rebuilding a target which you feel is already up to date and +doesn't need to be rebuilt, there can be a number of reasons: + +@itemize @bullet +@item +The recipe does not update the target. A makefile rule is a promise to +@code{make} that if it invokes the recipe, the target will be updated. The +file which @code{make} expects to be updated is placed in the @samp{$@@} +variable. If the recipe doesn't update this file, and @emph{exactly} this +file, then the next time @code{make} is invoked it will try to re-build that +target again. + +@item +A prerequisite is marked as phony (@pxref{Special Targets, ,Special Built-in +Target Names}). All phony targets are always considered out of date, and so +any targets depending on them are also out of date. + +@item +A directory is used as a prerequisite. Directories are not treated specially +by @code{make}: if their modification time is newer than the target then the +target is considered out of date and rebuilt. Since directory modification +times are changed whenever a file is created, deleted, or renamed in that +directory, it means targets depending on the directory will be considered out +of date whenever a file is created, deleted, or renamed in that directory. + +@item +Something is deleting the target file. Of course if a file does not exist it +is always considered out of date (see the first item above). If something in +your environment, either inside the @samp{makefile} or outside if it, is +deleting the target file then @code{make} will always rebuild it. + +@item +The target is created with a ``too-old'' modification time. If the recipe +creates the target with a modification time in the past, then it may still be +out of date with respect to its prerequisites. This could happen if, for +example, you are extracting files from an archive or copying them from another +location and the tool used to do the extraction or copying preserves the +original file's modification time. +@end itemize + +To troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies +for Troubleshooting}), use the @samp{--trace} option to understand why +@code{make} decides to build a target and see the full command used. + +@node Missing Rebuilds +@appendixsec Out-of-Date Targets Not Rebuilt + +The opposite of the previous problem is @code{make} not rebuilding targets +that you think should be rebuilt. Some reasons for this might be: + +@itemize @bullet +@item +The target is not being considered. Unless the command line specifies +otherwise, @code{make} will only consider the first target in the makefile and +its prerequisites. If the target you expected to be built is not one of +these, then @code{make} won't build it. + +@item +A different file is being built instead. Be sure that your target is the file +you want to be built (including any directory prefix!) and that the recipe +will create the file listed as @samp{$@@}. Also consider the directory that +@code{make} is running in and whether relative pathnames are the ones you +expect. +@end itemize + +To troubleshoot these issues (@pxref{Troubleshooting Strategies, ,Strategies +for Troubleshooting}), use the @samp{-n} or @samp{--trace} option to see what +command is being invoked. + +You can also use the @samp{--debug=v,i} option or the full @samp{-d} option to +obtain a complete description of everything @code{make} considered and why it +decided to build or not build every target. + +@node Troubleshooting Strategies +@appendixsec Strategies for Troubleshooting + +The strategies for troubleshooting differ for different types of problems. + +@subheading Show the makefile database + +Use the @samp{-p} option to show the makefile database, after evaluation +(@pxref{Options Summary, ,Summary of Options}). This allows you to see how +@code{make} has evaluated the variables and recipes in your makefile. + +The @samp{-p} option asks GNU Make to print its internal database of rules, +after all makefiles have been parsed. You might see output such as: + +@example +program: prereq.o +# Implicit rule search has not been done. +# Modification time never checked. +# File has not been updated. +# recipe to execute (from 'Makefile', line 10): + $(CC) -o $@@ $^ $(LDFLAGS) $(LDLIBS) +@end example + +Here we can see the target (here @samp{program}) and prerequisites (here +@samp{prereq.o}) after variable expansion, as well as the location of the +definition of the recipe for this rule (here, in @samp{Makefile} at line +@samp{10}). + +@subheading Add @code{info} or @code{warning} calls + +The @code{info} or @code{warning} function can help to understand how elements +of the makefile are expanded (@pxref{Make Control Functions, ,Functions That +Control Make}). + +Although their use requires modifying the makefile, these functions are a +powerful tool for troubleshooting complex makefiles such as those using +@code{eval} and @code{call} functions to dynamically generate rules. For +example if your makefile contains: + +@example +$(foreach T,$(TARGET),$(eval $(call makerule,$T,$($T_PREREQ)))) +@end example + +@noindent +then duplicating this line and replacing @code{eval} with @code{info} will +show exactly what content @code{make} will be evaluating: + +@example +$(foreach T,$(TARGET),$(info $(call makerule,$T,$($T_PREREQ)))) +@end example + +The @code{warning} function provides the same output as @code{info}, except +that each output line is prefixed with the filename and line number where the +@code{warning} function is expanded, and that the output goes to the standard +error file descriptor and not to standard output. + +@subheading Use the @samp{--trace} or @samp{-n} option + +The @samp{-n} option will show you which commands would be invoked to bring +targets up to date, without actually invoking them. Commands are displayed +even if the @samp{@@} prefix or the @code{.SILENT} target was specified +(@pxref{Options Summary, ,Summary of Options}). + +Use the @samp{--trace} option on the @code{make} command line to explain which +rules @code{make} invokes and why (@pxref{Options Summary, ,Summary of +Options}). This option also overrides @samp{@@} recipe prefixes and the +@code{.SILENT} special target and shows the expanded command line. + +Adding this will result in output like this for each target which is rebuilt: + +@example +Makefile:10: update target 'program' due to: target does not exist +@end example + +@noindent +or: + +@example +Makefile:10: update target 'program' due to: prereq.o +@end example + +This shows the filename of the makefile (here @samp{Makefile}) and line number +(here @samp{10}), along with the name of the target (here @samp{program}) and +the reason why it was rebuilt: in the first example because the target does +not exist, and in the second example because there were prerequisites (here, +@samp{prereq.o}) that were newer than the target. All newer prerequisites +would be listed here. + +After this information, the expanded command line make invoked will be shown, +just as it is passed to the shell. You should examine it carefully to +determine whether it's correct, and compare it to the pre-expansion recipe in +the makefile to see what aspect of the recipe might be incorrect. + +@subheading Use the @samp{--debug=v,i} or @samp{-d} option + +Use the @samp{--debug=v,i}, or the full @samp{-d}, options to show how +@code{make} is determining which recipes should be used, or why targets do not +need to be rebuilt (@pxref{Options Summary, ,Summary of Options}). + +The amount of output generated by these options can be daunting, but +redirecting the output to a file then searching it for the target you are +concerned with will show you exactly what steps GNU Make took when considering +this target, and why it decided to build, or not build, that target. + +If the issue is that @code{make} decides @emph{not} to rebuild the target when +you think it should, this may be your only recourse since @samp{--trace} only +shows why targets are considered out of date. + @node Complex Makefile @appendix Complex Makefile Example