Make make rebuild a target when it depends on a deleted file - makefile

Suppose I have a make rule like this:
SOURCES := $(wildcard ./text/*.txt)
$(INDEX) : $(SOURCES)
$(COMPILER) $(SOURCES)
And then one of the text files, ./text/foo.txt, is deleted. The target $(INDEX) does not seem to be rebuilt. How do I make make rebuild in this case?

If your ./text directory contains only your sources and all of them, you can add it as a pre-requisite of your target:
$(INDEX) : $(SOURCES) ./text
Directories are not like regular files: their last modification date is updated when you add, delete or rename a file (or subdirectory) in them, not when an existing file is modified. Think of it as a file containing the list of contained files.

Related

copying only changed files between directories using Makefile

I read this: Makefile: Copying files with a rule but couldn't do it.
To make it simple, suppose I have two directories dir1 and dir2. Under dir1 I have three files: rabbit.c, tiger.c and bus.c .
I made Makefile like this:
dir2/rabbit.c:dir1/rabbit.c
dir2/tiger.c:dir1/tiger.c
dir2/bike.c:dir1/bike.c
dir2/%:
cp -f $< $#
I specified the prerequisites in three separate lines and specified the unified recipe for the three targets. I expected when I touch any file under dir1, make will copy that file to dir2. But this happend only for rabbit.c. What is wrong?
ADD(after selecting an answer) :
After realizing what's wrong by Takkat's answer, I fixed it and later modified it further and I think this is the correct simplest Makefile for this case.
.PHONY:all
LIST:=rabbit.c tiger.c bike.c
DSTFILES:=$(addprefix dir2/, $(LIST))
all: $(DSTFILES)
dir2/%:dir1/%
cp -f $< $#
Make chooses a default target in your makefile and, unless you specify differently on the command line, it builds just that target (and all prerequisites required to build that target).
The default target in a makefile is, by default, the first explicit target listed.
So in your makefile the first rule is:
dir2/rabbit.c:dir1/rabbit.c
so the first explicit target is dir2/rabbit.c, so that's all make builds.
If you want to build multiple targets by default, you need a first target that lists all the "real" targets as prerequisites; put this line first in your makefile:
all: dir2/rabbit.c dir2/tiger.c dir2/bike.c
and it will work. It's often considered good practice to declare targets like this, which don't relate to real files on the disk, as phony:
.PHONY: all

How to create a rule to identify all the files with a .c extension on the included directories as a pre-requisite for a makefile rule?

If I have the rule, where OBJECTS_C is a list of object files with NO path:
$(OBJECTS_C): %.o: %.c
do stuff
how can I specify that the %.c file is supposed to match the same file stem, but the path can be anything?
Like suppose I have source/file1.c and source/dir1/file2.c
I want to modify the rule such that file1.o and file2.o are created on the current directory, regardless of where the source files are on the included directories.
You could use VPATH (as a variable or using the vpath directive) to add all the relevant directories to the list of directories searched for prerequisites.
(VPATH is for all prerequisites, vpath only for those matching the pattern it is given)
Here is the relevant documentation.
That said, beware of name conflicts : if you have src files that have the same name but are in different directories, you might experiment troubles. A better way would be to have your build tree reflects your source tree.

makefile ignore removed file names

A directory with css files in it and for each file in the directory I want a separate minified .min.css file in the same directory.
So for example my.css get minified into my.min.css in the same directory.
First I tried
css/*.css:
uglifycss $# > $(subst .css,.min.css,$#)
make -B yeaaa victorie its working :D
But after doing make -B again I get a new separate file each time resulting in my.min.css my.min.min.css my.min.min.min.css
Then I tried
.PHONY: clean
css/*.css: clean
uglifycss $# > $(subst .css,.min.css,$#)
clean:
-rm css/*.min.css
DOH! after clean it is still remembering the files it deleted in the first place resulting again in a my.min.min.min.css file
How can I tell make to stop doing my.min.min.min.css?
(make: GNU Make 3.81 OSX)
First get a list of all files with the suffix .css:
ALL := $(wildcard *.css)
then remove files that have the suffix .me.css:
NEW := $(filter-out %.me.css,$(ALL))
and add the suffix to remaining files:
ME := $(patsubst %.css,%.me.css,$(NEW))
Then you add those files as prerequisites to the default target, and add you own recipe that builds those files, in this case a simple echo:
%.me.css:
echo 123 > $#
default: $(ME)
Compared to your approach, this has the benefit that you don't have to use the flag -B, as only the files that need to be built are built. Therefore invoking make is done by simply caling make without any targets or flags (assuming the makefile is named makefile or Makefile):
make

How to write a Make rule for files of certain type in a directory tree?

Imagine a directory tree (which might be more than one level deep) containing several Markdown files. A PDF version of each file exist in the same directory and must be updated each time the corresponding Markdown file is updated. What rule must be written in a single Makefile in the root directory of this tree to achieve this?
I am looking a for a solution where files can be added or removed from the directory tree without a need for updating the Makefile.
Assumptions:
all markdown files follow a certain pattern in their name; for example they end with a .md postfix.
GNU Make is being used.
You can use $(shell find) to find files recursively. For example:
markdown := $(shell find . -name '*.md')
all: $(patsubst %.md, %.pdf, $(markdown))
%.pdf: %.md
pandoc -o $# $<

Use directory path of target in list of prerequisites in Makefile

I wrote a script that takes in two files ending in .cfg and outputs a file ending in .cmp. I want to include this in my Makefile because a few source code files depend on this .cmp file.
In my Makefile, I want to do this:
%.cmp: %.cfg $(dir %)/default.cfg
./compare.pl $^ $#
There are two dependencies to generate the .cmp file. First is a .cfg file with the same name, and second is a .cfg file which is always named default. Both .cfg files and the output .cmp file will be in the same directory.
Is there a way to grab the directory path of the target and use it with the prereqs?
I guess Secondary Expansion is probably what you're looking for:
.SECONDEXPANSION:
%.cmp: %.cfg $$(dir %)default.cfg
./compare.pl $^ $#
Also note the absence of slash after $$(dir %), dir function always append one to the resulting value.

Resources