What is purpose of TARGET_ARCH variable in Makefiles - makefile

I have noticed that in Implicit Rules in Gnu Make is variable $(TARGET_ARCH) for example :
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $#
LINK.o = $(CC) $(LDFLAGS) $(TARGET_ARCH)
I supposed that this variable is needed for cross compilation, but I haven't found any information about it in Gnu Make documentation.

I agree that it's probably meant for cross-compilation.
The variable TARGET_ARCH has no default value - it's there for end-users to define as they see fit.

Related

difference while adding static libraries in make file

my question is i am confused while adding a static library in my makefile which one is correct both the styles are giving different outputs and seems like correct one is 2nd style and how?
ABS_LIB= -L/home/saravind/work/Pinnacle_DEVIMPT_Sprint26/GeoPlugins/AtlasSegmentationPlugin/AbsEngine/lib/SunOS -lAbsInterface
my_unittest : Image_unittest.o gtest-all.o gtest_main.o
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ABS_LIB) $^ -o $#
and
my_unittest : Image_unittest.o gtest-all.o gtest_main.o
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $^ -o $# $(ABS_LIB)
The second one is correct, because the -l options must be at the end of the gcc command line.
By the way, instead of using the custom ABS_LIB variable, you may want to use the LDLIBS and LDFLAGS make variables.

Add dependencies to existing make targets

Condition 0:
Say, I have several source codes, a.c, b.c, ..., z.c, and I want a rule to have each of them compiled. Here is a solution:
%.o: %.c
$(CC) -c -o $# $(CFLAGS) $<
Condition 1:
Then I introduce a header c.h used in c.c, and another header e.h used in c.c and e.c, and things become complex:
%.o: %.c
$(CC) -c -o $# $(CFLAGS) $<
c.o: c.c c.h e.h
$(CC) -c -o $# $(CFLAGS) $<
e.o: e.c e.h
$(CC) -c -o $# $(CFLAGS) $<
My question:
Based on the solution of condition 1, is there something like add_dependency in make to simplify the solution and obtain something like the following one?
%.o: %.c
$(CC) -c -o $# $(CFLAGS) $<
add_dependency(c.o, c.h e.h)
add_dependency(e.o, e.h)
Or, what do you think is a better solution to condition 1?
EDITED:
Thanks for the kind notice #ctheo :)
Yes I did have a look at autotools and understood that shall satisfy all my needs. However what I'm dealing with is an existing project and its Makefile contains other directives dealing with codes in C++, and I think for now I'd better just modify a few lines instead of port the whole Makefile to autotools, unless I couldn't find a satisfying solution without introducing autotools. :)
At first I did not expected to exist a solution for this. It seemed to me that it was covered by autotools. However, after some search, I found this section of GNU/make manual.
It states that :
One file can be the target of several rules. All the prerequisites mentioned in all the rules are merged into one list of prerequisites for the target.
So there is a solution for your query
c.o: c.h e.h
e.o: e.h
%.o: %.c
$(CC) -c -o $# $(CFLAGS) $<
Thanks for insisting. I learned something today :)
In addition, the .o files in your example all depend on a .h file with the same stem, so you can generalise that part of your rules too:
c.o: e.h
%.o: %.c %.h
$(CC) -c -o $# $(CFLAGS) $<
This way, your “normal” situations are covered entirely by the rule that triggers compilation and your “unusual” situations stand out because those are the only additional rules.

Difference of two pattern rules and integration on makefile

I'm learning makefile and I'm little bit confused about the use of pattern rule and how to use it:
I have two questions:
difference form of pattern rules
In some examples I saw this form:
.c.o:
$(CC) $(CFLAGS) $< -o $#
Other times I saw this:
%.o: %.c
$(CC) $(CFLAGS) $< -o $#
Is this the same form or there are many differences?
How to integrate the pattern rule in my makefile
I have a makefile like this:
.PHONY: all brsserver brsclient clean
CC = gcc
CFLAGS = -Wall -pedantic -g -lpthread
# source files for server
SOURCES_SERV = brsserver.c func_client_serv.c comsock.c bris.c users.c aux_func.c Stack.c
# source files for client
SOURCES_CLI = brsclient.c func_client_serv.c comsock.c bris.c users.c aux_func.c Stack.c
# object file for server
OBJECTS_SERV = $(SOURCES_SERV:.c = .o)
# object file for client
OBJECTS_CLI = $(SOURCES_SERV:.c = .o)
# executable file server
SERV_EXE = brsserver
# executable file client
CLI_EXE = brsclient
I did this:
$(SERV_EXE): $(OBJECTS_SERV)
$(CC) $(CFLAGS) -o $# $^ newDeck.o
$(CLI_EXE): $(OBJECTS_CLI)
$(CC) $(CFLAGS) -o $# $^
But I want to use the pattern rule to do make brsserver and make brsclient from command.
it's enough do this?
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
As you can see, I have to complie only the brsserver including a module called newDeck.o.
The .c.o form is a suffix rule. This form is defined in the POSIX standard for the make program.
The %.o : %.c is a pattern rule. This is a GNU make feature, not part of the POSIX standard (I think there may be a few other make implementations that have something similar).
In this case, they are equivalent. However pattern rules in general are much more flexible than suffix rules; for example you can't represent a pattern rule like this:
foo%.o : bar%.c
as a suffix rule.

make, write a rule for single file

I need a file to have a dedicated rule for use special flags.
Now I use
$(OBJDIR)/%.$(OE): special_file.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(CFLAGS_SPECIAL) $(DEFINES) $(INCLUDE) $< -o $#
$(OBJDIR)/%.$(OE): %.c $(OBJDIR)
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDE) $< -o $#
But isn't working for special_file.c. It seems the path is not known, but when I comment my special rule and let make all files, file is compiling fine.
How to divert make to a rule just for one file?
Thanks very much in advance,
You should use Target-specific Variable Values:
$(OBJDIR)/special_file.$(OE): CFLAGS += --specific_flags
$(OBJDIR)/special_file.$(OE): special_file.c
$(OBJDIR)/%.$(OE): %.c $(OBJDIR)
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDE) $< -o $#
If you want to do it this way, you'll have to write it as a static rule:
$(OBJDIR)/special_file.$(OE): special_file.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $(CFLAGS_SPECIAL) $(DEFINES) $(INCLUDE) $< -o $#
However, much simpler and more flexible is to use recursive variable naming. Do something like this:
special_file_FLAGS = $(CFLAGS_SPECIAL)
$(OBJDIR)/%.$(OE): %.c
$(ECHO) "Compiling file $< => $#"
$(CC) $(CFLAGS) $($*_FLAGS) $(DEFINES) $(INCLUDE) $< -o $#
The automatic variable $* expands to the stem (the part that matches %). Now when you build anything other than special_file.c, say other_file.c, make will expand $(other_file_FLAGS) which is empty. When you build special_file.c, make will expand $(special_file_FLAGS).
BTW, you should (almost) never list a directory as a prerequisite of a target. Search for other answers to find out why not and the right way to ensure the target directory is created.
ETA:
Target-specific variables are definitely a cool feature. I tend to not use them, though. Why? Because I prefer to separate my data from my rules.
If you use target-specific variables, you are mixing together the rule syntax (the target) with the data syntax (the variable assignment). Using the recursive variable name method, I keep the rule syntax and the data assignment separate. What if I decide I need to change my pattern rule so that the target name changes? With target-specific variables I have to go through all my files and change the target names. With recursive variable naming, I just change the pattern rule and it Just Works.
In my build environments I typically have makefiles containing only data (variable assignments), plus an include of a common makefile that declares all my rules. Avoiding the need to leak target formatting syntax all over my general data-driven makefiles, escaping from my uber-magical common rule definitions, keeps me from doing much with target-specific variables.

How do I write a clean Makefile?

The Makefiles that I have dealt with, for the most part, are complex and hide a lot of relationships. I have never written one myself, and was wondering if anybody had some tips on writing a Makefile that is easy to read and reusable?
I usually use something like this, in this example the source files are main.c file2.c file3.c file4.c, to add more you simply add to the OBJECTS var.
They all depend on Makefile, so for a full recompile a simple touch Makefile would suffice.
PROGNAME = hi2u
LIBS = -ljpeg -ldirectfb -pthread
INCLUDES = -I/usr/local/include/directfb
LDFLAGS = -Llibs/
OBJECTS = main.o file2.o \
file3.o file4.o
CFLAGS = -W -Wall -O2 -ggdb
all: $(PROGNAME)
$(PROGNAME): $(OBJECTS)
gcc -o $(PROGNAME) $(OBJECTS) $(LIBS) $(INCLUDES) $(LDFLAGS)
$(OBJECTS): Makefile
.c.o:
gcc -c $(CFLAGS) $(INCLUDES) -o $# $<
clean:
rm *.o $(PROGNAME)
In all honesty, the complexity of a makefile relies on the complexity of the program. If you have a lot of folders and files and different compiling processes, you're makefile is probably going to be a little long and complicated. If you have a helloworld program, there's no reason for it to be longer than a few lines.
Here's some tips on makefiles : http://mrbook.org/tutorials/make/
Here's a very reusable makefile that's not too complicated:
CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $#
.cpp.o:
$(CC) $(CFLAGS) $< -o $#
A tutorial that I've found helpful for understanding Makefiles is http://www.jfranken.de/homepages/johannes/vortraege/make_inhalt.en.html
Another tip is to make generous use of regular expressions for source files and dependencies
For me, the read that got me thinking about these issues, is the classic "Recursive Make Considered Harmful".
When I get the chance to create makefiles from scratch, I try to use implicit rules as much as possible, and also define rules in a separate file, which I can include from the "real" makefile.
The challenges with using make can be divided in two major groups:
issues inherent with make itself, its rich semantics and syntax and somewhat archaic appearance
issues which are not makes "fault", but come from when make is used to call another make process. Suddenly we have another task at hand - communicating between two or more make processes. It is very easy to get lost with environment variables or other ways to pass information. Platform differences which make itself is designed to hide, may become visible.

Resources