makefile concepts - gcc

can anyoone help me.
this is the code for make file
i'm just trying to save different objective files at different directories is that possible?
in the below code.
OBJECTS = objj/mall.o objj/fall.o
BACK = kajj/ball.o kajj/call.o
DIR = objj kajj rajj
execc/gola : $(OBJECTS) $(BACK)
gcc $^ -o $#
$(OBJECTS):objj/%.o:%.c
mkdir $(DIR)
gcc -c $< -o $#
$(BACK) : kajj/%.o
i want to save the mall.o fall.o in objj and ball.o and call.o in kajj i'm stucked up here i dont know how to cotinue further can anyone help me if we use %.o:%.c it replaces all obj files one on one but how to seperate them. and anyone please tell me what these line really does $(OBJECTS):objj/%.o:%.c.im unable to understand we can have only one colon in our line but here we have two im confused help me out guys

For the two column rules, consider what is before the first as the actual targets, and what is after the first column as a pattern rule.
Thus, to compile the objects in kajj, you could replace your last rule by:
$(BACK): kajj/%.o: %.c
mkdir $(DIR)
gcc -c $< -o $#

Related

GNU make generate assembly first, them compile them to .o and link

SOURCE=a.c b.c c.c
ASM=$(patsubst %.c,%.s, $(SOURCE))
all:%.o
gcc -o test $^
$(ASM):%.c
gcc -S -o $# $<
%.o:%.s
gcc -c -o$# $<
I want to generate assembly code (.s) first, then compile the assembly code to object (.o), then link them.
But it seems above makefile code does not work. What is the correct code?
When asking questions, does not work is never very useful... if it worked you probably wouldn't be asking a question! :-) Instead you should always show the command you ran and the output you received (or at least the failing part of the output if it's long). Please cut and paste the actual text rather than paraphrasing messages. Also, including the version of the make program you're using (make --version) and the platform you're running on is often helpful.
Luckily this time we can figure out the problem without this information:
This:
$(ASM):%.c
gcc -S -o $# $<
where ASM is a.s b.s c.s, is not a pattern rule because the targets don't contain a pattern character %. That means the prerequisite %.c is not treated as a pattern, but as an actual file name, literally %.c which obviously doesn't exist.
Similarly, this:
all: %.o
has the same problem: all is a target, so this depends on the literal file named %.o which doesn't exist, and can't be created.
Also as a general rule every recipe that creates a target must create the actual target you told make it would, so this all rule is wrong because the target name is all but the recipe creates the target test.
Finally, it's a very bad idea to name your program test because test is a common UNIX program and a shell built-in, so if you run test it won't do the right thing (if you run ./test it will work).
You want to have all depend on the program you want to build, say mytest, and mytest should depend on the actual .o files:
all: mytest
mytest: $(SOURCE:.c=.o)
gcc -o $# $^
Next, you need to define a pattern rule that knows how to create an assembly file from a source file:
%.s : %.c
gcc -S -o $# $<
That, along with your other pattern rules, is all you need: make will figure it all out from that.
Finally, make has a built-in rule that tells it how to build object files directly from source files. It's best to get rid of this to force make to use your rules; add this to your makefile to delete it:
%.o : %.c

order rule execution in parallel make without introducing dependencies

I have a project that consists a single target that requires ~30 files of type A, that are handled by one pattern rule, and one different target of type B, that is independent of the other 30. Here's some pseudo-code to show what I have, in a very simplified form:
OBJECTS=obj/obj1.o obj/obj2.o ...
SPECIAL=special/specialobj.o
libMyLibrary.so: $(OBJECTS) $(SPECIAL)
g++ -shared -o $# $^
obj/%.o: src/%.cxx
g++ -c -fPIC -o $# $^
$(SPECIAL): special/mySpecialCode.cxx
g++ -c -fPIC -o $# $^ -DFANCY_FLAG
The makefile works fine, and the dependency resolution is flawless. However, somehow, make always decides to build $(SPECIAL) last. While this doesn't matter at all, as it works either way, the compilation of $(SPECIAL) takes significantly longer than anything else in my case, almost as long as all other objects combined. Hence, it would be nice if one could encourage make to start with compiling $(SPECIAL), so that it can be compiled in parallel along the others, which would cut compile time dramatically.
Is it possible to achieve such a thing?
PS: I can live with non-portable versions, as the code is a very dedicated piece of software that will only be compiled and run on a very particular set of machines, the setup of which I know pretty well at development time.
EDIT
Following up on a comment made me realise that in the case I have shown here, the problem can indeed be solved by simply swapping the order $(OBJECTS) $(SPECIAL) to $(SPECIAL) $(OBJECTS) - sometimes, it's that simple.
However, in my actual usecase, this does not work, so I have built an MWE that (1) actually works (with gnumake) and is (2) a little bit closer to how things actually work in my project.
Here, the file that takes so long to compile actually depends on a source file that is only generated in an additional step. You can observe the change in order by swapping the two lines following the comment.
If somebody can provide a way how to fix the behavior also for this case, that would be great!
If it's not possible to change the order to the desired one in this case, I will accept any answer that explains to some details why it's impossible.
OBJECTS=obj/obj1.o obj/obj2.o obj/obj3.o obj/obj4.o obj/obj5.o
SPECIAL=special/specialobj.o
SPECIALSRC=special/mySpecialCode.cxx
OBJ_DIR=obj
SPECIAL_DIR=special
all: libMyLibrary
$(SPECIAL_DIR):
mkdir -p $#
$(OBJ_DIR):
mkdir -p $#
libMyLibrary: $(SPECIAL) $(OBJECTS)
cat $^ > $#
obj/%.o: | $(OBJ_DIR)
#echo creating $#
#echo $# > $#
$(SPECIALSRC): | $(SPECIAL_DIR)
#echo special > $#
# swap the following two lines to observe the change in ordering
# $(SPECIAL): $(SPECIALSRC) | $(SPECIAL_DIR)
$(SPECIAL): | $(SPECIAL_DIR)
#echo starting special
#echo special > $#
#sleep 1s
#echo special done
clean:
rm -rf libMyLibrary $(OBJ_DIR) $(SPECIAL_DIR)

Makefile separate directories

It really takes a long time to read the make and gcc manual. Since I just need some basic function of them, I want to learn them quickly.
The project directory is like the following.
CWD
|----Source----1.cpp
|----Header----1.h
|----Object----1.o
|----Makefile
There are three directories and one Makefile in Current Working Directories, and "1.cpp" includes "1.h". I want to use Makefile which is in the CWD to compile the project such that the object output is in Object directory.
This is simplified version of the problem I have now. Since it is relatively hard to begin from scratch, could anyone help me to write a Makefile for this simple problem? And I will try to learn from it and solve my own problem. Or could anyone suggests which parts of make and gcc I need to learn to solve this problem.
Thanks in advance.
This will be enough to compile the source and produce the object:
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c Source/1.cpp -IHeader -o Object/1.o
If you want to build an executable, maybe called "one", add another rule above that:
one: Object/1.o
$(CXX) Object/1.o -o one
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c Source/1.cpp -IHeader -o Object/1.o
To clean things up a little, use automatic variables:
one: Object/1.o
$(CXX) $^ -o $#
Object/1.o: Source/1.cpp Header/1.h
$(CXX) -c $< -IHeader -o $#
And if you want to make the second rule more general, so that it can handle more objects you can turn the second rule into a pattern rule and separate the header dependency of 1.o:
one: Object/1.o
$(CXX) $^ -o $#
Object/1.o: Header/1.h
Object/%.o: Source/%.cpp
$(CXX) -c $< -IHeader -o $#
And of course there is a lot more you can do, when you're ready.

separate builds in separate directories

I'm sure this is a totally normal thing to do, but I can't figure out how to get make to do this.
I have a compiler that generates make dependencies of the usual form:
M/A.o : M/A.hs
M/B.o : M/A.o
So I write a rule to compile %.hs into %.o, add a rule to link the binary, include the dependencies file, and all is well. But I want to have several binary targets with different flags. E.g. I want build/test built with -DTESTING and build/profile built with -prof. So I need to keep the .o files in a separate tree, where they will be compiled with special flags.
The straightforward way I can think of would be to have dependencies that look something like this:
build/test/M/A.o : M/A.hs
build/test/M/B.o : build/test/M/A.o
build/profile/M/A.o : M/A.hs
... etc.
And then rules so that %.hs to build/test/%.o compiles with -DTESTING, etc. I think this would work, but it's clumsy, means preprocessing the deps file to add all that build/whatever/ prefix stuff, and would multiply its size by however many kinds of builds.
VPATH appears to be designed for this sort of thing and my idea was that I could set the VPATH and compiler flags depending on the target, and it almost works, but:
%.o: %.hs
#mkdir -p build/M
cp $< build/$#
VPATH = build
main: M/A.o M/B.o
cat $^ >$#
M/A.o : M/A.hs
M/B.o : M/B.hs
The first time the main target wants to run 'cat M/A.o M/B.o >main' which seems contrary to the gnu make documentation that says $^ should include the include the VPATH directory in which the dependency was found. Curiously, if I remove 'main' and make again, this time it uses the correct path. This is GNU make, 3.81.
What's going on here? Is there a better way to build with different flags? VPATH seems like a clumsy tool, surely there is a better way?
Make is working correctly. It tries cat M/A.o M/B.o >main the first time because it can't find the prerequisites it needs, but it knows a rule for M/A.o' andM/B.o(<em>not</em>build/M/A.o' and build/M/B.o) and expects that that is what the rule will produce. If you remove main and try again, it will find build/M/A.o' andbuild/M/B.o` via VPATH.
Let's modify this makefile in stages. First we change the VPATH so that it can find the .hs files (Make is good at using things there to build things here, not vise-versa, and that's what VPATH is good for), and change the rules slightly:
build/%.o: %.hs
cp $< $#
VPATH = M
main: build/A.o build/B.o
cat $^ > $#
Now for the different object directories.
build/test/%.o build/project/%.o: %.hs
cp $< $#
VPATH = M
test: build/test/A.o build/test/B.o
cat $^ > $#
project: build/project/A.o build/project/B.o
cat $^ > $#
Then we simplify those last two rules, so that it's easy to add more object files and binary targets:
OBJECTS = A.o B.o
test: $(addprefix build/test/,$(OBJECTS))
project: $(addprefix build/project/,$(OBJECTS))
test project:
cat $^ > $#
Now for the different compiler flags:
build/test/%.o: FLAGS += test_flags
build/project/%.o: FLAGS += proj_flags
build/test/%.o build/project/%.o: %.hs
#echo building $# from $^ using flags $(FLAGS)
cp $< $#
Finally the dependencies. This is a little tricky. Suppose you want the dependency B.o : A.hs to apply to however many object you have. This is one approach:
OBJECT_PATHS = build/test/ build/project/
# The following is from the included file generated by the compiler
$(addsuffix B.o,$(OBJECT_PATHS)) : A.hs
To generate lines like that, I'd pipe the raw lines (e.g. B.o: A.hs) through sed 's/\(.*\):\(.*\)/\1:\2/', and note that if you want to put this in a makefile command, don't forget to double the $ signs to preserve them for the shell.
I know that's a lot to absorb. Take it one step at a time and let us know how it works out.
If you haven't solved your problem by now or are experiencing further problems, best give the autotools (automake and autoconf) a chance. They'll quickly build you a Makefile that supports more configurable and flexible out-of-tree builds.

How to add different rules for specific files?

I have a certain problem with my Makefile.
With this command, I can compile all my *.c files to *.o which works well:
$(OBJ) : %.o : %.c $(LDSCRIPT) Makefile
$(CC) $(ARM9_INCLUDES) -c $(CFLAGS) $< -o $#
But now I'm wondering, what if I want to run -O3 optimization on just ONE particular file, and have -O0 on the rest?
Is there any command to add a different rule for a specific file?
What I'm doing right now is compiling each C file with its own rules, which is very annoying because I have around 30 files which makes the Makefile huge, and every time I change something in one file it compiles EVERYTHING again.
particular_file.o : CFLAGS+=-O3
(assuming GNU make) see target-specific variable values in GNU Make manual
(and the immediately following pattern-specific variable values, maybe).
Also note, that commands are used from the most specific rule for given file, so you can have in case target-specific variable value is not sufficient:
particular_file.o : particular_file.c
completely_special_compiler -o $# $<
%.o : %.c
$(CC) $(CFLAGS) -o $# $<
It's possible to make the solution a bit more extensible.
Suppose you need to compile one set of files in one way and the other set of files in another way, rather than having only one exception, and you could identify patterns in those two sets of files, e.g. one set starts with "a", and the other set starts with "b", you can do something like this:
a%.o : a%.c
completely_special_compiler -o $# $<
b%.o : b%.c
$(CC) $(CFLAGS) -o $# $<
For more explanation, see Static Patterns.

Resources