Writing compilation rule before linking rule in makefile doesn't produce executable [duplicate] - makefile

My makefile have two lines:
Rule_1
File.o : File.cpp
g++ -c File.cpp -o File.o
Rule_2
File : File.o
g++ File.o -o File
I want any change in File.cpp leads to regeneration of both File.o and File. This is done by:
Makfile:
Rule_2
Rule_1
But the following does not work and only regenerates File.o
Rule_1
Rule_2
Why? I note that, I am not using any all: in my makefile. With all: File both methods above work.

I assume your make tool is GNU Make.
Unless you specify targets on the commandline, like:
make File
make will by default attempt to make the first target
in the makefile, which in your problem case is File.o.
See How make Processes a Makefile
When you add:
all: File
at the top, all is the first target, which depends on File,
which in turn depends on File.o.
And I suggest you replace that with:
.PHONY: all
all: File
See Phony targets

Related

'make: nothing to be done for p1 and' no rule to make target 'clean''

I'm trying to create a makefile titled 'p1' for a project.
When I try the command make p1 it returns with make: nothing to be done for p1
Also, when I try the command make p1 clean it returns no rule to make p1 'clean.' Stop
Here is my makefile:
a.out: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o const_iterator.o iterator.o Node.o
main.o:
g++ -std=c++11 -c main.cpp
P1LinkedList.o:
g++ -std=c++11 -c P1LinkedList.cpp
iterator.o:
g++ -std=c++11 -c iterator.cpp
const_iterator.o:
g++ -std=c++11 -c const_iterator.cpp
Node.o:
g++ -std=c++11 -c Node.cpp
depend:
g++ -MM main.cpp > p1.dep
clean:
rm -f a.out *.o
What do I need to fix to have the makefile compile .o files from my .cpp files and how do I fix the issue with the clean command?
Edit:
Here are the commands I've used to compile manually:
Helens-Air:p1a helenade$ g++ -std=c++11 *.cpp
Helens-Air:p1a helenade$ ./a.out
^^ and this just continues with the program execution from there
We may have to take this in stages.
First, you seem to misunderstand the difference between a makefile name and a target name. This appears to have been a miscommunication between you and your teacher, but it's easy to clear up.
Suppose you have a makefile named "Makefile", containing the following:
foo:
#echo running the foo rule
bar:
#echo running the bar rule
If you make foo, you will get:
running the foo rule
The argument (foo) tells Make which target to attempt to build. And how did Make know which makefile to use? (After all, you could have a dozen makefiles in the working directory.) You can specify which makefile to use, but if you don't then by default Make will look for a makefile named Makefile (or makefile or GNUmakefile, don't worry about this for now). To specify a makefile with another name, like "Buildfile", you can use the -f flag:
make -f Buildfile
So "p1" ought to have been the name of a target, not a makefile. Within the makefile, rename your a.out rule to p1. Then rename the whole makefile to Makefile. Then
make p1
should work (or at least run).
Edit:
I'll go out on a limb. In the a.out rule (which should now be called the p1 rule), I notice that you have left P1LinkedList.o out of the list of object files to be linked. So try changing it:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 main.o P1LinkedList.o const_iterator.o iterator.o Node.o
If that works, you can simplify it with an automatic variable:
p1: main.o P1LinkedList.o const_iterator.o iterator.o Node.o
g++ -std=c++11 $^
And there will be other small improvements you can make.
If it doesn't work, try ls *.cpp and see if you've overlooked some other source file.

How to create a makefile that will place object code in different folder

I am very new to Makefile. I had build the following makefile(Which don't work).I wan't put genarated object codes in differnt folder(the folder is in current directory).
$ ls
main.cpp Makefile object_code Time.cpp Time_.h
how can I do this ??
VER = Debug
CC = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CC) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
clean:
rm $(OBJECTFIELS) main
this is error.
$ make
g++ ./object_code/main.o ./object_code/Time.o -o ../Debug/main
g++: error: ./object_code/main.o: No such file or directory
g++: error: ./object_code/Time.o: No such file or directory
g++: fatal error: no input files
compilation terminated.
Makefile:8: recipe for target '../Debug/main' failed
make: *** [../Debug/main] Error 1
please this is last question.
I don't see how you can possibly get that output given the makefile you've posted here.
Either the object files already exist in which case the link will succeed rather than printing that error.
Or the object files don't exist in which case make will complain because it doesn't know how to make them. There must be some difference between the makefile you're using and the one you've posted here.
In any event, make knows how to build a file foo.o from a file foo.cpp for any string foo. There's a built-in rule that tells it how to do that.
But, make doesn't know how to build a file ./object_code/foo.o from a file foo.cpp, regardless of foo. There's no built-in rule that tells make how to build object files in some random other directory. If you want make to do that, you'll have to tell it how. You should remove the lines:
./object_code/main.o: main.cpp
./object_code/Time.o: Time.cpp
and replace them with a pattern rule describing how to build object files into the object_code directory (I'm using CXX as the compiler variable here: by convention CC is the C compiler and CXX is the C++ compiler, and you should always stick with convention unless there's a good reason not to):
VER = Debug
CXX = g++
OBJECTFIELS = ./object_code/main.o ./object_code/Time.o
../$(VER)/main: $(OBJECTFIELS)
$(CXX) $(OBJECTFIELS) -o $#
$(OBJECTFIELS): Time_.h
./object_code/%.o : %.cpp
$(CXX) -c -o $# $<
clean:
rm $(OBJECTFIELS) main

C Makefile - recompile only changed files

Hello I have a shared library libnsd.so (made up of nsd.c,nsd.h,nd.c,nd.h) linked to main file.
My question is how to write the makefile so that it recompiles only those source files that have been changed.
I have read some topics about this but got somewhat confused, I'm a beginner programmer.
My makefile code so far:
CC=gcc
all : lib alll
alll : main.c
$(CC) main.c -o main -L. libnsd.so
lib : nsd.c nsd.h nd.c nd.h
$(CC) -c -fPIC nsd.c -o nsd.o
$(CC) -c -fPIC nd.c -o nd.o
$(CC) -shared -Wl,-soname,libnsd.so -o libnsd.so nsd.o nd.o
clean:
rm main libnsd.so nd.o nsd.o
Makefiles have the concept of build targets. The build targets are, really, all the intermediate as well as the final files and, by the way they are written, they can be made to use dependencies.
A sample solution for your makefile:
CC=gcc
all: main
main: main.c libnsd.so
$(CC) main.c -o main -L. libnsd.so
libnsd.so: nsd.o nd.o
$(CC) -shared -Wl,-soname,libnsd.so -o libnsd.so $#
%.o: %.c nsd.h nd.h
$(CC) -c -fPIC $< -o $#
A few things to note:
You should properly correct my dependencies on the object file creation (since I consider that each of the C files depends on both of the headers).
You may wish to note the wildcard construction I have used...
If there was nothing special with some of these commands I could have left default commands work. Do note that I have used $< for the first dependency and $# for the output in the wildcard rule.
I haven't copied the clean rule, since it was written correctly in the question itself.
Each of the targets (besides the "phony" target all) creates a file with the same name: The target libnsd.so creates a file with the name libnsd.so. The target main creates a file with the name main.
As a dependency of a target changes date so that the dependency is newer than the output, make will recreate the target, as well as other targets that depend on it. But if you have a target that is not mapped to any output file, that target is always called (in our code, the all target is always called but thankfully it has no commands and it depends only on actual files which may or may not need being recreated)
Do note that GNU Make doesn't need to have compiling in particular. The creation of an output file can happen by any means, and indeed I have seen a target create a .cpio.gz archive. But if that archive is older than any of the dependencies (the folder it would pack in) then it would be recreated, according to make.

What is the importance of target in makefile?

I am learning how to create makefile on a Linux distro.
I am using the following code (I know it can be written in a small form, but the long form is intentional) to properly understand the behavior of makefile
test: test.o
cc -o test test.o
test.o: test.c
cc -c test.c
clean:
rm test.o
Now, when I use make and make clean in the shell, they are working as intended.
However, I want to know the importance of target in makefile. Hence, started by changing test.o: test.c line to test2.o: test.c and typed make in the shell; my initial guess was that there would be a file in my home directory called test2.o, but that's not the case, I still see test.o being created again.
So, the above behavior begs my question, what is the important of target component in makefile?
The 'target' is the file which Make checks to determine whether it needs to execute the commands associated with the target at all.
I.e. if you change test.o: test.c to test2.o: test.c, Make sees that test2.o does not exist and hence executes the command cc -c test.c -- which still only creates test.o. Hence, if you re-run make, you will see that the compiler is executed again because test.o still does not exist.
In the original version, test.o: test.c, the compiler will only be executed if test.o does not exist, or if the modification time of test.c is newer than that of test.o.
The target becomes available in the commands section as a variable $#, which can be used to define what gets built.
In your makefile you had:
test2.o: test.c
cc -c test.c
Because you didn't tell the compiler what the output would be as part of the cc command, it created test.o from test.c, which is the default behaviour. If you run cc -c file.c it will generate file.o by default.
You need to specify the destination file as part of the commands run for generating the target, so:
test2.o: test.c
cc -c test.c -o $#
Would cause the compiler to generate the test2.o file appropriately.
At a fundamental level, a makefile is nothing more that a set of targets, dependencies for the targets and the sets of commands for making those targets. You have to ensure that as part of the build process, the final product from a set of commands is the target in order to have a properly functioning makefile.
The compiler doesn't know anything about the fact that it's being run in the makefile.
There are a bunch of automatic rules, pre-created by the default make system. These include rules for making .o files from .c files - it knows that it needs to compile a file using the following rule and commands:
%.o: %.c
# commands to execute (built-in):
$(COMPILE.c) $(OUTPUT_OPTION) $<
where COMPILE.c:
COMPILE.c = $(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
and OUTPUT_OPTION is:
OUTPUT_OPTION = -o $#
CC defaults to cc, CFLAGS defaults to empty, CPPFLAGS defaults to empty and TARGET_ARCH defaults to empty. You can see these definitions using make -p
So the resulting command is:
cc -c -o $# $<
Where $# is the name of the target and $< is the first item in the list of dependencies. This pattern matches all target files called <something>.o where there is an existing file called <something>.c. If there's a request to build test.o as a target then it will compile a file called test.c, because that file exists and matches these rules.
tl;dr
Your test2.o rule is never executed. test.o is created by make's implicit rule.
Let's take this apart.
test.o: test.c
cc -c test.c
This is a rule.
The general syntax for a rule is:
targets : prerequisites
recipee
So, test.o is the target, and test.c the prerequisite.
If:
the target (file) does not exist, or
(one of) the prerequisite(s) is newer than the target,
the recipee is executed (which should, but does not have to, create the target).
So, let's look at your Makefile:
test: test.o
cc -o test test.o
test.o: test.c
cc -c test.c
When you say make test, you want to create the target test. This target has test.o as prerequisite.
For test.o exists another rule, with test.c as prerequisite. So that rule gets checked and executed first (compiling your source to object code), before the test prerequisite is checked, and the recipee run if required (linking your object code to executable format).
Hence, started by changing test.o: test.c line to test2.o: test.c and typed make in the shell; my initial guess was that there would be a file in my home directory called test2.o, but that's not the case, I still see test.o being created again.
No target has a test2.o prerequisite, and you did not ask for that to be build specifically (make test2.o), so the recipee for test2.o is never executed.
But test still has test.o as a prerequisite. As there is no explicit rule for a target of that name in your Makefile, make substitutes it with its implicit rule for creating a .o file from an existing .c file...
The default output file from cc -c test.c is test.o. If you want it to create test2.o, you need to tell it explicitly:
test2.o: test.c
cc -o test2.o -c test.c
cc doesn't know anything about the makefile or what target it's being run from.
The importance of targets is that they're used for finding all the dependencies. So the first rule in your makefile says that test is dependent on test.o: before you can create test, you first need to create test.o, and if test.o has changed, you need to rebuild test.
The commands below the target are expected to do whatever it takes to create the target. But you have to code that explicitly (although there are some macros that can automatically substitute targets and dependencies into the command line -- these are mostly useful when the target contains a wildcard pattern).

make is calling g++ is always re-compiles even when I do not change the source code

I am using make which calls g++ always re-compiles the code, even when I do not change the source code. That happens for all my projects, even for simple ones such as:
[code]
all: main.cpp
g++ -std=c++11 -c main.cpp
[/code]
I believe it should compare the date/time on source and object code. Could some help me with this, I am running using GNU toolchain on Ubuntu 12.04
THX
Edit: sorry guys, I do use Makefile, I edited my question accordingly.
Simplest Makefile
It was already pointed out that your Makefile is probably wrong. The 'all' target is indeed always built (although it may result in a no-op if it has no commands and all dependencies are already satisfied). All you need in your makefile is this:
all: main
Object files
If you expect to have more source file in your build, you should consider creating intermediate object files:
all: main
main: main.o
Tweak the build
Make will automatically find the main.ccp file and turn it into main which is required per the directive above. You can use special make variables to further tweak the compilation, e.g. for debug information inclusion and for warning configuration:
CXXFLAGS = -g -Wall -Werror
all: main
main: main.o
Nitpicking
If you insist on building up the compile rule yourself, you can do it like this:
%.o: %.hpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# -c $<
CXX: C++ compiler
CPPFLAGS: C preprocessor flags
CXXFLAGS: C++ compiler flags
$#: Target
$<: First dependency
If you don't want to use the standard variables nor pattern matching, you can build up the whole makefile explicitly:
all: main
main: main.o
gcc -o $# $^
main.o: main.c
gcc -g -Wall -Werror -o $# -c $<
$^: Use that one if you want to include all dependencies, for example if you have multiple *.o files to build one binary.
Note: It is a bad idea to write the file names directly into the command as you might forget to update them later.
all: main.cpp
g++ -std=c++11 -c main.cpp
This seems wrong. Why does the rule for all has main.cpp as its target? Shouldn't it be something.exe or something.o? Say
all: main.exe
main.exe: main.cpp
g++ -std=c++11 main.cpp -o main.exe
clean:
del main.exe
Targets are output files and cpp files are source code which should be input to the make system.
g++ would have to "recompile" in general (what happens if you change the header but not main.cpp?)
If you are concerned about long build times, you should use something like Make (which is designed specifically to avoid recompiling when the source hasn't changed)
The compiler will always compile the code. If you want to do conditional compilation (based on file times etc) you will need to use a make system such as Make, CMake, Ant, etc. For the simplest you can set up a small "Makefile" in the directory and use the command "make" to build.
Simple Makefile for compiling "myapp.exe" from "main.cpp", "file1.cpp" and "file2.cpp"
myapp.exe: main.o file1.o file2.o
g++ -o myapp.exe main.o file1.o file2.o
(make knows to use .cpp files to build .o files)
But if you also have header files, then you will need to build dependency chains, for which you may want to look into something more sophisticated like automake, cmake, ant, etc.
---- EDIT ----
Based on your updated post, the problem is that you aren't specifying a target, so Make has to assume it needs to recompile. See my example in the above answer.

Resources