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

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

Related

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

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

make don't build file even if dependency is updated

this is my make file:-
VER = Debug
CC = g++
OBJECTFIELS = main.o Time.o
main: $(OBJECTFIELS)
$(CC) $(OBJECTFIELS) -o $#
$(OBJECTFILES): Time_.h
clean:
rm $(OBJECTFIELS) main
every time I change the Time_.h file, nothing happens:-
$ make
make: 'main' is up to date.
$ touch Time_.h
$ make
make: 'main' is up to date.
other files compile when changed :-
$ touch main.o
$ make
g++ main.o Time.o -o main
please I am complete noob. Please tell why is this happening
You need to generate new .o files in your rule for Time_.h.
$(OBJECTFILES): Time_.h
This says make should run a command whenever Time_.h is updated, and that the command will generate both main.o and Time.o. But no command is given!
Time.o: Time_.h
$(CC) Time_.cpp -o Time.o
This is the kind of rule you want. Whenever Time_.h changes, we run $(CC) Time_.cpp -o Time.o, which will generate Time.o. Now if some other rule depends on Time.o, make will know that this command can be used to create Time.o, but that it only needs to be run if Time_.h changed since the last time make was run.
I'm specifying "Time.o" explicitly, since your source filenames don't seem to exactly match the object files you're expecting. (Time.o vs Time_.o)

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).

Switching from g++ to clang++ in makefile

I 've got following makefile:
all: xmltest
xmltest: xmltest.cpp tinyxml2.cpp tinyxml2.h
This works fine - after executing make all executable 'xmltest' is produced.
However, I want to switch compiler to clang++. So I've added this line at the beginning of the file:
CXX=clang++
and now executing make all produces an error:
clang++ xmltest.cpp tinyxml2.cpp tinyxml2.h -o xmltest
clang++.exe: warning: treating 'c-header' input as 'c++-header' when in C++ mode, this behavior is deprecated
clang++.exe: error: cannot specify -o when generating multiple output files
<builtin>: recipe for target 'xmltest' failed
make: *** [xmltest] Error 1
How to fix this with minimal modifications to original make file?
You might as well just write a shell script: there's no advantage to using the makefile in your solution. Any time you change any file, the entire thing will be rebuilt, so you might as well just run:
clang++ -g -o xmltest xmltest.cpp tinyxml2.cpp
whenever you change anything and skip the makefile.
If you wanted a makefile which took advantage of some of the capabilities of make, you would write it something like this:
CXX = clang++
all: xmltest
xmltest: xmltest.o tinyxml2.o
xmltest.o tinyxml2.o: tinyxml2.h
Now you have something useful, where only the files that need to be rebuilt based on what you've changed will be rebuilt. If your program gets more complex, you can use even more make facilities to keep it manageable.
You shouldn't list the header file as a translation unit (those are the cpps)
You should usually make the .h prerequisites:
xmltest.cpp: tinyxml2.h
tinyxml2.cpp: tinyxml2.h
And compile/link the translation units:
all: xmltest
xmltest: xmltest.cpp tinyxml2.cpp
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
IIRC you /might/ also put the 'dependency only' items on the same line using |
xmltest: xmltest.cpp tinyxml2.cpp | tinyxml2.h
$(CXX) $(CXXFLAGS) -o $# $^ $(LDFLAGS)
But I'm unable to check that right now

Gcc error only when using makefile (CreateProcess: No such file or directory)

I am having trouble compiling using make in windows 7 with gcc and the gsl library. It occurs only when using make (when I type the compilation commands manually into the cmd line, it compiles correctly). I found some posts where people had similar errors from gcc, but none where it worked when typing normally, but not when using make. The contents of my Makefile are shown below:
#Compiler
COMP=gcc
# Compiler Flags. -Wall turns on all warnings
FLAGS=-Wall
# GSL include file dir
INCLUDES=GnuWin32/include
# GSL Libraries directory
LIB=GnuWin32/lib
# Library Flags
LFLAGS=-lgsl -lgslcblas -lm
# Target Program
EXE=ex2.1.exe
# Dependencies needed for $(PROGRAM)
OBJ=ex2.1.o
# List of source files for objects
SRC=ex2.1.c
# List with types of files to be cleared by clean:
TRASH=*.exe *.o
# I/O files to be cleaned with 'very clean' target
#IOFILES= *.dat *.out *.csv *.mod
all: $(SRC) $(EXE)
$(EXE): $(OBJ)
$(COMP) -L/$(LIB) $(OBJ) $(LFLAGS) -o $(EXE)
$(OBJ): $(SRC)
$(COMP) -I/GnuWin32/include -c ex2.1.c
#$(COMP) -I/$(INCLUDES) -c $(SRC)
clean:
del $(TRASH)
If I type make with only the ex2.1.c present in the directory, I get the following output and error:
gcc -I/GnuWin32/include -c ex2.1.c
gcc: error: CreateProcess : No such file or directory
make: *** [ex2.1.o] Error 1
However, if I first type "gcc -I/GnuWiun32/include -c ex2.1.c", ex2.1.o is created successfully with no error. If then type 'make' I get the following output/error:
gcc -L/GnuWin32/lib ex2.1.o -lgsl -lgslcblas -lm -o ex2.1.exe
gcc: fatal error: -fuse-linker-plugin, but liblto_plugin-0.dll not found
compilation terminated
make: *** [ex2.1.exe] Error 1
But if I manually enter "gcc -L/GnuWin32/lib ex2.1.o -lgsl -lgslcblas -lm -o ex2.1.exe" then the executable compiles and runs like it should, so the problem seems to be with how make is calling gcc? My PATH variable contains the paths to both make.exe as well as gcc.exe, so I am not sure what I do not set up correctly. Does anyone have an idea of what may be wrong? Thanks.

Resources