Makefile use of $< - c

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.

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.

Source and Include for MakeFile in C

I am taking a Coursera course and I am totally stuck in one of the project. Project demands us to create a makefile but I could not.
Here is my files and folders:
project
|---include
|---CMSIS
|---cmsis_gcc.h
|---core_cm4.h
|---core_cmFunc.h
|---core_cmInstr.h
|---ore_cmSimd.h
|------common
|---memory.h
|---platform.h
|------msp432
|---cmsis_gcc.h
|---msp_compatibility.h
|---syste_msp432.h
|---src
|---interr.c
|---main.c
|---memory.c
|---str.h
|---system_msp.h
|---makefile
|---msp432p401r.lds
|---sources.mk
Here is my sources.mk and makefile.
For now, I just want to check whether makefile succesfully find related source and include files but it does not.
I have checked several example makefiles and could not find where is the fault of mine? What I have got here is:
What I understand from error is it can not find related memory.h file. What can I do?
Any help will be appreciated.
Thanks.
Make searches for prerequisites in the working directory. It doesn't know that you have memory.h somewhere else, and will not go looking for without instructions.
One way to solve this is with the vpath directive:
vpath %.h common
You can use the same trick when you run into problems finding other prerequisites:
vpath %h common CMSIS
vpath %.c src
That will get echo "HI" to work, but you will have more trouble with a real rule that actually uses the prerequisites. To take a contrived example:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) memory.c -o memory.o
This will fail because although Make can find the prerequisites, the compiler still doesn't know where they are.
We tell the compiler where memory.c is by referring it to the list of prerequisites:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) $< -o memory.o
($< means the first prerequisite; Make will provide the path.) We could use the same trick (with some effort) to tell the compiler where to search for the header file, but it's usually simpler to put that in by hand:
memory.o: memory.c memory.h
$(CC) -c $(CFLAGS) -Icommon $< -o memory.o
It's important to understand that make and the compiler are two completely different programs, that do different things and work different ways. Make can run a compiler, but it can also do all sorts of other things: it could build documentation, or an entire website, or copy files, etc. Basically make is a general-purpose tool that can investigate when files are out of date and run any command you give it to make that file "up to date", whatever that may mean.
So, when you create a variable like INCLUDES = -I... that is setting a make variable to a flag that can tell the compiler where your header files are.
That means nothing to make.
Make sees this rule:
ysk: memory.h memory.c
and says "ok to build the file ysk I need to have memory.h and memory.c". It looks in the current directory and those files don't exist (because they are in src/memory.h and src/memory.c) so it fails.
You need to put the paths into your makefile, so make can find them.

Automatic variable not expanding properly in Makefile

I am using the following code:
HELLO_WORLD=hello
$(HELLO_WORLD): $(addsuffix .c,$#)
gcc $< -o $#
However, when I run the code, I receive the following error, implying that $< is not evaluating to anything:
gcc -o hello
gcc: fatal error: no input files
When I use the following code...
HELLO_WORLD=hello
$(HELLO_WORLD): $(addsuffix .c,$#)
gcc $(addsuffix .c,$#) -o $#
...the Makefile evaluates to the following command...
gcc hello.c -o hello
...which is precisely what I would like. However, I do not want to use addsuffix twice. I would like to use $< in the event that I change the prerequisite. How would I go about doing this?
The problem is not with the expansion of $< in the recipe. The problem is the expansion of $# in the prerequisite list.
Automatic variables, such as $#, are only defined in the recipe, not in the target or prerequisite lists. This is highlighted in the GNU Make manual section on automatic variables:
A common mistake is attempting to use $# within the prerequisites list; this will not work.
The fact that hello.c is not actually in the prerequisite list does not prevent you from invoking make hello. It just means that make hello will always invoke the compiler, even if hello.c has not been modified. But it does mean the $< will be as empty as the computed prerequisite list.
GNU make does have a feature to let you do a second expansion of prerequisites; this is explained in the manual. But the simpler solution is to simply not rely on $# in the prerequisite list. If you're trying to create your own generic C compile recipe, use a pattern rule for object file (.o) targets. For the final executable, list all the prerequisites for the final executable (which will almost certainly be more than one file).
Typically this is done using separate variable with names like SRCS and OBJS (or SOURCES and OBJECTS if you don't mind typing vowels). Normally you make the object files prerequisites for the final executable (which will be a link operation), since each individual source file will have its own header prerequisites.
The fundamental problem is automatic variables are only defined in the recipe. So, in the prerequisite, $# is not defined. Because $< will refer to an expression that depends on $#, which does not exist, $< will therefore not exist as well.
So, there are really two ways to resolve the issue. The first way is a bit clunky, but you can use secondary expansions. This essentially allows us to do what we want without adding much code...
HELLO_WORLD=hello
SECONDEXPANSION:
$(HELLO_WORLD): $(addsuffix .c,$$#)
gcc $< -o $#
The more proper way to do this involves restructuring the Makefile and using pattern rules. This gives us a generic recipe for building any C file. With the following Makefile, we can either run "make" or "make hello" to build the executable.
HELLO_WORLD=hello
all:
$(MAKE) $(HELLO_WORLD)
%: %.c
gcc $< -o $#

How does Redis Makefile include header file prerequisites

I was teaching myself GNU Make and thought a look at the Redis Makefile would teach me a thing or two about the tool.
The rule that compiles the source file to the object file is here:
%.o: %.c .make-prerequisites
$(REDIS_CC) -c $<
Notice that the suffix rule just mentions the C source file (with %.c) as a prerequisite.
But if I add a echo in the middle and run make:
%.o: %.c .make-prerequisites
echo $^
$(REDIS_CC) -c $<
Then the first few lines of the output from make is like below:
cd src && make all
make[1]: Entering directory `/home/cltpadmin/code/redis/src'
echo adlist.c .make-prerequisites adlist.h zmalloc.h
adlist.c .make-prerequisites adlist.h zmalloc.h
CC adlist.o
How did make know that adlist.c depends on adlist.h and zmalloc.h?
The prerequisites in question come from line one of the Makefile.dep included makefile (included on line 134).
The dep target on line 136 generates that file.
This was a fairly common (though entirely avoidable) step for using the compiler to generate the necessary header file includes. This static method also has issues with conditional header includes I believe.
To clarify, the "avoidable" part of this is that it need not be a separate step and a static dependency file at all. See Advanced Auto-Dependency Generation for details about this idea.

Makefile with multiple submodules

I have following program structure:
main.c
Makefile
Submodule
--{somefiles}
--Makefile
Submodule is creating library submodule.a. It has many source files and it need some libraries.
All I want to know that
Makefile in submodule knows how to make submodule.a
Makefile in submodule sets variable SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS
How can I write Makefile in root project directory that:
it would create submodule.a using Makefile in submodule
it would add SUBMODULE_LDFLAGS and SUBMODULE_LDLIBS to its own variable?
AT the end I want the following command in main Makefile works correctly:
TARGET = MyProgram
OBJS = $(TARGET).o submodule/submodule.a
$(TARGET): $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) $^ -o $# $(LDLIBS)
Now it creates MyProgram.o and cannot create MyProgram, because Makefile doesn't know how to make submodule/submodule.a.
I can add lines:
submodule/submodule.a:
make -C submodule
but it won't help me with missing libraries.
There is no direct way for the sub-Make to pass variables to the parent process. There are (at least) two indirect ways.
You could have the sub-Make write a file containing the variable values, which the parent Make could then read.
You could copy the part of submodule/Makefile that constructs those variables, and put it into Makefile. Better still, you could isolate that code in a separate file that both makefiles would then include.
EDIT:
One disadvantage of recursive Make is that it interrupts much of Make's dependency handling. In this case, there's no clean way to have the sub-make run when and only when one of the library's sources is changed.
You can put the list of submodule sources -- or the code that constructs the list -- in a separate file which both makefiles will include. Then those files can be among the prerequisites of $(TARGET).
Or, you could make submodule/submodule.a a PHONY target. In that case, Make will rebuild the binary every time, but otherwise it'll work perfectly.

Resources