I'm trying to generate bindings using SWIG and an automatic input file list. But apparently it is not working (make simply says there's nothing to do for target 'bindings'). Manually calling make as make whatever.i works as intended.
I have the following Makefile.am by now:
bin_PROGRAMS = ptpcapture2
ptpcapture2_SOURCES = *.scm
BINDSRCS = *.i
BINDSCMS = $(BINDSRCS:.i=.scm)
.i.scm:
$(SWIG) -chicken -addextern $<
.scm.c: bindings
$(CSC) -t -c $<
bindings: $(BINDSCMS)
What did I miss or do wrong?
If you're going to use suffix rules, you have to add any new suffixes to the list of known suffixes via the .SUFFIXES special target:
.SUFFIXES: .i .scm
It's simpler to just use pattern rules instead:
%.scm : %.i
$(SWIG) -chicken -addextern $<
%.c : %.scm bindings
$(CSC) -t -c $<
But the real problem here is that you have to be explicit about your wildcards, like:
ptpcapture2_SOURCES := $(wildcard *.scm)
BINDSRCS := $(wildcard *.i)
Why is this? Because the globbing is not expanded when the variable is assigned, it's only expanded when the rule is run. That means that this line:
BINDSCMS = $(BINDSRCS:.i=.scm)
sets BINDSCMS to the string *.scm because BINDSRCS is not expanded, it's still just the literal string *.i.
Why is that bad? Because then when make sees this:
bindings: *.scm
it tries to expand the wildcard *.scm... but none of those files have been created yet and so they don't exist, and this expands to no files, and so as long as the target bindings exists there's nothing to do to rebuild it (it has no prerequisites).
Related
I have another make-like tool that produces an XML as an artifact after parsing my makefile which I'll then further process with Python.
It'd simplify things for me - a lot - if I could have make consider every single prerequisite to be an actual target because then this other tool
will classify each and every file as a "job".
This is a fragment of my makefile:
.obj/eventlookupmodel.o: C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h \
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h \
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h \
...
I'd want for make to think I have a dummy rule for each prerequisite such as below:
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h:
#echo target pre= $#
C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h:
#echo target pre=$#
C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp :
#echo target pre=$#
C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h:
#echo target pre=$#
I don't care about the exact form of the rule just that each file is considered an actual target.
My method of passing in this rule would be by setting the MAKEFILES variable like so
make all MAKEFILES=Dummy.mk
with Dummy.mk containing this rule so that I do not modify the makefiles.
I've tried the following so far.
Dummy.mk:
%.h:
#echo header xyz = $#
%:
#echo other xyz= $#
This partially works.
I run make all --trace --print-data-base MAKEFILES=Dummy.mk and I can see that
make does "bind" the %.h: rule to the header files. In the --print-data-base section, I see that rule being assigned to the header files.
C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef.h:
# Implicit rule search has been done.
# Implicit/static pattern stem: 'C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef'
# Last modified 2016-05-27 12:39:16
# File has been updated.
# Successfully updated.
# recipe to execute (from '#$(QMAKE) top_builddir=C:/Users/User1/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/ top_srcdir=C:/Users/User1/Desktop/A/HMI_FORGF/ -Wall CONFIG+=release CONFIG+=qnx_build_release_with_symbols CONFIG+=rtc_build -o Makefile C:/Users/User1/Desktop/A/HMI_FORGF/src/HmiLogging/HmiLogging.pro
', line 2):
#echo header xyz = $#
However, I do NOT see the "echo header xyz $#"-rule being executed.
Regarding the %: rule, it is neither executed for the .cpp files nor "bound" to them in the --print-data-base section.
However, it is bound and executed for existing targets which have no suffix i.e.
all: library binary
binary: | library
ifs: | library
For the %: rule, the reason for this behavior is because of 10.5.5 Match-Anything Pattern Rules: If you do not mark the match-anything rule as terminal, then it is non-terminal. A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.
If I make it non-terminal - no double colon - then the rule doesn't apply to built-in types like .cppunless I un-define the built-in rules that negate my intended %: rule.
If I make it terminal, "it does not apply unless its prerequisites actually exist". But a .h or .cpp doesn't technically have prerequisites; can I just create a dummy file and have that as its prerequisite?
NOTE: This has NOTHING to do with gcc -M generation. Yes the -M option would help in the specific case of header and source files but this question is for more generic targets and prerequisites that already exist in the makefile when make is launched.
This may take a few iterations. Try:
%.h: null
#echo header xyz = $#
%: null
#echo other xyz= $#
null:
#:
Try generating static pattern rules for the header files. See one of the answers to Make ignoring Prerequisite that doesn't exist.
Static pattern rules only apply to an explicit list of target files like this:
$(OBJECTS): %.o: %.c
*recipe here*
where the variable OBJECTS is defined earlier in the makefile to be a list of target files (separated by spaces), for example:
OBJECTS := src/fileA.c src/fileB.c src/fileC.c
Note that you can use the various make utility functions to build that list of target files. For example, $(wildcard pattern), $(addsuffix), etc.
You should also ensure that the recipe "touches" the header file to change the timestamp.
I've found that using static pattern rules instead of pattern rules fixes problems where make doesn’t build prerequisites that don’t exist, or deletes files that you want.
Here is an example of using wildcard to copy files from one directory to another.
# Copy images to build/images
img_files := $(wildcard src/images/*.png src/images/*.gif src/images/*.jpg \
src/images/*.mp3)
build_images := $(subst src/,$(BUILD_DIR)/,$(img_files))
$(build_images): $(BUILD_DIR)/images/% : src/images/%
mkdir -p $(dir $#)
cp -v -a $< $#
There are other make functions like addprefix that could be used to generate a more complex file specification.
Motivation:
I have a C project in which multiple .o files are to be generated from a common file. This main file uses preprocessor directives to conditionally include other .h files as needed, depending on target-specific variables defined in the makefile.
I've written this rule below, but depending on the order in which I apply my variable references I get different outcomes.
One small(ish) change, two different outputs
Consider two versions of code from my Makefile. In version A we have the following snippets:
MAIN_OBJ:= $(MAIN_1) $(MAIN_2) $(MAIN_3) $(MAIN_4)
... omitted non-relevant rules (including an all: rule)
$(OBJECT_DIR)/$(MAIN_1): MFLAG = $(METHOD_1_FLAG)
$(OBJECT_DIR)/$(MAIN_2): MFLAG = $(METHOD_2_FLAG)
$(OBJECT_DIR)/$(MAIN_3): MFLAG = $(METHOD_3_FLAG)
$(OBJECT_DIR)/$(MAIN_4): MFLAG = $(METHOD_4_FLAG)
$(OBJECT_DIR)/$(MAIN_OBJ): $(SOURCE_DIR)/$(DEPENDENT_MAIN)
$(CC) -DUSE_$(MFLAG) $(CFLAGS) -o $# $<
This only successfully builds the first target, $(OBJECT_DIR)/$(MAIN_1). The remaining three never get compiled and make stops there.
Now in version B we redefine MAIN_OBJ so that the directory prefix is included within the target list itself:
MAIN_OBJ:= $(MAIN_1) $(MAIN_2) $(MAIN_3) $(MAIN_4)
MAIN_OBJ:= $(addprefix $(OBJECT_DIR)/,$(MAIN_OBJ)
... omitted non-relevant rules (again)
$(OBJECT_DIR)/$(MAIN_1): MFLAG = $(METHOD_1_FLAG)
$(OBJECT_DIR)/$(MAIN_2): MFLAG = $(METHOD_2_FLAG)
$(OBJECT_DIR)/$(MAIN_3): MFLAG = $(METHOD_3_FLAG)
$(OBJECT_DIR)/$(MAIN_4): MFLAG = $(METHOD_4_FLAG)
$(MAIN_OBJ): $(SOURCE_DIR)/$(DEPENDENT_MAIN)
$(CC) -DUSE_$(MFLAG) $(CFLAGS) -o $# $<
This solution works, and compiles all 4 .o files, each with the proper $(MFLAG) value.
What's happening here?
This is probably a dumb question, but why does Version A only compile one .o file? I recognize version B is a generally better way to write rules.
Let me provide one more example that will perhaps illustrate my confusion.
Say we want to write a much more common type of rule: compiling targets from a list with a pattern rule for finding dependencies.
Doing something similar to Version A wouldn't result in a single .o being successfully generated:
MY_FILES:= $(wildcard $(SOURCE_DIR)/*.c))
MY_OBJ:= $(patsubst $(SOURCE_DIR)/%.c, %.o, $(MY_FILES))
...
$(OBJECT_DIR)/$(MY_OBJ): $(OBJECT_DIR)/%.o: $(SOURCE_DIR)/%.c
$(CC) $(CFLAGS) -o $# $<
Clearly the above is a bad idea, and you should write something like this instead:
MY_FILES:= $(wildcard $(SOURCE_DIR)/*.c))
MY_OBJ:= $(patsubst $(SOURCE_DIR)/%.c, $(OBJECT_DIR)/%.o, $(MY_FILES))
...
$(MY_OBJ): $(OBJECT_DIR)/%.o: $(SOURCE_DIR)/%.c
$(CC) $(CFLAGS) -o $# $<
But my question is this:
Why in this case does adding the directory prefix in the rule itself result in nothing being built, while in version A of my makefile the first target was successfully made?
"Version A" fails because make is just expanding things like you asked it to. A variable reference like this:
$(OBJECT_DIR)/$(MAIN_OBJ): ...
says "expand the variable OBJECT_DIR, then add a "/", then expand the variable MAIN_OBJ". So you get:
$(OBJECT_DIR)/$(MAIN_1) $(MAIN_2) $(MAIN_3) $(MAIN_4): ...
So, only the first one is actually prefixed by the OBJECT_DIR value, not all of them (since you didn't show what the values were for all these variables I didn't complete the expansion).
Secondly, make always builds just the first target that it finds in the makefile (unless you override that with the command line or .DEFAULT). You don't say what the "non-relevant rules" are that you omitted, but unless one of them was an all target or similar that depends on all the MAIN_* targets, make will only build the first one which is the behavior you saw.
ETA Prepending to all words is trivial using various methods; see the GNU make manual.
One option:
$(addprefix $(OBJECT_DIR)/,$(MAIN_OBJ)): ...
Another option:
$(MAIN_OBJ:%=$(OBJECT_DIR)/%): ...
Another option:
$(patsubst %,$(OBJECT_DIR)/%,$(MAIN_OBJ)): ...
I am trying to wrap my head around pattern rules and how they function. I am using this article for reference which states
A pattern rule is a concise way of specifying a rule for many files at
once. The rule will depend on the file names, but usually it depends
on them in a simple way. You specify a pattern by using the %
wildcard. When present in the dependency list, % matches any string of
any length; when present in the list of targets, % stands for the
string that % in the dependency list matched.
The following pattern rule will take any .c file and compile it into a
.o file:
%.o: %.c $(CC) $(CFLAGS) $(INCLUDES) -c $(input) -o $(output)
(This assumes that you have the variables CC, CFLAGS, and INCLUDES
defined to be something suitable. Makepp will guess a value for CC and
CFLAGS.)
The first line of the rule says that it applies to every possible
input file that matches the pattern %.c. These .c files can be
transformed into the corresponding .o file using the specified
actions.
The action of rule is quite similar to the other actions we've seen
previously, except that it uses automatic variables. An automatic
variable is a variable whose value is automatically set by makepp
depending on the rule that it appears in. Some useful automatic
variables are:
$(input)
The name of the first input file. In this rule, this would be the file that matches the %.c pattern. $(dependency) is a synonymn for $(input). In older makefiles, you will also see the cryptic symbol $< used as well.
$(output)
The name of the first output file. In this rule, this would be the file that matches the %.o pattern. $(target) and $# are synonymns.
$(inputs)
The name of all explicitly listed input files. In this case, since there is only one, $(inputs) is equivalent to $(input). $(dependencies) and $^ are synonymns.
$(outputs)
The name of all explicitly listed targets. In this case, since there is only one, $(outputs) is equivalent to $(output). $(targets) is a synonymn for $(outputs).
Here are the questions that I have:
1 ) Suppose I have 2 files FileA.c and FileB.c. When I apply the above mentioned pattern rule how would that apply to the above two files. The example given only deals with one file.
2) Whats the difference between the automatic variable input and inputs
A pattern rule will be applied to each target file that matches the rule that make needs to build.
So if you need to build both FileA.o and FileB.o (because they are both listed as prerequisites of some other target (e.g. FileBin: FileA.o FileB.o) that rule will be run twice, once for each.
Take the rule
FileBin: FileA.o FileB.o
#echo '$$input = $(input)'
#echo '$$inputs = $(inputs)'
When run that would output
$input = FileA.o
$inputs = FileA.o FileB.o
It should also be pointed out that input and output are makepp variable names and not valid for GNU make itself.
A makefile generates a file from another via an intermediate and automatically deletes the intermediate file:
.INTERMEDIATE $(B_FILES)
%.b : %.a
a_to_b $<
%.c : %.b
b_to_c $<
all: $(A_FILES)
The above is a simplified example - it produces a .c file and deletes the intermediate .b file. It's possible to produce and keep the intermediate .b file if made specifically:
$ make my_file.b
However, by adding a rule to produce the intermediate files:
b_files: $(B_FILES)
it's possible to make all of the intermediate files:
$ make b_files
However make deletes the .b files after it makes them because they are listed as intermediate. Is it possible to prevent make from deleting them when this specific target is used?
I think the answer would require redefining .INTERMEDIATE in the b_files rule but I am not sure if it is possible to redefine a target within a specific rule.
Try using .PRECIOUS or .SECONDARY instead as described here. If you need to do this conditionally you can use MAKECMDGOALS to check for special target:
ifeq ($(MAKECMDGOALS),b_files)
.SECONDARY: $(B_FILES)
endif
A common type of makefile has a line like this:
OBJS=something.o other.o third.o progname.o
progname: $(OBJS)
Then you would run make progname. But GNU Make can also generate the list of o-files itself from all the c-files it sees in the current directory. How is this done?
Basically, I want to be able to add C files to the directory without having to change the makefile.
(Is it for instance through some shell-magic, or is there is a built-in function for this?)
It can also be done like this:
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
progname: $(OBJS)
Which works just fine if the object file with main() in it is "progname.o".
To view all the defined rules (include the implicit ones), issue make -p.
However the fact that make knows how to generate object files from source files, does not mean that it should do this. Make will try to do the bare minimum in order to satisfy the target you ask it to build.
If you want make to compile all the sources into object in the current directory you will need a rule that will depend on all the objects, e.g.:
all: $(patsubst %.c,%.o,$(wildcard *.c))
You can expand a shell command to give you a list of files. You can also use implicit rules.
It can be done like this:
$(ODIR)/%.o: %.cpp
$(CC) -c $(CFLAGS) -o $# $<
make generates .o file names from .cpp file names it found in the current directory.