Let's say, compiling hello.c requires car.c and water.c.
But main.c requires hello.c.
When I say requires, I mean that the compiled output would differ if the things it requires is modified in any way.
So, if car.c or water.c is changed, then hello.c would need recompiling.
Then, would this be the correct Makefile?
main: main hello.o
gcc main.c hello.c -o main
hello.o: water.c, car.c
gcc water.c car.c -o hello.o
Otherwise, if it's not correct, can someone explain to me why it is wrong and give me an example?
Thank you!
Let's say, compiling hello.c requires car.c and water.c. But main.c requires hello.c.
This statement doesn't make a lot of sense. The only thing it could mean is that either these aren't C or C++ source files, rather some other language that uses these names confusingly, or they contain #include directives that include those other files.
In that latter case (which is rare, and a poor design), there's no need to specify the included files on the command line, since gcc will include them for you. You just need to specify the dependencies in the Makefile:
main: main.c hello.c car.c water.c
gcc -o main main.c
since main.c has #include "hello.c" and hello.c has #include "car.c" and #include "water.c", only the one compile gets everything.
If these are some other language, and you mean something completely different, its likely that gcc can't understand (or compile) them at all...
What you're doing is a little strange, but I guess not incorrect. Don't have a recursive dependency on main and compile hello.o as an object file.
main: main.c hello.o
gcc main.c hello.o -o main
hello.o: hello.c water.c car.c
gcc hello.c water.c car.c -c hello.o
I would re-write it as:
SRC := hello.c main.c water.c
OBJS := $(patsubt %.c,%.o,$(SRC))
main: $(OBJS)
$(CC) -o $# $^
This makefile works because there is an implicit rule for compiling C files. This will mean that when $(OBJS) is expanded to hello.o, main.o, and water.o, each of those .o files will be built by "$(CC) -o hello.o -c hello.c".
Note that if you use the GCC -c flag to only compile the file, but not link it, you will not need to be worried that hello.c relies on car.c and water.c.
EDIT:
Note that in your original makefile, the line "main: main hello.o" is incorrect. A target cannot depend on itself.
In general, with Make, you want to specify dependencies, but not the implementation of making those dependencies, if you can help it. It is much cleaner to say "I need this" versus "do these steps". In a lot of cases, Make is smart enough that if you say "I need this," it will "do the right thing."
In your makefile there are entities of the following type:
final executable program: main
compiled objects (relocatable ELFs linked into the main executable). I can see hello.o, but I cannot find water.o, car.o and main.o (since each *.c compilation unit is generally converted by the compiler to a *.o compiled object).
the source files (compilations units): main.c, hello.c, water.c and car.c. These are used as inputs by the compiler to generate the corresponding *.o files.
So, based on the above, the appropriate Makefile would look like this (tested):
main.o:
gcc -c main.c
hello.o:
gcc -c hello.c
water.o:
gcc -c water.c
car.o:
gcc -c car.c
main: hello.o water.o car.o main.o
gcc hello.o water.o car.o main.o -o main
The shortened versioned, using makefile text functions and automatic variables (tested):
%.o:
gcc -c $(addsuffix .c, $(basename $#))
main: hello.o water.o car.o main.o
gcc $^ -o main
Another approach (tested):
SRC := hello.c water.c car.c main.c
OBJ := $(addsuffix .o, $(basename $(SRC)))
main: $(OBJ)
gcc $^ -o main
Related
I'm trying to run a simple makefile that looks like this:
T=-ansi -pedantic -Wall -Werror
a.out: test.o extra.o
gcc $(T) -c test.o extra.o
test.o: test.c test.h
gcc $(T) -c test.c
extra.o: extra.c extra.h
gcc $(T) -c extra.c
clean:
rm *.o a.out
But I seem to be getting warnings telling me that "linker input file unused because linking not done"
I tried removing the "-c" from the a.out directive, after the gcc, but that produced to give me more problems. I'm not sure how to go about proceeding from here, any ideas/input would be much appreciated.
EDIT: I'm running the program by "make -T", also removing the -c from a.out, causes the error" invalid symbol index"
You need to remove the -c from the a.out command:
a.out: test.o extra.o
gcc $(T) test.o extra.o
or, better:
a.out: test.o extra.o
gcc $(T) -o $# test.o extra.o
or, still better:
extra: test.o extra.o
gcc $(T) -o $# test.o extra.o
The error message is normally because you specify something like -lm on a command line with -c, but you're not doing that here. OTOH, you are listing object files with the -c option — that'll generate the warning:
gcc -ansi -pedantic -Wall -Werror -c test.o extra.o
^ this one, here
Those .o files are the linker inputs, but you're not linking. Drop the -c and you will generate a.out. That should proceed OK.
I think this is the first time I've seen a makefile used to build a.out. It is unusual in the extreme — not precisely wrong, but definitely not the way you normally use make. It has built-in rules to build programs from single source files, such as example from example.c. Normally, you give a program a meaningful name based on one of the source files. Note that creating a program test is usually a bad idea; there is a standard test command built into the typical shell and confusion is rampant.
When compiling a little C or C++ project in terminal using gcc, g++ or make, I get these kind of errors:
/tmp/ccG1caGi.o: In function `main':
main.c:(.text+0xa): undefined reference to `display_menu'
main.c:(.text+0xf): undefined reference to `get_input'
collect2: ld returned 1 exit status
main.c:
#include "menu.h"
int main()
{
display_menu();
get_input();
return 0;
}
menu.h:
void display_menu();
int get_input();
However with Xcode I get no errors or warnings.
What could be the issue here? It's seems it's like this when I include files.
So, gcc is complaining that it doesn't know where display_menu and get_input are, what they are doing or how to link them in, and rightly so.
You probably have more sourcefiles, where those functions are defined (menu.c, perhaps?). If so, add them to your compile instruction:
gcc main.c menu.c
Alternatively, just compile into an object (waiting for the functions later) with the -c flag. This will not make an executable, but will make an object file that awaits final compilation with
gcc main.c -c # Make the main.o object
gcc menu.c main.o # Link the main.o object with a compiled menu.c
into a final executable.
Xcode, in all likelihood, knows all about all your source files, and is happy to put them all together in its compilation step. If you are doing it manually, you have to do a little more work yourself. Its not when you include files (h files, that is) but when you have multi-file sources.
Try with a basic Makefile:
CC=gcc
CFLAGS=-W -Wall
LDFLAGS=
SRC= $(wildcard *.c)
OBJ= $(SRC:.c=.o)
all: myexec
myexec: $(OBJ)
#$(CC) -o $# $^ $(LDFLAGS)
%.o: %.c
#$(CC) -o $# -c $< $(CFLAGS)
.PHONY: clean
clean:
#rm -rf *.o
I tried to make a Makefile using files main.cpp, factorial.cpp, hello.cpp and function.h
On typing 'make' on Linux command window, it shows:
g++ -c -o hello main.o factorial.o hello.o
g++: main.o: linker input file unused because linking not done
g++: factorial.o: linker input file unused because linking not done
g++: hello.o: linker input file unused because linking not done
I am making the Makefile for first time. Please give suggestions what can be the problem?
The Makefile contains following code->
hello: main.o factorial.o hello.o
g++ -c -o hello main.o factorial.o hello.o
main.o: main.cpp
g++ -c -o main.o main.cpp
factorial.o: factorial.cpp
g++ -c -o factorial.o factorial.cpp
hello.o: hello.cpp
g++ -c -o hello.o hello.cpp
The individual file contents if you want to see are:
1) main.cpp
#include<iostream>
#include"functions.h"
using namespace std;
int main()
{
print_hello();
cout << endl;
cout << "The factorial of 5 is " << factorial(5) << endl;
return 0;
}
2) hello.cpp
#include<iostream>
#include "functions.h"
using namespace std;
void print_hello()
{
cout << "Hello World!";
}
3) factorial.cpp
#include "functions.h"
int factorial(int n)
{
if(n!=1)
{
return(n * factorial(n-1));
}
else return 1;
}
4) function.h
void print_hello();
int factorial(int n);
The -c parameter to g++ tells it not to link:
-c Compile or assemble the source files, but do not link. The linking stage simply is not done. The ultimate output is in the form of an object file for each source file.
You definitely don't want the -c here:
hello: main.o factorial.o hello.o
g++ -c -o hello main.o factorial.o hello.o
You could also use rules and patterns to make it more generic:
SRC_DIR = ./src
OBJ_DIR = ./bin/obj
BIN_DIR = ./build/bin
# List all the sources
SRCS = A.cpp B.cpp
# Define the rule to make object file from cpp
$(OBJ_DIR)/%.o : $(SRC_DIR)/%.cpp
g++ -o $# $(INCLUDES) $(CPPFLAGS) -c $^
TARGET_BIN = $(BIN_DIR)/test
all : make_dirs $(TARGET_BIN)
$(TARGET_BIN) : $(SRCS:%.cpp=$(OBJ_DIR)/%.o)
g++ $(LDFLAGS) -o $# $^ $(LDLIBS)
make_dirs :
mkdir -p $(OBJ_DIR)
mkdir -p $(BIN_DIR)
With this approach you have several benefits:
Easy to use: you specify source files once, and you don't care about processing of each object file: the job is done by a single rule.
More maintainable: every time you need to change the compiler or linker options you do it in the single rule, not for each translation unit.
You have an error in that line:
g++ -c -o hello main.o factorial.o hello.o
man gcc says: ... the -c option says not to run the linker.
This option is used to produce objects files only. When it passed, gcc will not start linker to produce executable file or shared library.
As clear from all above answers, because of using -c in g++ -c -o hello main.o factorial.o hello.o, it is preventing from linking. After creating the object files from corresponding .cpp or .h etc files, these need to be linked. Without linking, as each file is a part of a complete program that can perform some task, nothing useful can be done as these file are dependent. So, we have to link these dependent parts to run our complete program.
One basic video tutorial for easy learning of making a Makefile in the two methods viz dependencies and pattern rules is here.
It takes example of method of dependencies and then introduce pattern rules as a better approach for making a long Makefile.
To know the difference between compilation and linking, this link can be useful.
I'm writing a terminal based Tetris game using ncurses. I've segregated all of the ncurses code into a file called tetrisUI.c which i include a header file for in my main.c source file. When I compile all of the ncurses functions raise compiler errors. I have included ncurses.h in my source file and I'm using the -lncurses flag in gcc. I'm compiling from a makefile with the following contents:
Tetris : tetris.o main.o tetrisUI.o
gcc tetris.o main.o tetrisUI.o -o Tetris
tetrisUI.o : tetrisUI.c
gcc -std=c99 -c tetrisUI.c -lncurses
tetris.o : tetris.c tetris.h
gcc -std=c99 -c tetris.c
main.o : main.c tetris.h tetrisUI.h
gcc -std=c99 -c main.c
I was able to compile a few short test programs using ncurses just fine. This is my first attempt at using ncurses and my first significant c program (I've done a little c++ in school). I have a hunch that my problem has something to do with my makefile but I'm a noob at using those too.
Use -lncurses at the link stage not at the compile stage:
gcc tetris.o main.o tetrisUI.o -o Tetris -lncurses
You can simplify your Makefile by using default macros and rules:
CFLAGS = -std=c99 # C compiler flags
LDLIBS = -lcurses # curses
Tetris : tetris.o main.o tetrisUI.o # make does a "$(CC) $(CFLAGS) -o $# $^ $(LDLIBS)" on its own
That's all you need. The following definitions and rules can be completely omitted - make does the right thing by default:
CC = gcc # C compiler name
tetrisUI.o : tetrisUI.c tetrisUI.h # make does a "$(CC) $(CFLAGS) -o $# $<" on its own
tetris.o : tetris.c tetris.h
main.o : main.c tetris.h tetrisUI.h
A bit of explanation: $# is whatever is being built, $< is the first dependency, $^ is all of them. Judicious use of this makes for less typing (and less idiotic errors, where you add a dependency and don't process it; or omit a dependency (and thus don't redo the build if it changes)). Take a look at the make manual, if you have GNU make, its info file has lots of detailed examples and tips.
I have one "helper" file included in two "main" files which are built into two executables with the same makefile. I have debug print statements in the helper file. I want the print statements to actually be printed in one executable, but not the other. Is there a way to do it? Right now I have the following, and I was hoping to compile with DEBUG_PRINT defined for one executable but not the other, but I don't see how.
main1.cpp:
#include "helper.h"
...
main2.cpp:
#include "helper.h"
...
helper.cpp:
#ifdef DEBUG_PRINT
cout << "here is a debug message" << endl;
#endif
Makefile:
build: main1 main2
main1: main1.o helper.o
g++ -g -o main1 main1.o helper.o
main2: main2.o helper.o
g++ -g -o main2 main2.o helper.o
%.o: %.cpp
gcc -g -c $<
You will need two different object files (main1-helper.o and main2-helper.o) and target-specific compiler flags:
main1: CXXFLAGS=-DDEBUG_PRINT
%.o: %.cpp
gcc $(CXXFLAGS) -g -o $# -c $<
Note: This leaves you with the problem of generating main1-helper.o from helper.o. There are a few ways to solve this; however, you might be more comfortable using automake from the start instead of rolling your own solutions.