GNU Make only executes 10 rules - makefile

I have a makefile that shall convert some files into PDFs. Right now the makefile looks like this:
PDFS = file_A.pdf file_B.pdf <snip> file_K.pdf
all : convert
file_%.pdf:
$(CONVERTER_COMMAND) $< -o $#
file_A.pdf : file1.ext
file_B.pdf : file2.ext
<snip>
file_K.pdf : file11.ext
convert : $(PDFS)
.PHONY : convert
The above is the general structure (unfortunately I can't show the actual file).
Running make convert works like a charm for the first 10 files, i.e. it generates file_A.pdf up until file_J.pdf. The last one however, file_K.pdf, is never generated. If I move the rule for it to the top of the list it gets generated, but then the now last one in the list no longer gets generated.
If I do make file_K.pdf make just state the file is up to date, even though it does not yet exist.
Any ideas? Or any alternative ideas on how to solve similar problems?

Is there a stray TAB character on the line after the last prerequisite statement (after file_K.pdf : file11.ext in the list above)?
You should try running make -d and see what it has to say about the targets that it doesn't build.

Related

Makefile:1: *** missing separator. Stop error when using Make with a config file with no tabs or spaces

I have seen this question and has read its many answers. I understand that this problem usually (always??) appears because of a mistake in using tabs vs spaces in Makefiles. So far that is the general case.
In my case, I have found the error in the title but not when doing make with a Makefile I suspect.
I do:
make a_configuration_file
and I get
Makefile:1: *** missing separator. Stop.
I suppose this "1" means that the error is occurring in the first line of the file, right?
This a_configuration_file is actually a generated file and the first lines are copied here :
#
# Automatically generated file; DO NOT EDIT.
# Ambarella SDK Configuration
#
CONFIG_THREADX=y
CONFIG_BOOT_CORE_SRTOS=0
So my questions for my particular case are:
The "1" refers to the comment line "#"? or the CONFIG_THREADX line?
This configuration file is not using Tabs. So what could be the problem?
EDIT:
Robert tells me that the problem could be the end-of-line. I checked with cat -A a_configuration_file and it seems there are no \r characters (I ve had problems with this before so I learned how to check for end-of-line chars)
Wander Nauta tells me the problem is in the Makefile. Which Makefile should I check? Right now there is a Makefile in the directory from where I call make and it is like this
build/Makefile
no tabs or spaces
I also did cat -A Makefile and I got
build/Makefileroot#themachine.....
If you are wondering what is that, is just that it seems that the Makefile does not have an end of the line at the end, so the cat command prints the contents and the rest (root#themachine...) is just the normal line in the command line
EDIT2:
I think I am close to finding the error.
Originally the "Makefile" was a link as in
ls ./ -l
lrwxrwxrwx 1 1133 543 13 Mar 18 Makefile -> build/Makefile
However now it is just a plain text file
ls ./ -l
-rw------- 1 11250 10513 14 Jul 6 Makefile
Somehow in the linux-windows-linux transference the link condition got lost
In my case, I have found the error in the title but not when doing make with a Makefile I suspect.
The error in the title specifies the name of the file in which the error is encountered: Makefile. Thus, your suspicion about "not when doing so with a Makefile" is unfounded. Although it is possible to run make without a makefile, and doing so can even be advantageous, make will always read a makefile if it can find one by one of the default names it looks for.
Moreover, though it may not be obvious in this case, the name given in the message is not just a base name but a (relative) path to the file. It is therefore complaining about a file named Makefile in make's working directory.
Right now there is a Makefile in the directory from where I call make
and it is like this
build/Makefile
no tabs or spaces I also did cat -A Makefile and I got
build/Makefileroot#themachine.....
Those two claims do not appear to be consistent with each other. In any case, however, neither one attributes valid makefile content to the makefile in question. This is likely the cause of the error message, which would then be a bit misleading.
It looks like you may be trying to have one makefile specify that another make be run in the build/ directory -- a so-called "recursive make". There are a couple of variations on how that is done, and they differ slightly in effect, but here's a guess at what you might be after for that top-level Makefile:
all:
$(MAKE) -C build
Of course, that second line needs to be indented with a leading tab, not spaces.
That will cause the top-level make run to trigger a second make run with the build/ directory as the second's working directory.

Makefile static pattern rule matching issue

I think there is something kind of basic I am missing about the gnu make (I am using 3.81 if it matters) static pattern rule matching (which apparently someone else did as well where I work because this was discovered as I was trying to fix a rule that had been commented out). I have tried to simplify my example down to the crux of it (hopefully I haven't' missed anything essential in the real example).
So this appears to work as I'd expect
JUNK:=foo bar
BINS:=$(patsubst %,bin/%,$(JUNK))
all : $(BINS)
.PHONY : all
# This works
$(BINS) : bin/% : %
mkdir -p bin && cp $< $#
But this (which is closer to what I found in the real Makefile) does not
JUNK:=foo bar
BINS:=$(patsubst %,bin/%,$(JUNK))
all : $(BINS)
.PHONY : all
# This doesn't work
$(JUNK) : bin/% : %
mkdir -p bin && cp $< $#
# This doesn't work either
#bin/$(JUNK) : bin/% : %
# mkdir -p bin && cp $< $#
Based on my understanding of what should be happening in both cases I would have expected that both Makefiles would behave exactly the same; however, only the first one behaves as I expected (i.e., properly copies the files to bin) and the second gives the following output
Makefile:12: target `foo' doesn't match the target pattern
Makefile:12: target `bar' doesn't match the target pattern
make: *** No rule to make target `bin/foo', needed by `all'. Stop.
What is more confusing is there are nearly identical other static pattern rules in the make file I was examining that were working.
So I obviously know how to "work around" the issue if need be but I'd like to understand why the second (and the commented out portion in the second code block as well) do not do what I expect them to.
Thanks in advance for any help/insight.
The first one doesn't work because, after expanding the JUNK variable, make sees this:
foo bar : bin/% : %
The way static pattern rules work is that the first pattern (the target pattern) must match each word in the list of targets. That tells make which part of the target name is the stem (the part that matches the %). If the target pattern doesn't match, make doesn't know what the stem is. The pattern bin/% does not match the text foo, (there is no bin/ in the text foo) so you get the error you see.
The second one doesn't work because the result of exanding the JUNK variable in this example (bin/$(JUNK) : bin/% : %) looks like this:
bin/foo bar : bin/% : %
Here, bin/foo matches the pattern, but bar doesn't match and so you get the same error as you did in the previous one.
To make it work you must have bin/ prepended to every target, not just the first target, hence the use of patsubst (or, addprefix would work as well).

Makefile sequential execution

I have the following Makefile:
all: generate print # <-- doesn't work
date:
date > date.txt
ls:
ls -la > ls.txt
generate: ls date
print: *.txt
cat $^
clean:
rm *.txt
The targets date and ls generate a file each, the target print, prints them out.
How do I write the target all, so that it first generates the files and then prints it?
Just add the pipe symbol:
all: | generate print
From the make manual:
Order-only prerequisites can be specified by placing a pipe symbol (|) in the prerequisites list: any prerequisites to the left of the pipe symbol are normal; any prerequisites to the right are order-only:
targets : normal-prerequisites | order-only-prerequisites
The dependancy hierarchy of the rules you want is all -> print -> generate.
'print' should be dependant on 'generate'.
The Makefile you have is interesting. On first pass it generates the .txt files using { all -> generate -> ls, date } hierarchy but the print fails. On second pass if you don't do clean it works.
The 'print' rule you have is a valid rule. But doesn't allow make to know that you need to do the 'generate' actions before doing the 'print'.
You could EXplicitly make a print rule which says it is dependant on generating date.txt and ls.txt. Try change your 'all' and 'print' rules like this . . .
EDIT: SORRY! First Answer I gave doesn't work. Tested it. This works.
all: print # <- just print target here as you don't want generate to happen after print
.
print: generate ls.txt date.txt
cat $^
Make could decide to do print action first and the generate action afterwards if print is not made dependant on the files explicitly or generate.
This works but we get an error as the cat of non existant file generate doesn't work.
Taking this a bit further . . . Get rid of the generate rule. And I think the date and ls rule would be better if they explicitly detailed what file they generated, i.e.
all: print
date.txt:
date > date.txt
ls.txt:
ls -la > ls.txt
print: ls.txt date.txt
cat $^
*.txt. If you want to operate on multiple files with same extension then you can do different things e.g. put the list of files in a make variable. You can have a make rule to calculate this list of files (using shell cmd in make). But that make rule cannot be dependant on the files already existing if it is the thing that is generating them.
The make manual gives a rule very close to your original print rule - using wildcard in rule prerequisites.
http://www.gnu.org/software/make/manual/make.html#Wildcard-Examples
Make has quite a simple hierarchy of dependancies. Make will follow dependancies in order.
Getting your head around the sequence a makefile will follow can be tricky but it is actually quite simple enough so well worth while working on understanding it.
It is a common problem for makefiles for some part of make system to be missing a dependancy on another. Often build systems will get away with this but sometimes it can cause weirdness (e.g. object files being compiled after being linked in).
The make manual has a good introduction.
http://www.gnu.org/software/make/manual/make.html#Introduction
Secondary Expansion not work for me.
I choose to delay wildcard call by use another make in recipe:
all: generate
$(MAKE) print

Make error of mixed implicit and normal rules

When building an open source project I met error of:
make subdir=manual -C manual ..=../ subdir_lib
Makefile:235: *** mixed implicit and normal rules. Stop.
Code from line 235 of the Makefile as follows:
235: $(objpfx)stubs ../po/manual.pot $(objpfx)stamp%:
236: $(make-target-directory)
237: touch $#
That error message is printed by GNU make when you have something that looks like a pattern rule output (containing a %) as well as something that looks like a normal output (no %) on the left-hand side of a : in a rule declaration. For example:
%.pat normal:
#echo $#
So on line 235 of your Makefile, you have managed to put together something that "looks like" that construct. To avoid the error, fix that declaration, most likely by splitting it into two:
%.pat:
#echo $#
normal:
#echo $#
Without seeing the complete makefile that produced this error there's not much more advice we can give you.
I am here to remind the successor, check your path, is there any space in it?
We wasted all afternoon on this!
In my case, the error was due to idiotically putting an extraneous : at the end of the dependency line:
%.o: %.cpp:
g++ -c -o %# $<
Just had this myself and it was due to a hidden space after a "/" in a variable definition i.e.
#accidental/invisible space left after the final "/" i.e...
DESTDIR=path/to/the/destination/directory/
# ...just here ^
#rule to make copies of text files...
$(DESTDIR)%.txt:$(SRCDIR)%.txt
The problem described in this question has been reported here
http://sourceware.org/bugzilla/show_bug.cgi?id=11873
The fix was indeed to split the rule, as suggested by Eric.
Completing Eric Melski answer, you can do this to avoid duplicating code everywhere:
define DEFAULTTARGET :=
#echo $#
endef
%.pat:
${DEFAULTTARGET}
normal:
${DEFAULTTARGET}
Check your path, check where you have saved your projects, there shouldn't be a space in the name of the directory. Save it along with system generated projects directory files if u have imported it from another source
maybe you have "space" character after path.
for example:
(this is a ' ' character at the end)
PATH_OUT = ../lib
then you use
$(PATH_OUT)/1.cc
and you will get this error

GNU Make and wildcards - missing files

I have a Makefile with the following type of rule:
%.html:
./generate-images.py > $#
make $(patsubst %.png,%.gif,$(wildcard *.png))
The generate-images script writes not only the HTML file (to stdout) but several .png files to the current directory. The goal here is to convert them to .gif. (not really, but this is an example)
This works if I invoke it directly. The problem is: If I invoke it from another rule where foo.html is a dependency, the wildcard statement fails to find any files. In other words, it just called make with no arguments, which is not what I want here.
What's the deal with the wildcard? Or, is there a better way to do this?
While your problem may be something different, I clearly see one.
The whole text of all commands within the rule is simultaneously processed so that make's functions and variables get expanded. Assume you have no .png files in the directory, and you invoke make so it should regenerate them: a.png and b.png. Then, after you invoke make, the text of the rule would effectively look like this:
file.html:
./generate-images.py > file.html
make
because at the moment of reading the makefile there were no .png files! After the first line is executed, the files will appear, but the next line was already generated to be just "make".
And only when you invoke your makefile for the second time, will it expand to
file.html:
./generate-images.py > file.html
make a.gif b.gif
This is not what you want. So I suggest doing it in The Right Way.
# If you have batch conversion program, this may be helpful
images.stamp: *.png
convert_all_images $?
touch images.stamp
# OR, if you want convert one-by-one with means of make
images.stamp: $(wildcard *.png)
touch images.stamp
%.gif: %.png
convert_one --from=$^ --to=$#
# HTML would look like
%.html:
./generate-images.py > $#
make images.stamp
So when you invoke make all, it generates htmls and converts newly generated images. Note that it will only convert the images that are updated, which is what you want.
Thanks to Beta for pointing out the mess with gif/png extensions.
That sounds like it's evaluating all of the $() expressions as it's processing the Makefile, rather than as it executes each rule. You could add a rule to your makefile like so:
images: $(patsubst %.png,%.gif,$(wildcard *.png))
.PHONY: images
and then change your example snippet to
%.html:
./generate-images.py > $#
make images
so that Make evaluates the glob at the right time. This is something about which checking the manual might be worthwhile.

Resources