Generate include files for the Makefile by the sam

2019-07-19 03:42发布

问题:

In my program, I have a somewhat complicated build process. Currently, in one directory I use include in Makefile.am with a file, that does not exist but has to be build on its own. The reason is that this include file is quite long. Further in the real program it is not just only one file but several and the generation process for this file can change from time to time.

The Makefile.am looks something like this

noinst_LIBRARIES = libtest.a
nodist_libtest_a_SOURCES = file.c
CLEANFILES = file.c Make_file.mk 

$(builddir)/Make_test.mk: $(srcdir)/Perl/generate_mk_files.pl
      perl $(srcdir)/Perl/generate_mk_files.pl file

include $(builddir)/Make_file.mk

After creation of Make_file.mk it looks something like

$(builddir)/file.c: $(srcdir)/file.template $(srcdir)/Perl/generate_c.pl
      perl $(srcdir)/Perl/generate_c.pl $(srcdir)/file.template

Automake works and the final build process as well. The output to make is something like (I have shorted it somewhat):

Makefile:721: Make_file.mk: Datei oder Verzeichnis nicht gefunden (file not found)
perl ../../../../src/components/test/Perl/generate_mk_files.pl test
perl ../../../../src/components/test/Perl/generate_c.pl ../../../../src/components/test/file.template

Therefore, make first complains that the include file is not found, then creates it and then also follows the rules of the included file.

Although I am happy that it works I wonder why. First, I thought that make loads the Makefile. During this step, Make_file.mk does not exists. Therefore it seems the Makefile is loaded more than once.

Further, the manual of Automake for include states:

Note that these fragments are read and interpreted by automake, not by make.

Which is not what I see, since the included fragment does not exist during the execution of Automake.

My questions basically are:

  • Why does it work?
  • Is this the correct way to do this or should I use another approach, e.g. starting new instances of make within Makefile.

回答1:

I don't really know Automake, but, from the GNU make manual :

If an included makefile cannot be found in any of these directories {standard includes directories} , a warning message is generated, but it is not an immediately fatal error; processing of the makefile containing the include continues. Once it has finished reading makefiles, make will try to remake any that are out of date or don’t exist. See How Makefiles Are Remade. Only after it has tried to find a way to remake a makefile and failed, will make diagnose the missing makefile as a fatal error.

If you want make to simply ignore a makefile which does not exist or cannot be remade, with no error message, use the -include directive instead of include, like this:

-include filenames…

This acts like include in every way except that there is no error (not even a warning) if any of the filenames (or any prerequisites of any of the filenames) do not exist or cannot be remade.

So basically, make cannot execute the recipe for remaking the include file before he has finished to parse the main Makefile. So it raises a warning, continue to read the Makefile, find the rule for remaking the included file, remake it, and then restart itself (that is explained in details in the How Makefiles Are Remade section).



回答2:

Going back to the manual, it states there's two forms for automakes include mechanism:

include $(srcdir)/file

and

include $(top_srcdir)/file

neither of which match your include. So I'd imagine the include is actually run by the underlying make whatever that might be (e.g. GNU Make, though of course other make programs have this functionality as well).

Now for the questions:

Why does it work?

As explained in another answer, GNU Make will attempt to make a missing included makefile, before failing.

Is this the correct way to do this or should I use another approach, e.g. starting new instances of make within Makefile

Generating makefiles is one of the tasks autotools do, either through autoconf or automake. Going through multiple stages of "making makefiles" seems prone to error (and hard to maintain). Recursive make has similar problems.

The reason is that this include file is quite long.

automake include statements will happily paste together a large makefile out of smaller components.

Further in the real program it is not just only one file but several and the generation process for this file can change from time to time.

It's hard to recommend what to suggest to do in autotools based on how the "changes" are determined. Since it seems you're also using libtool adding/removing sources to libs (or entire libs) there can be effected by conditionals, variables, etc.