Adding dependency on a non-compiled file in a Makefile - c++

I have the following code generation scheme:
The original file is *.c.macro
It is processed by a special program that generates the *.c file. The program uses external XML files mentioned in the original .c.macro file. Somthing along this line:
macroprocess foo.c.macro -o foo.c
Then the *.c file is compiled to *.o normally
What I want to do is to make the .c file dependant on the XML files. So that if the XML changes, macroprocessing is automatically redone when 'make' command is invoked.
I can modify the code of the macroprocessor so that it would generate a list of all XMLs and write it somewhere, but I have no idea how to incorporate it into a makefile. Apparently I would need to play with 'include' command in the makefile, but usually it's employed to add dependencies on actual code like .h files.

If you can get your macroprocess to write a dependency file (e.g. *.xmldep) for each *.c.macro file you can do:
-include $(C_MACRO:.c.macro=.xmldep)
where $(C_MACRO) is a variable that contains your *.c.macro files.
The - in front will ensure that the first time, the make will not fail when it cannot locate the dependency files.

You can add foo.xml as a dependency of foo.c and use a filter command to get only the %.c.macro file as arguments for macroprocess.
Something like this:
# Basic targets
all: foo
foo: foo.o
gcc -o $# $^
foo.o: foo.c
gcc -o $# -c $<
# Special target with filter
foo.c: foo.c.macro
macroprocess -o $# $(filter %.c.macro,#^)
# Adding foo.xml as a dependency of foo.c
foo.c: foo.xml
.PHONY: all foo

Related

Please explain this Makefile - executable rule appears to be missing

I have this makefile which I don't understand.
build_sources:=$(wildcard *.cpp)
depends:=$(build_sources:.cpp=.d)
build_targets:=$(build_sources:.cpp=)
.PHONY: all
all: $(build_targets)
.PHONY: clean
clean:
rm -f $(build_targets) *.{a,o,d}
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
-include $(depends)
I understand that the executables created are build_target. So if I have Foo.cpp and Bar.cpp, the executables created would be Foo and Bar.
But how does it do that? I only see 1 rule, and it is %.d: %.cpp. So it's saying the Foo.d file depends on Foo.cpp. But what about the rule to actually compile Foo?
This makefile works, so it's not actually missing anything. But how come I don't see the rule? Is there some implicit rule?
EDIT - i did make debug, and saw the following
No need to remake target `foo.d'.
Considering target file `foo'.
File `foo' does not exist.
Looking for an implicit rule for `foo'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.o'.
Found an implicit rule for `foo'. ## WHAT EXACTLY IS THIS?
Considering target file `foo.o'.
File `foo.o' does not exist.
Looking for an implicit rule for `foo.o'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.c'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cc'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.C'.
Trying pattern rule with stem `foo'.
Trying implicit prerequisite `foo.cpp'.
Found an implicit rule for `foo.o'.
Pruning file `foo.cpp'.
Pruning file `foo.cpp'.
Finished prerequisites of target file `foo.o'.
Must remake target `foo.o'.
g++ -I../../include -Wall -std=c++11 -O3 -Wsign-compare -Wno-strict-aliasing -s -c -o foo.o foo.cpp
That's great. This must be the rule that's getting called. But where is this rule from? How do I know what default rules exist?
What you probably miss to understand this Makefile is the concept of pattern rule and automatic variables.
This part finds .cpp files:
build_sources:=$(wildcard *.cpp)
And this part creates targets with the same name (using the variable build_sources defined above) except the extension is replaced by .d:
depends:=$(build_sources:.cpp=.d)
The same kind of construction defines the build targets (same file name with extension removed):
build_targets:=$(build_sources:.cpp=)
Then the default target is defined to require build_targets, i.e the executable corresponding to the .cpp`
all: $(build_targets)
This rule defines how to build a .d from a .cpp:
#build the list of header file dependencies automatically
%.d: %.cpp
#echo building include dependencies for $(*F)
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; } > $#
gcc -MM produce rules to know on which headers a .c or .cpp file depend. Typically if test.cpp includes test1.h and test2.h the output will be:
test.o: test.cpp test1.h test2.h
The .d will contain dependencies of each cpp file and will create a ruleto build a .o file and an executable from each cpp. $# is the target of the rule (the .d file) and will contain, unless I'm mistaken, a rule looking like this (written by the sed expression):
filename.o filename.d : filename.cpp <list of headers>
%.h:;
The first rule give dependencies of the .o files. It has no recipe which means it simply adds dependencies to any existing rule. An implicit rule will be used to build them.
The second one is here in case you suppress a header. In this case, make will use this rule that says that there's simply nothing to do (it has an empty recipe).
Then all the .d files are included as part of the makefile:
-include $(depends)
Finally, the implicit rule to link a single .o file kicks in:
Linking a single object file
n is made automatically from n.o by running the linker (usually called ld) via the C compiler. The precise recipe used is ‘$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)’.
Edit: To build objects in a subdirectory obj you would have to modify each filename:
depends:=$(foreach file,$(build_sources:.cpp=.d),"obj/$(file)")
To build binaries in a separate subdirectory bin you would need to do the same for build_targets:
build_targets:=$(foreach file,$(build_sources:.cpp=), "bin/$(file)")
Then you need to write the rule to build it because the default rule wont work anymore (the .o is not in the same directory). What you want is to add a rule like this:
bin/foo: obj/foo.o
$(CC) $(LDFLAGS) obj/foo.o $(LOADLIBES) $(LDLIBS) -o bin/foo
which can be done with the right modification of the long shell command:
#$(CXX) -MM $(CPPFLAGS) $< | { sed 's#\($*\)\.o[ :]*#\1.o $# : #g' ; echo "%.h:;" ; obj=`echo $< | sed 's/.cpp/.o/'` ; bin=`echo $< | sed 's/.cpp//'` ; echo "$bin: $obj" ; echo -e "\t\$(CC) \$(LDFLAGS) $obj \$(LOADLIBES) \$(LDLIBS) -o $bin" ; } > $#
Your make package includes a large number of default rules, which this Makefile depends on. Try running your make with -d (debug info). I believe that will show you everything that is in play.
Many rules are built in to Make. If you are using GNU Make, you can get it to print its built-in rules like this:
make -f /dev/null -p
You can make it ignore the built-in rules with -r; if you do this with your Makefile, you'll find that it complains that it doesn't know how to make your targets.
The makefile is't complete in itself. It automatically creates the files .d which are snippets included into that makefile at the end. These files are created with the %.d-rule.
So have a look at those generated .d files to see rules for each individual object file. The rule generation script is written with sed and kind of hard to read, but in fact very simple. At first, the compiler is invoked on the .cpp file with the -MM flag, which will output something like
foo.o: foo.cpp foo.h bar.h
if foo.cpp includes its own header file foo.h as well as bar.h, for example (directly or indirectly).
The sed regex replacement command now simply adds the name of the file, in which the generated rules are about to be written (the .d file) right after the .o in the above rule, so it is also marked as depending on the sources, just like the object file. That's important when the includes in one of the sources is changed later. The sed command also adds a rule for all header files to do nothing.
foo.o foo.d: foo.cpp foo.h bar.h
%.h:;
The resulting object files .o are then linked using one of the implicit rules:
Linking a single object file
n is made automatically from n.o by
running the linker (usually called ld) via the C compiler. The precise
recipe used is $(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS).
[...]

Makefile syntax using -o and -c in c++

It's been a while since I've done a makefile. I have inherited some code that is built with the following line in a makefile
$(CC) $(FLAGS) -c -o $*.o $*.cpp
Why would you use -c and -o in the same line. Doesn't the -c make it so that you build the objects without linking?
EDIT Here is the complete makefile, now I get an error saying cpp.cpp No such file or directory
.SUFFIXES: .o .cpp
CC=g++
MAIN_OBJS = \
main.o \
f1.o \
f2.o \
all:
$(CC) -c -o $*.o $*.cpp
$(CC) $(MAIN_OBJS) -o final
Shouldn't the $*.cpp find all the .cpp files in my current path (and they are there)
As you say, -c means make object files without linking.
-o means you want to override the default output file name and specify your own. So -o $.o means the output file name would be the same as the input file name but with .o on the end.
You might do this if you were planning to have this Makefile rule usable with a number of different compilers, some of which might have a different default output file name for object files.
The man page for gcc describes -o like this:
-o file
Place output in file file. This applies regardless to whatever sort of output is being produced, whether it be an executable file, an
object file, an assembler file or preprocessed C code. If -o is not
specified, the default is to put an executable file in a.out, the
object file for source.suffix in source.o, its assembler file in
source.s, a precompiled header file in source.suffix.gch, and all
preprocessed C source on standard output.
Yes, what you said makes sense.
As we know,-c will compile the source files and produce the assembly files.
After that, we normally use -o to link all those assembly files and produce a executable file.
What follows -o is the name of the output executable file.
And if the -c and -o are used in the same line, it means the output assembly file produced by -c is named what follows -o.

Example makefile for building simple c project recompiling when headers change

Does anyone have a complete makefile that can do the following:
Rebuilds the project if a HEADER file changes
The cpp files are listed in the makefile
The header files are NOT listed in the makefile
The header files are allowed to have different names than the cpp files
Some of the cpp files do not have header files
I have seen instructions for figuring out how to make the make tool figure out header dependencies, but none of these instructions provide anything remotely resembling a working example. A simple example would be as follows: main.cpp C1.cpp C1.h C2.cpp C2.h
CXX = g++
OBJECTS := main.o C1.o C2.o
all: $(OBJECTS)
%.o : %.cpp
$(CXX) $(CPPFLAGS) -Wall -MMD -c $< -o $#
-include *.d
EDIT: As TobySpeight points out, this won't work if you build an object file, rename or delete one of the prerequisite source or header files, then try to rebuild the object file; the .d file will still require the missing file, and the build will fail. I neglected to include lines to deal with that case:
%.h: ;
%.cpp: ;
(This is effective, but crude. The more precise approach is to put some sed commands in the %.o rule, so as to add specific null rules to the .d file, one for each prerequisite, but the sed commands are ugly, and the approach above is good enough for almost all cases.)
You can also use CMake for this. Everything you need to write is:
add_executable (exec main.cpp C1.cpp C2.cpp)

Make file header file dependency

I want to add header file dependency in make file
I written rule
${OBJECTDIR}/%.o: %.cc %.h
gcc $(WarningLevel) $(CFLAGS) $(INCLUDES) -c -o $# $^
but there are two error
One for .cc file which don't have any .h files . It will give no rule to make.
Second one is the object file build by rule give error at linking
file format not recognized; treating as linker script
how can I achieve that ? (source file should be compile if header file is got modified )
First of all, you haven't shown us your link command. Secondly, you shouldn't be using $^ here. $^ expands to a list of all dependencies (here, the .c and the .h), but we only want to compile the .c file. Use $<, which expands only to the name of the first dependency:
${OBJECTDIR}/%.o: %.c %.h
gcc $(WarningLevel) $(CFLAGS) $(INCLUDES) -c -o $# $<
You need to provide a rule for the header file dependency you listed:
%.h:
echo This is my build target for header files.
Make won't actually do anything with the %.h files, but atleast you're telling it to watch for file changes (which then cause the .o files to need recompilation).

GCC dependency generation for a different output directory

I'm using GCC to generate a dependency file, but my build rules put the output into a subdirectory. Is there a way to tell GCC to put my subdirectory prefix in the dependency file it generates for me?
gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
I'm assuming you're using GNU Make and GCC. First add a variable to hold your list of dependency files. Assuming you already have one that lists all our sources:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
Then include the generated dependencies in the makefile:
include $(DEPS)
Then add this pattern rule:
# automatically generate dependency rules
%.d : %.c
$(CC) $(CCFLAGS) -MF"$#" -MG -MM -MP -MT"$#" -MT"$(<:.c=.o)" "$<"
# -MF write the generated dependency rule to a file
# -MG assume missing headers will be generated and don't stop with an error
# -MM generate dependency rule for prerequisite, skipping system headers
# -MP add phony target for each header to prevent errors when header is missing
# -MT add a target to the generated dependency
"$#" is the target (the thing on the left side of the : ), "$<" is the prerequisite (the thing on the right side of the : ). The expression "$(<:.c=.o)" replaces the .c extension with .o.
The trick here is to generate the rule with two targets by adding -MT twice; this makes both the .o file and the .d file depend on the source file and its headers; that way the dependency file gets automatically regenerated whenever any of the corresponding .c or .h files are changed.
The -MG and -MP options keep make from freaking out if a header file is missing.
The answer is in the GCC manual: use the -MT flag.
-MT target
Change the target of the rule emitted by dependency generation. By default CPP takes the name of the main input file, deletes any directory components and any file suffix such as .c, and appends the platform's usual object suffix. The result is the target.
An -MT option will set the target to be exactly the string you specify. If you want multiple targets, you can specify them as a single argument to -MT, or use multiple -MT options.
For example, -MT '$(objpfx)foo.o' might give
$(objpfx)foo.o: foo.c
You may like this briefer version of Don McCaughey's answer:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
Add -include $(DEPS) note the - prefix, which silences errors if the .d files don't yet exist.
There's no need for a separate pattern rule to generate the dependency files. Simply add -MD or -MMD to your normal compilation line, and the .d files get generated at the same time your source files are compiled. For example:
%.o: %.c
gcc $(INCLUDE) -MMD -c $< -o $#
# -MD can be used to generate a dependency output file as a side-effect of the compilation process.
Detailing on DGentry's answer, this has worked well for me:
.depend: $(SOURCES)
$(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend
This also works in the case where there is only one dependency file that contains the dependency rules for all source files.
Ok, just to make sure I've got the question right: I'm assuming you have test.c which includes test.h, and you want to generate subdir/test.d (while not generating subdir/test.o) where subdir/test.d contains
subdir/test.o: test.c test.h
rather than
test.o: test.c test.h
which is what you get right now. Is that right?
I was not able to come up with an easy way to do exactly what you're asking for. However, looking at Dependency Generation Improvements, if you want to create the .d file while you generate the .o file, you can use:
gcc $(INCLUDES) -MMD $(CFLAGS) $(SRC) -o $(SUBDIR)/$(OBJ)
(Given SRC=test.c, SUBDIR=subdir, and OBJ=test.o.) This will create both subdir/test.o and subdir/test.d, where subdir/test.d contains the desired output as above.
If there is an argument to GCC to do this, I don't know what it is. We end up piping the dependency output through sed to rewrite all occurrences of <blah>.o as ${OBJDIR}/<blah>.o.
[GNU] make gets angry if you don't place the output in the current directory. You should really run make from the build directory, and use the VPATH make variable to locate the source code. If you lie to a compiler, sooner or later it will take its revenge.
If you insist on generating your objects and dependencies in some other directory, you need to use the -o argument, as answered by Emile.