Makefile: count updated object-files - c

Hey is it possible to count all updated files when running make again?
I have a rule $(NAME) which is dependent on my Object files which I compile with the rule %.o : %.c
So f.e. when my project is already compiled and I change only some files make will only recompile these files and now I need to find a way of counting all these changed .c files. Does make have such a feature or is there some workaround?
I need the amount of changed files before I compile not after (which wouldn't be a problem).

Related

Compile each file from file list in Make

The problem is the following. I have a list of .c files in several directories that I wish to compile, one by one, into a .o file, located at BUILD_DIR folder, to be later linked. They are appended to the SOURCE_FILES_FREERTOS variable. The Makefile code section that attempts to perform this is:
OBJ_FILES_FREERTOS = $(SOURCE_FILES_FREERTOS:%.c=$(BUILD_DIR)/%.o)
# Build the Operating System Library
freertos: ${OBJ_FILES_FREERTOS}
${BUILD_DIR}/%.o : $(dir ${SOURCE_FILES_FREERTOS})/%.c
-mkdir -p ${BUILD_DIR}
$(CC) $(CFLAGS) ${INCLUDE_DIRS} -MMD -c $< -o $#
However, it does not work, saying there is no rule fore the first target file:
make: *** No rule to make target 'build/../../../FreeRTOS/Source/stream_buffer.o', needed by 'freertos'. Stop.
What seems to be the problem?
From a top-down perspective we first declare the objects to be part of the library:
OBJECT_FILES_FREERTOS := $(patsubst ...)
libfreertos.a: $(OBJECT_FILES_FREERTOS)
I cannot create OBJECT_FILES_FREERTOS from the variables in the question. You'd have to add more to it or figure it out yourself. Below I assume that all object files have $(BUILD_DIR)/-prefix and the same directory structure as the source it is derived from (which is a pain since Make does not create necessary directory hierarchy for you, but that's just how Make rolls).
Make now tries build object files from source files. By default searching for source files in the same directory as where the object files are expected to be. This is where it becomes tricky, since the source files (from looking at your error) is not in the source tree, making a relative path to god knows where. You need a different source-to-object map, here using static rules:
$(OBJECT_FILES_FREERTOS): $(BUILD_DIR)/%.o: $(FREERTOS_SRC_DIR)/%.c
No rule to make target means it cannot find a rule to build the file, most often because the source file is missing and Make does not know how to build it from nothing.
freertos has a dependency on build/../../../FreeRTOS/Source/stream_buffer.o but you don't have any rules that cover that file. This is your root cause for the build failure.
The pattern rule suggest you are putting the object files in $(BUILD_DIR) and not 3 levels up from it. This means that the pattern rule doesn't apply in this case.

How do you indicate relative (or absolute) path for pattern rule in makefile? and How do you detect included headers from a source file?

We can add pattern rules such as %.c or %.o which mimics *.c or *.o in bash (it searches for all files that have extension .c or .o. This is very useful if you have several targets, so you don't have to write all rules. I would like to know how to use this trick if your target files (.c or .o) are in the previous directory. In bash, one can write ../*.c, but ../%.c does not work in makefile as I tested. How do you do such thing in makefile?
My second question: sometimes one would like to add header dependencies like this:
HEADER=factorial.h
%.o: %.c $(HEADERS)
gcc -o program $%
It is a good idea to add a header dependency because sometimes you don't know whether or not the included libraries have some change.
Here we have to manually type the file names for HEADER.
How do I make it so it can scan the target file's included headers?
For example: my main.c has #include "dog.h"
How do I make it so it detects main.c has included dog.h.

what does the "makefile" mean in the Makefile "kaodv.o: $(KOBJS) Makefile"

I have a makefile. In the file there are some words :
kaodv.o: $(KOBJS) Makefile
$(LD) -r $(KOBJS) -o $#
I do not known the "makefile" mean in these words. Can some body help me?
That is listing the makefile as a prerequisite for the kaodv.o object file.
So that if the makefile changes the object file will be rebuilt. This is the same as how the files in $(KOBJS) (which is a slightly odd name for that variable in this context) means.
This is likely an attempt to get kaodv.o to rebuild for flag changes made to the makefile. This will do that but will also recompile for any other changes. Unfortunately a more fine-grained flags-only approach requires a bit more work.
It means that execute the rules for building kaodv.o if Makefile has changed.
This is there, most likely, to make sure that if compiler flags in Makefile are changed, the .o file is rebuilt.

Makefile use of $<

Can anyone explain why the use of $< in:
$(BUILD_DIR)/release/%.o: %.c $(HEADERS)
$(RELEASE_LINK.c) $< -c -o $#
iterates over both the .o files and .c files in pairs building an obj file from a c file, whereas $< in:
$(program_C_OBJS) : $(program_C_SRCS)
$(RELEASE_LINK.c) $< -c -o $#
iterates over all the obj files but only ever pulls out the 1st dependency, i.e. the 1st c file
Is it possible in the 2nd example to modify such that the matching pairs of obj and c files are built as happens in the 1st example?
The $< variable doesn't "iterate" anything. It doesn't do anything but expand to the name of the first prerequisite of the target it is expanded in.
The first rule is a pattern rule. It applies to any files that need to be built that match that pattern.
The second rule (which almost certainly doesn't do anything even remotely like what you want unless those variables contain patterns) maps specific output files to specific input files (in your case presumably the limited set of input C files you want the rule to apply to).
The choice about what files get compiled during any given make run is determined by what files make is told to build and which of their dependencies make determines need to be updated to make that happen.
From GNU Make - 10.5.3 Automatic Variables
$<
The name of the first prerequisite. If the target got its recipe from an implicit rule, this will be the first prerequisite added by the implicit rule
Depending on what you want to accomplish, there is also
$?
The names of all the prerequisites that are newer than the target, with spaces between them.
$^
The names of all the prerequisites, with spaces between them
You can build a specific set of objects by stating them as dependencies to another target
target1: $(program_C_OBJS)
Now, when you call
make target1
make tries to create the dependencies for target1, which in turn can be built using your first rule, one by one. Of course, you can specify a command for target1 as well. This command will be executed as soon as its dependencies $(program_C_OBJS) are built.

Updating source files to different folder using makefile in Linux

I have a Linux GNU C project that requires building output for two different hardware devices, using a common C source code base, but different makefiles. Presently I have two makefiles in the same folder, one for each device, and when I make a change to the code, I have to first do "make clean" to make the first model, then "make clean" to make the second model. This is because they use different compilers and processors. Even if a code file didn't change, I have to recompile it for the other device.
What I would like to do is use a different folder for the second model, so it stores a separate copy of *.d and *.o files. I would not have to "make clean", only recompile the changed sources. I have looked at makefile syntax, and being new to Linux, can only scratch my head at the cryptic nature of this stuff.
One method I'm considering would update the .c & .h files from model_1 folder into model_2 folder. Can someone provide me with a simple makefile that will copy only newer *.c and *.h files from one folder to another?
Alternatively, there must be a way to have a common source folder, and separate output folders, so duplicated source files are not required. Any help to achieve that is appreciated. I can provide the makefiles if you want to look at them.
You want to generated files (object and dependencies) put into a separate folder for each build type as it compiles. Here's what I had do that may work for you:
$(PRODUCT1_OBJDIR)/%.o $(PRODUCT1_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT1_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT1_OBJDIR)/$*.o
$(PRODUCT2_OBJDIR)/%.o $(PRODUCT2_OBJDIR)/%.d: %.cpp
#mkdir -p $(#D)
$(CXX) $(PRODUCT2_DEPSFLAGS) $(CXXFLAGS) $(INCLUDE_DIR) $< -o $(PRODUCT2_OBJDIR)/$*.o
$PRODUCT1_OBJDIR and $PRODUCT2_OBJDIR are variables names for the directory where you wish to have the generated files stored. This will check for changes to dependencies and recompile if needed.
If you still have problems, get back with feedback, will try and sort you out.
You could compile your source files to object files in different directories ("folder" is not really the appropriate word on Unix). You just have to set appropriate make rules. And you might use other builders like omake, scons, ...
You could use remake to debug your GNU Makefile-s. You could have inside a rule like
$(OBJDIR)/%.o: $(SRCDIR)/%.c
$(COMPILE.c) -c $^ -o $#
And you could set (earlier in your Makefile) variables with e.g.
OBJDIR:=obj-$(shell uname -m)
or something better
I do suggest to read GNU make's manual; it has an introduction to makefiles.
This can be easily achieved with makepp's repository mechanism. If you call makepp -R../src ARCH=whatever then it will symbolically link all parts of ../src under the current directory and compile here.
You can even create a file .makepprc and put in any options specific to this architecture, so you'll never get confused which command to call where.
If your different architectures have identically produced files (like generated sources), you can even build in ../src and the other architecture will pick up everything that doesn't depend on your current compile options.
There is much more to makepp. Besides doing almost all that GNU make can, there are lots more useful things, and you can even extend your makefiles with some Perl programming.

Resources