I am new to GNUmakefile and what I want to do is really simple. As you can see below, OBJS contains all the *.c files under MYDir . What I want to do next is to have a program called MyProgram to run on EACH .c file stored in the OBJS . But I don’t know how to pass each .c from the OBJS to “runThis”.
Thanks
DIR := MyDir
OBJS := $(wildcard $(DIR:=/*.c))
.PHONY: all
all : $(OBJS) runThis
runThis:
MyProgram some.c
Most simply, you could pass the $(OBJS) (which I took the liberty of renaming to CFILES) directly in the rule:
DIR := MyDir
CFILES := $(wildcard $(DIR:=/*.c))
.PHONY: all
all:
for f in $(CFILES); do MyProg $$f; done
This is assuming Bourne style shell (like bash, dash, ash, etc) and that your file names do not contain spaces.
You could also let the GNU make do the "hard work" of looping:
DIR := MyDir
CFILES := $(wildcard $(DIR:=/*.c))
.PHONY: all
define gen-rule
all: process-$1
process-$1:
MyProg $1
endef
$(eval $(foreach c,$(CFILES),$(call gen-rule,$(c))))
For each file $(c) in $(CFILES), we create a rule process-$(c) and induce all rule to depend on that rule.
Hear's another route:
DIR := MyDir
OBJS := $(wildcard $(DIR:=/*.c))
DUMMY_TGTS := $(addsuffix ., $(OBJS))
.PHONY: all $(DUMMY_TGTS)
all : $(DUMMY_TGTS)
$(DUMMY_TGTS) : %. : %
MyProgram $<
As usual with stackoverflow make answers you will need to switch the indent from spaces to a tab.
It uses a Static Pattern rule to call MyProgram on each of the .c files individually. The DUMMY_TGTS are setup with .PHONYensure they will still trigger the rule even if there is a file existing with that name.
Related
In a toplevel (unix, GNU) Makefile I want to iterate over a list of subdirs and execute tasks in there but exclude some of them. In this case exclude all subdirs starting with an underscore (_)
The following is working in iterating but ignores the exclusion regex. It still visits dir "_exclude".
In particular I think it ignores the "start of string" ^ (or it takes it literally). I have tried other regexes and they do work. Any idea how to fix that? Or indeed if you have any idea how to eliminate the shelling out or not using GNU makefile extensions?
SHELL=/bin/bash
EXCLUDE_DIRS_REGEX=^_
# later addition:
ALLMAKEFILES = $(shell find . -maxdepth 2 -type f -name Makefile)
SUBDIRS = $(filter-out ./,$(dir $(ALLMAKEFILES)))
all:
for dir in $(SUBDIRS); do \
if [[ "$$dir" =~ $(EXCLUDE_DIRS_REGEX) ]]; then continue; fi; \
make -C $$dir all; \
done
You have two problems to solve:
compute the list of target directories
call make in each of them
For the first one a mixture of make and shell functions or built-ins could be something like:
REGEX := ^_
ALLMAKEDIRS := $(patsubst %/,%,$(dir $(wildcard */Makefile)))
SUBDIRS := $(shell for d in $(ALLMAKEDIRS); \
do ! [[ "$$d" =~ $(REGEX) ]] && echo "$$d"; done)
I kept the REGEX just in case you have more complex regular expressions or you would like it to be easily modified. But of course if it is exactly ^_ and you never change it the following is simpler:
SUBDIRS := $(filter-out _%,$(patsubst %/,%,$(dir $(wildcard */Makefile))))
For the second one your approach is not very make-ish. A better approach would be to have one rule per subdirectory. The following is an example:
.PHONY: all $(SUBDIRS)
all: $(SUBDIRS)
$(SUBDIRS):
$(MAKE) -C $# all
It has several advantages:
there is no need to loop over subdirectories in a complicated recipe, make will do it for you,
make can launch several jobs in parallel (see the -j option) and this will speed-up your build.
Note: calling make in a Makefile is not recommended. Prefer $(MAKE). See this section of the manual for the details.
Say I have a list of source files like this:
SOURCE=aaa.src bbb.src ccc.src
I want to create a rule to build each corresponding target in its own folder, the name of which depends on the soruce file.
Sourcefile ----> Corresponding output file / target
aaa.src -------------------> aaa/aaa.out
bbb.src -------------------> bbb/bbb.out
ccc.src -------------------> ccc/ccc.out
How do I write a rule for this using GNUMake? My best effort was the following Makefile:
.PHONY: all clean
CC=somecompiler
SOURCE := aaa.src bbb.src ccc.src
RTARGS := $(SOURCE:%.src=%.out)
TDIRS := $(addsuffix /,$(basename $(SOURCE)))
TARGS := $(join $(TDIRS), $(RTARGS))
all:$(TARGS)
%.out: $(SOURCE) # Better source specification?
#[ ! -d "$(dir $*)" ] && mkdir "$(dir $*)"
$(CC) "$(patsubst %/,%,$(dir $*)).src" "$#"
clean:
rm -f $(TARGS)
rmdir --ignore-fail-on-non-empty $(TDIRS)
The problem here is, that any one target (i.e. .out file) depends on every source (i.e. .src file), instead of just the one that has the same basename. I could change the commented line to %.out: %.src but than the source file would have to be in the same directory as the output file. I could also compile it something like this:
%.out: %.src
$(CC) "$>" -o "$*/$#"
But then make would always compile every target regardless of whether it already exists or not.
How do I get make to use the appropriate source file only. What is the proper way of specifying dependences for each target separately in a generic rule?
In GNU Make you can specify prerequisites separately from recipes and still have a generic / pattern rule for all .out files:
.PHONY: all clean
all :
SOURCES := aaa.src bbb.src ccc.src
OUTPUTS := $(foreach src,${SOURCES},$(basename ${src})/${src:%.src=%.out})
# Build dependencies in the form of x/x.out : x.src | x
define ESTABLISH_DEPENDENCY =
$(basename ${1})/${1:%.src=%.out} : ${1} | $(basename ${1}) # Also depend on the output directory.
$(basename ${1}) : # Rule to create the output directory.
mkdir $$#
endef
$(foreach src,${SOURCES},$(eval $(call ESTABLISH_DEPENDENCY,${src})))
all : ${OUTPUTS}
# Generice rule for all .out files.
%.out :
#echo "build $# from $^"
touch $#
%.src : # For debugging only.
touch $#
.PHONY: all
Output:
$ make
touch aaa.src
mkdir aaa
build aaa/aaa.out from aaa.src
touch aaa/aaa.out
touch bbb.src
mkdir bbb
build bbb/bbb.out from bbb.src
touch bbb/bbb.out
touch ccc.src
mkdir ccc
build ccc/ccc.out from ccc.src
touch ccc/ccc.out
Note that it is more efficient and elegant to have order-only dependencies on directories and let make create them, than to have each recipe checking directory existence first.
I'm trying to understand a makefile, can anyone tell me what the following line does:
#echo cp -f --preserve=mode,timestamps $(call $1,$<) $(call $1,$#)
Especially I don't get what is the significance of $1 and call here.
There's no way to know what this does, since it's completely out of context.
It looks to me like this value is supposed to be passed to another instance of $(call ...). So for example if your makefile has:
QUOTE = '$1'
COPY = #echo cp -f --preserve=mode,timestamps $(call $1,$<) $(call $1,$#)
then later you would see something like:
foo: bar ; $(call COPY,QUOTE)
The first call would expand to the COPY value with $1 replaced with QUOTE, so it would be:
#echo cp -f --preserve=mode,timestamps $(call QUOTE,bar) $(call QUOTE,foo)
then that gets expanded, and you end up with:
#echo cp -f --preserve=mode,timestamps 'bar' 'foo'
But without more information we can't say more.
The 'call' command is a GNU extension in GNUmake; it is not supported in POSIX make or most other makes. It basically expands a macro with arguments. Something like
$(call A,b,c,d)
will expand the macro A with the arguments b, c, and d. The arguments are assigned to the temporary macros $(1), $(2), ... which may be present in the definition of A
See the GNUmake documentation
I have a number of latex files, and I want to be able to compile them all conveniently. My makefile is currently as follows.
targets := $(patsubst %.tex, %.pdf, $(wildcard *.tex))
.PHONY: all
all: $(targets)
.SECONDEXPANSION:
%.pdf: %.tex $$(wildcard $$*_inc/*.*)
pdflatex $<
This way, if an include folder exists, everything within that folder will be treated as a dependency.
However, I also want to automate the running of dependent python scripts. These might be the creation of plots or the calculation of values to be included. I attempted to make the following modification.
targets := $(patsubst %.tex, %.pdf, $(wildcard *.tex))
all: $(targets)
.PHONY: all run_%
.SECONDEXPANSION:
%.pdf: %.tex $$(wildcard $$*_inc/*.*) $$(patsubst %, run_%, $$(wildcard $$*_inc/*.py))
pdflatex $<
run_%: %
$<
However, this does not work as I would expect to. I have the following folder structure.
|
|-Makefile
|-paper.tex
|-paper_inc/
|---a.txt
|---b.py
I would expect this to run b.py, then run pdflatex paper.tex. However, b.py is not run. If I look at the dependencies created, I see that paper_inc/a.txt and paper_inc/b.py are dependencies of paper.pdf, but run_paper_inc/b.py is not.
I'm not entirely certain what is the issue with this, as it feels that it should work. In addition, I tried the following lines as well for the %.pdf rule.
%.pdf: %.tex $$(wildcard $$*_inc/*.*) $$(addprefix run_,$$(wildcard $$*_inc/*.py))
%.pdf: %.tex $$(wildcard $$*_inc/*.*) $$(shell ls $$*_inc/*.py | sed 's/^/run/')
%.pdf: %.tex $$(wildcard $$*_inc/*.*) $$(shell ls $$*_inc/*.py | awk '{print "prefix "$0}')
With each of these rules, though, I receive the error message make: *** No rule to make target 'paper.pdf'. Stop.
What should be be done to fix this error, or, alternatively, what should I use instead of make?
You have two problems.
First:
run_%: %
$<
From the manual:
When the target pattern does not contain a slash (and it usually does
not), directory names in the file names are removed from the file name
before it is compared with the target prefix and suffix. After the
comparison of the file name to the target pattern, the directory
names, along with the slash that ends them, are added on to the
prerequisite file names generated from the pattern rule's prerequisite
patterns and the file name.
This is a little hard to follow, but basically when Make tries to build run_paper_inc/b.py, it looks for a pattern rule that matches b.py. The rule above doesn't fit. But this does:
%.py:
$(subst run_,,$#)
Second:
.SECONDEXPANSION:
%.pdf: ... $$(patsubst %, run_%, $$(wildcard $$*_inc/*.py))
...
One of Make's big shortcomings is its weak handling of wildcards. In this case % can't work for the pattern rule and the patsubst at the same time. But there's a way:
.SECONDEXPANSION:
%.pdf: ... $$(addprefix run_,$$(wildcard %_inc/*.py))
...
This question is similar in spirit to question 2543127.
I have a gnu makefile with a list of header files. Each header file may be located in a different directory, e.g.,
HEADERS = $(wildcard *.h) $(wildcard foo/*.h) $(wildcard bar/*.h)
and I want to have the makefile copy all headers to an include directory
INCDIR = ../include
and when a dummy target, e.g., ALL is invoked, it will update the header files in the include directory appropriately, i.e.,
.PHONY: ALL
ALL : $(addprefix $(INCDIR)/,$(notdir $(HEADERS)))
Obviously, I could accomplish what I want quite easily if I knew what the lists of directories were. If I did, then I could write some rules (something) like so (not entirely correct, but you get the jist):
$(addprefix $(INCDIR)/,$(notdir $(filter foo/%.h,$(HEADERS)))) : %.h : foo/%.h
#cp -f $< $#
$(addprefix $(INCDIR)/,$(notdir $(filter bar/%.h,$(HEADERS)))) : %.h : bar/%.h
#cp -f $< $#
$(addprefix $(INCDIR)/,$(notdir $(filter-out bar/%.h,$(filter-out foo/%.h,$(HEADERS))))) : %.h : %.h
#cp -f $< $#
There are two problems with this approach, (1) It becomes tedious as the number of directories increases and (2) I am writing this in a makefile include, which doesn't know directories, all it knows are the variables INCDIR and HEADERS; it does not directly know the directories foo/, bar/, and ./ other than through $(sort $(dir $(HEADERS)))
Question: How can I write a rule to achieve the desired effect under the constraints of only being provided the INCDIR and HEADERS variables.
This should do it:
HFILES = $(notdir $(HEADERS))
DIRS = $(dir $(HEADERS))
TARGETS = $(addprefix $(INCDIR)/, $(HFILES))
all: $(TARGETS)
$(INCDIR)/%.h: %.h
cp $< $#
vpath %.h $(DIRS)
OK. The answer is pretty "easy", although it requires usage of some gnu make that I haven't previously used. My solution, creates a subroutine that requires 2 arguments: (1) the name of the file (sans directory) and (2) the name of the directory in which it resided.
The "subroutine" is a template for a rule. When one evaluates the call to the subroutine, one initiates another rules, just as if one had written it explicitly.
define COPY_HEADER
$$(INCDIR)/$(2) : $(1)$(2)
#cp -f $$< $$#
endef
One then evaluates this subroutine for every header file and passes in the directory part and the file part of each header file.
$(foreach file,$(HEADERS),$(eval $(call COPY_HEADER,$(dir $(file)),$(notdir $(file)))))