Add prerequisite on condition - makefile

Is it possible to add a prerequisite if another file is found in the workspace? Or how else could I achieve the following idea? Basically if my workspace has a lcf file in a specific location I need to make another file.. Something like this:
lcf := ../base_sw/lcf/base.lcf
.PHONY :
all : $(objects)
# if $(lcf) file exists then
all : $(objects) sup.a2l
sup.a2l :
# Perl script runs here to produce sup.a2l
#echo Chris > $#

This should do it:
lcf := $(wildcard ../base_sw/lcf/base.lcf)
.PHONY :
all : $(objects) $(lcf)

Think I've managed to answer this one myself!
The wildcard function returns nothing if lcf file does not exist:
lcf := $(wildcard ../base_sw/lcf/base.lcf)
Start to build the files that need making:
make_these_file := $(obejcts)
If lcf variable is not empty, append to files list:
ifneq ($(lcf),)
make_these_file += sup.a2l
endif
Now our target with files required to make:
.PHONY :
all : $(make_these_file)
sup.a2l :
# Perl script here to produce sup.a2l
#echo Chris > $#
Works for me :)

Related

In a Makefile, use patsubst and wildcard with subfolders and subfolder substitutions

I'm trying to use a makefile to convert some markdown files to html files. I'm trying to accomplish in a few lines that which I previously had a long python script doing.
In the simple example below, I would like to see this code:
build: $(patsubst src/pages/%.md, output/%.html, $(wildcard src/pages/*.md))
%.html: %.md
#echo $< to $#
and this output
src/pages/index.md to output/index.html
src/pages/about.md to output/about.html
src/pages/contact.md to output/contact.html
src/page/foo/bar.md to output/foo/bar.html
Instead, it says:
$ make build
make: *** No rule to make target 'output/index.html', needed by 'build'. Stop.
I'm missing something very basic here.
Consider the target output/index.html. The dependency...
%.html: %.md
will effectively expand to...
output/index.html: output/index.md
with $* equal to output/index. So make looks for output/index.md but can't find it -- hence the error message.
To get the correct pattern stem ($* == index) you need to add the base directories to the pattern rule...
output/%.html: src/pages/%.md
#echo $< to $#
EDIT 1:
If you're concerned about repeated hard-coded strings such as output and src/pages then you can always assign them to parameters...
OUTPUT_DIR := output
SOURCE_DIR := src/pages
build: $(patsubst $(SOURCE_DIR)/%.md, $(OUTPUT_DIR)/%.html, $(wildcard $(SOURCE_DIR)/*.md))
$(OUTPUT_DIR)/%.html: $(SOURCE_DIR)/%.md
#echo $< to $#
(Assuming that's what you meant by `optimization' in your comment.)

Make use Pattern Rule for multiple prerequisites and multiple targets

I have a problem with make and I cannot figure out how to solve it. I would like to transform each file in a sub-directory using a shell script. This is what I wrote:
OBJ=$(wildcard src/*.in)
OUT=$(patsubst %.in, %.out, $(notdir $(OBJ)))
%.out : src/%.in
./myscript.sh $< > $#
$(OUT) : $(OBJ)
The makefile works but it runs the script only for the first .in file and then it stops. Sorry for the dumb question but I cannot fix this!
Because you are not telling the Makefile to build all $(OUT) files, you are just saying how it should be built.
Try instead this
OBJ=$(wildcard src/*.in)
OUT=$(patsubst %.in, %.out, $(notdir $(OBJ)))
all: $(OUT)
%.out : src/%.in
./myscript.sh $< > $#
.PHONY: all

GNU make wildcard variable target

I'm trying to create a makefile with wildcard targets but the wildcards should match on variables.
So I have a makefile like this:
A_OUT := bin/a
B_OUT := bin/b
# This does not work
$(%_OUT):
#echo $#
Output:
$ make bin/a
make: *** No rule to make target 'bin/a'. Stop.
I can not use bin/%: because the variables may point to another directory.
Is there any way to do this in GNU make?
If you just want a list of targets to all have the same recipe then just list them all in the same rule definition. e.g.
$(A_OUT) $(B_OUT):
#echo $#
You can use a variable for that too:
A_OUT := bin/a
TGTS += $(A_OUT)
B_OUT := bin/b
TGTS += $(B_OUT)
$(TGTS):
#echo $#
Depending on what you need you may also want to use Static Pattern Rules
$(TGTS) : bin/% :
#echo $# : $*

How to write a makefile

Okay so what needs to be done is that the makefile must compile a .test into a .vtt only when it's .test has changed since the most recent build. I don't have the paths to the .test files directly but I can get a list of them and the supposed path to the new .vtt file can be generated from that. What I have so far is:
SRC_DIR = .
TEST_DIR = $(SRC_DIR)/test
SPEC_DIR = $(TEST_DIR)/spec
OBJ_DIR = $(SRC_DIR)/objdir
OBJ_DIR_SPEC = $(OBJ_DIR)/test/spec
TEST_SRC := $(shell find $(SPEC_DIR) -name '*.test' -print)
VTT_SRC := $(subst $(SRC_DIR)/test,$(OBJ_DIR)/test,$(subst .test,.vtt,$(TEST_SRC)))
RUN_STIP_VTT = $(SPEC_DIR)/strip-vtt.py
%.vtt : %.test:
$(PYTHON) $(RUN_STIP_VTT) $< $#
$(VTT_SRC): $(TEST_SRC)
$(PYTHON) $(RUN_STIP_VTT) $< $#
objdir:
mkdir $(OBJ_DIR)
check-js: objdir $(VTT_SRC)
$(PYTHON) ./test/spec/run-tests-js.py $(OBJ_DIR_SPEC)
TEST_SOURCE is a list of the .test files that have been found. VTT_SOURCE is a list of the transformed test files into the .vtt format underneath and object directory. I need to be able to find the .vtt files dependency .test file in the TEST_SOURCE and somehow tell the makefile about that connection.
Ended up fixing it with these changes:
check-js: objdir $(VTT_SRC)
$(PYTHON) ./test/spec/run-tests-js.py $(OBJ_DIR_SPEC)
$(OBJ_DIR)/%.vtt : $(SRC_DIR)/%.test
#$(PYTHON) $(STIP_VTT) $< $#
I'd use a static pattern rule:
$(VTT_SRC): $(OBJ_DIR)/%.vtt : $(SRC_DIR)/%.test
$(PYTHON) $(RUN_STIP_VTT) $< $#
The VPATH construct in Make is probably what you're looking for.

Unix find with GNU Make to auto-update files

I have .haml files and want to convert them automatically into .html files and update the latter when .haml is changed.
The generic makefile rule is no problem:
%.html: %.haml
hamlpy $< $#
But now I need a rule or a command to do the following:
find all X.haml files in templates/
execute make X.html command, where X is the same filename (haml is replaced with html).
I can't find how to do this with GNU Make or Unix find.
If all of your *.haml files are well name (i.e. no spaces or other funny characters), you can do it with a call to find(1):
HAML_FILES = $(shell find templates/ -type f -name '*.haml')
HTML_FILES = $(HAML_FILES:.haml=.html)
all: $(HTML_FILES)
%.html : %.haml
hamlpy $< $#
You can use GNU make wildcard function to find files in a certain directory:
INDIR := templates
OUTDIR := ${CURDIR}
haml_files := $(wildcard ${INDIR}/*.haml)
html_files := $(subst ${INDIR}/,${OUTDIR}/,${haml_files:.haml=.html})
all : ${html_files}
clean :
rm -f ${html_files}
${OUTDIR}/%.html : ${INDIR}/%.haml
hamlpy $< $#
.PHONY : all clean
INDIR and OUTDIR can be customized on the command line, for example, to use the current directory for inputs and iutputs:
$ make INDIR=. OUTDIR=.

Resources