Gnu make : using content of file as recipe - makefile

Consider having a makefile, which can generate some files using generating lines listed in a file. For example file 001 using first line, 002 using second line, etc.
This file can be changed (it has it's own dependences, but this doesn't metter).
If some lines in this file changed, appropriate files should be remade. But other files shouldn't.
The solution I found is this one: for every file there is flag-file which content is generating line it was made last time. After remaking file with generating lines, i check all this file, and remove them if line changed. So files which have dependences on removed files will be remade, and other files won't. But this works too slow if use msys-make.
Can you suggest any other solution, which doesn't need many extra calls to file system and executable runs.

If I understand your description correctly, what you're describing is a Makefile which depends on another file that is functionally a Makefile but for unknown reasons uses a different format.
Turn that file into Makefile format and include it into the original Makefile. (If you're using GNU Make.)

We have what may be similar to your problem. We have xml files, say foobar.xml which contains the dependencies for foobar.out
<files>
<file>a</file>
<file>b</file>
<file>c</file>
</files>
We decided to adhere to this simple layout, so we don't need to parse xml. We use makepp (because we got fed up with gmake not noticing dependencies like changed commands). This gives us the builtin &sed command (the expression is actually Perl programming, but as you see, you don't need to get into it much). Here's what we do with three simple substitutions for the three kinds of lines:
%.d: %.xml
&sed 's!<files>!$(stem).out: \\! || s!<file>(.+)</file>!$$1 \\! || s!</files>!!' \
$(input) -o $(output)
include foobar.d
This produces foobar.d which we then include:
foobar.out: \
a \
b \
c \
Stackoverflow is swallowing the last empty line here, which avoids having to worry about the trailing backslash.

Related

makefile for metapost: how to compile file-N.pdf

I want to let makefile manage the compilation of figures with metapost.
The source file is file.mp. This generates .mps files file.1, file.2 etc. that are then converted to file-1.pdf, file-2.pdf etc.
Here are my rules:
export TEX = latex
%: %.1
mptopdf $*
%.1: %.mp
mpost $*
So that when I run make file it creates all the files.
However, I am not satisfied with this solution. Namely, I'd like to be able to let only one of the files be compiled (say file-2.pdf) by entering make file-2.
Unfortunately, I don't know how to write the rule for this, although I suspect it might be trivial.
I thought the problem could be solved by extracting the number from the file name given in the command line (i.e. extract 2 from file-2) but it is not clear to me how to do it either.

The difference between .mk file and Makefile

I've just begun to study Porting Android. And I come across a new type of file which is .mk file. It's is an extension of Makefile but I don't know what it is different from a Makefile ? So, can somebody help you clarify them. Thanks very much !
A make file can have any name. The -f option of make is used to specify which file to use:
make -f foobar
You can even use -f several times:
make -f foo -f bar
In which case make processes the files in order (or, equivalently, concatenates the files and processes the result).
makefile and Makefile are special names because if make is called without the -f option it automatically searches for them, in this order, and use the first it finds. Note that GNU make also considers GNUmakefile, and prefers it over makefile and Makefile. Other make implementations can have other default names.
The .mk extension is a more or less standard extension for make files that have other names than the defaults. It is a reasonable extension if you want humans to quickly understand what these files are: convert.mk is more informative than foobar. Some editors use this extension to identify the file type and apply syntax coloring. They usually apply the same syntax coloring to makefile and Makefile.

Finding dependencies by grep in Make

I'm working on a rather large project in pure C, and for various reasons we are not using CMake.
We have a good system which uses various shell commands to require very little maintanence. It will automatically find new headers and C files and add the headers to the dependencies and will compile the C files and include them in the output. However, we've gotten to the point where any changes we make to the header files becomes a problem because it requires a recompilation of the entire project, rather than just the C files that include it directly or indirectly.
I've worked on a system to ensure that the only header files which are added as dependencies are ones which are required by the C file itself (recursively up the tree).
I had thought I would be able to solve this myself, but it seems that make has rather inconsistent rules for expansion of variables.
The solution I came up with was to try to use ag and get all the includes out of the file. This works as intended, and I pipe it into tr so that I can ensure that no newlines are added, thereby messing up make. The issue that I'm having though is in determining which file to search in. This is the recipe that it's using for the section in question:
$(GAMEOBJDIR)/%.o : $(GAMEDIR)/%.c $(shell ag -o '(?<=(^#include "))(.*?)(?=("$$))' $(GAMEDIR)/%.c | tr '\n' ' ')
$(CC) $(CFLAGS) $(if $(RELEASE),$(RELFLAGS),$(DBFLAGS)) -c -o $# $<
The problem is that $(GAMEDIR)/%.c is expanding to src/game/%.c and not src/game/<filename>.c. I'm unsure how to fix this issue based on the expansion rules of make.
Once I can figure this out I'll be able to make sure this walks up the chain of header files too, but until I can get this figured out I have no reason to work on that.
Make's rules for expansion are completely consistent... but sometimes they aren't what people want. That's not the same thing :)
Rules for expansion are explained in the manual. In your case you're working with a prerequisite list which means the variables are expanded as the makefile is parsed. That includes the shell command and all other variables. Because you are working with a pattern rule, it means that at the time the makefile is parsed it doesn't match any particular file, it's just defining the pattern rule itself. So, % can't be expanded here. It will be expanded later, when make starts walking the dependency graph and trying to locate ways to build targets.
In general your method cannot work efficiently. You could defer the expansion of these parts of the prerequisites list using Secondary Expansion. However, that means every time make wants to TRY to use this pattern it will run these commands--that will just be slow.
Have you considered using a more standard way to manage detecting prerequisites? Try reading this description for example to see if it would work for you.

Sed script behaves differently on similar platforms

I am building a project from Cygwin. Among other things, the GCC compiler creates dependency files, and then a sed script is called to "fix" the dependency files.
After the script finishes, on one system the dependency files contain, as example, this:
src/man/man.o: \[LF]
../include/debug.h \[LF]
../include/sys.h ../include/types.h \[LF]
and on the another system line endings are changed by the script to:
src/man/man.o: /[CR][LF]
../include/debug.h /[CR][LF]
../include/sys.h ../include/types.h /[CR][LF]
The second case with forward slashes and [CR][LF] breaks the build.
Why would the script behave differently?
Here is the critical sed line:
#sed -i -e's/\\\(.\)/\/\1/g' $(#:.o=.d) ;\
Could anyone decipher why is it system dependent?
sed -i -e's/\\\(.\)/\/\1/g'
Find a backslash (\\), followed by something (.) (i.e., not at end-of-line), and replace it with forward slash, plus whatever it was that followed (\1)...
$(#:.o=.d)
...in dependency files...? (Haven't seen this before, but it looks like "the corresponding .d for each .o.)
The rest looks unrelated to your problem.
I guess this is part of a crude way to turn Windows paths into Unix paths... and I guess the <CR> in there (no idea where that came from) makes this fail to operate correctly.
What happens if you add a dos2unix before that to get rid of the <CR>?
define DEPEND_HACK
#dos2unix $(#:.o=.d) ;\
sed -i -e's/\\\(.\)/\/\1/g' $(#:.o=.d) ;\
....

in makefile, what does a sole dash as the target of a rule mean?

I see a file .missing-syscalls.d which contains
-: /home/ckim/MVP/snake_linux_3.3.mvpe/include/linux/kconfig.h \
include/generated/autoconf.h \
/home/ckim/MVP/snake_linux_3.3.mvpe/arch/sparc/include/asm/types.h \
include/asm-generic/int-ll64.h \
/home/ckim/MVP/snake_linux_3.3.mvpe/arch/sparc/include/asm/bitsperlong.h \
include/asm-generic/bitsperlong.h \
/home/ckim/MVP/snake_linux_3.3.mvpe/arch/sparc/include/asm/unistd.h
I know .d file is only for showing dependancy. But what is '-' as the target?
Hyphen prior to commands in makefiles is used to suppress errors and continue instead of failing like this:
clean:
-rm -f *.o
The same way goes for include syntax in makefiles to suppress the error messages that would otherwise appear if the file isn't available like this:
-include $(SRC:%.c=%.d)
I would assume the .missing-syscalls.d file is used the same way, ignoring non-existing header files it attempts to include.
Either that's an error (from some automated process gone wrong) and that's a literal target of - which defines some extra prereqs (for a target that I can't imagine is ever likely to actually run).
Or that's an attempt to ensure that those files aren't considered as intermediate files by make in case some chain of rules would cause it to consider them as such.
See http://www.gnu.org/software/make/manual/make.html#Chained-Rules for reference.
Ordinarily, a file cannot be intermediate if it is mentioned in the
makefile as a target or prerequisite. However, you can explicitly mark
a file as intermediate by listing it as a prerequisite of the special
target .INTERMEDIATE. This takes effect even if the file is mentioned
explicitly in some other way.

Resources