Undefined reference to 'main' error in crt1.o function _start - c++

I've having problems with my Makefile.
I'm trying to create a program from 2 files - main.cpp that contains the main function, and modules.c that contains the definitions of the functions that are called in main(). modules.c only contain function definitions, no main function.
My Makefile is as follows:
CC := gcc
CXX := g++
LINK := g++ -Wall
CFLAGS := -g
CXXFLAGS := -g
TARGET = program
$(TARGET): modules.o main.o
$(LINK) -o $# $< -lpcap
clean:
rm *.o $(TARGET)
modules.o:
$(CC) $(CFLAGS) -c modules.c -o $# $<
main.o:
$(CXX) $(CXXFLAGS) -c main.cpp -o $# $<
I have included "modules.h", which contains all the function declarations, in my main.cpp. The CFLAGS and CXXFLAGS variables point to the correct paths containing
When I try to make using this Makefile, I get the error
/usr/lib/gcc/x86_64-redhat-linux/4.4.4/../../../../lib64/crt1.o: In function '_start':
(.text+0x20): undefined reference to 'main'
If I switch the order of modules.o and main.o in my $(TARGET) line, then I get errors that say "undefined reference to" the functions I have defined in modules.c, in main.cpp.
I don't know what is wrong.
Thank you.
Regards,
Rayne

Use $^ instead of $<. The latter contains only the first dependency (modules.o), so main.o is not linked into the executable.

Here are a couple of hints:
-o $# $< is not needed for .o files, so remove that from those targets.
-Wall makes more sense when used while compiling not linking. So I would add it to the CC and CXX line instead (or better, to the CFLAGS and CXXFLAGS).
the clean target should be a dependency of the .PHONY target, so that you can execute it always (without previous check for changed dependencies).
If you still get an error about missing references to your functions from modules.c, you are probably missing some extern "C" ... statements in main.cpp. That's because the internal name of C++ functions is calculated differently than that from C functions (i think C++ prefixes all names with the namespace, class names, etc). To tell C++ that a specific function can be found using the old internal name for linkage, use the extern "C" statement.

Related

Confused how my Makefile is remaking object files

My make file is failing to find my include directory when it tries to remake object files. For example, when I call make tests I get the output:
g++ -c -o sdl_class.o sdl_class.cpp
sdl_class.cpp:9:23: fatal error: sdl_class.h: No such file or directory
#include <sdl_class.h>
^
compilation terminated.
make: *** [sdl_class.o] Error 1
My Makefile is this:
#Originally from: http://www.cs.colby.edu/maxwell/courses/tutorials/maketutor/
#But will be heavily modified
IDIR =../include
CC=g++
CFLAGS=-w -I$(IDIR)
#ODIR=obj
LDIR =../lib
LIBS=-lSDL2
_DEPS = sdl_class.h SDL_image.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
OBJ = sdl_class.o tests.o
#OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
%.o: %.cpp $(DEPS)
$(CC) -c -o $# $< $(CFLAGS) $(LIBS)
tests: sdl_class.o tests.o
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
all: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(IDIR)/*~
My understanding is that when I call make tests, that it should attempt to remake the sdl_class.o file. This should then call the %.o rule, which should try to make the object file by calling something like:
g++ -c -o sdl_class.o sdl_class.cpp -w -I../include -lSDL2
However, this is not the case as it looks like it is calling $(CC) -c -o $# $< $(CFLAGS) $(LIBS), as you can see from above.
Do I have a fundamental misunderstanding about how make builds its rules? Seems likely, this is my first Makefile. Perhaps I am confused on how compilation works in general, as I'm somewhat new to that as well.
I would say that the problem is that one or more of the files ../include/sdl_class.h or ../include/SDL_image.h does not exist. Because of that, make is deciding that your pattern rule does not match (because not all the prerequisites can be found or made) and it defaults to the built-in rule to create object files from .cpp files.
The built-in rules use the make variables CXX for the C++ compiler and CXXFLAGS for the C++ flags: the CC and CFLAGS variables are used for the C compiler. That's why your settings for CFLAGS are being ignored.
If you run make -d sdl_class.o you'll see which file make is looking for and why it decides to not use your pattern rule.
If you rewrite your rules like this it will work better:
%.o: %.cpp
$(CC) -c -o $# $< $(CFLAGS)
sdl_class.o tests.o: $(DEPS)
because make will now complain that the relevant files can't be found or created.
There are other issues, of course. You shouldn't be passing $(LIBS) to your compile command; that belongs only in your link line. And, you should probably stick to the standard variables CXX for the C++ compiler, CPPFLAGS for preprocessor flags like -I and -D, and CXXFLAGS for C++ compiler flags. Also, linker library flags like -L../lib go in LDFLAGS and linker libraries like -lSDL2 go in LDLIBS.
CC/CCFLAGS are for C compilation. You should use CXX and CXXFLAGS for C++. They are used in built-in rules and in the LINK.cc macro, making the Makefile much simpler, and thus less error prone.
CXXFLAGS = -Wall ...
prog : foo.o bar.o
$(LINK.cc) -o $# $^
see Default linker setting in Makefile for linking C++ object files

Understanding a makefile better - How the .o file gets generated in this case

I currently have the following makefile (I am using an example of an online tutorial) which works however I have a few questions regarding this:
# *****************************************************
# Variables to control Makefile operation
CXX = g++
CXXFLAGS = -Wall -g
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
objcopy --only-keep-debug test test.debug
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
car.o: car.h
student.o: student.h car.h
house.o: house.h
clean:
rm -rf *.o test *.debug
Here is my understanding of what is going on here please correct me if I am wrong. When initially test target is called it looks for the first dependency main.o This could either be a file or a target. Since there is no file called main.o it will look for main.o as a target. Once main.o as a target is found it looks for dependencies student.h house.h main.cpp since these exist as a file make then executes the recipe (command) which is $(CXX) $(CXXFLAGS) -c main.cpp. Now here is the part that I dont understand. When the second dependency car.o turn comes up make looks for car.h and finds it but there is no command that tells it to generate the .o file. How is the .o file being generated here ?
make contains several implicit rules. That means that make has built-in knowledge about how to create a .o file from a .cpp file without you telling it explicitly how to do that.
From the documentation:
Compiling C++ programs
n.o is made automatically from n.cc, n.cpp, or
n.C with a recipe of the form ‘$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c’. We
encourage you to use the suffix ‘.cc’ for C++ source files instead of
‘.C’
You may think of this as make having a built-in rule that looks quite like:
%.o : %.cpp
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $#
Read more about these implicit rules here and here.
There is a built in rule for generating an .o file from a .cpp file.
You have told it that is has an extra dependency of car.h, but not how to make car.o so it falls back on the built in rule, with car.h as an added dependency.
You could change
main.o: student.h house.h main.cpp
$(CXX) $(CXXFLAGS) -c main.cpp
to
main.o: student.h house.h
and it would build it too using the built in rule. Its documented here.
You could also use a built in rule to make your test binary, were you not also running the objcopy command.
Instead of
test: main.o car.o student.o house.o
$(CXX) $(CXXFLAGS) -o test main.o car.o student.o house.o
You could just use
test: main.o car.o student.o house.o
Most make (and similar) programs pre-define implicit rules for things like converting a source file (with any of a number of common extensions) to object file (using their default extension).
Typically that'll be equivalent to something like this:
.c.o:
$(CC) $(CFLAGS) -o $*.o -c $*.c
.cc.o:
$(CXX) $(CXXFLAGS) -o $*.o -c $*.cc
...with more for other common extensions, so it'll not only know how to compile most typical extensions (.c, .cc, .cpp, .C, etc.) to .o files, but also implicitly pick up the content of some variable you can specify as the set of flags to pass to the compiler when it does so.
As for the details of these rules: a rule like .cc.o: is an implicit rule--it basically says "if you have a .cc file you can create a .o file from it using this rule". These get used as kind of a backstop--if you have an explicit rule telling how to create some specific .o file, make will use that by preference--but if there isn't an explicit rule, it can fall back on the implicit rule instead.
The $* is a built-in macro, that expands to the base name (without the extension) of the source file. There are a number of them for just the base name of the source ($*) and the full name of the source file ($<). There are a number of other automatic variables like this, but from what I've seen most people using them rarely enough that they have to look them up when they need to use them.

C/C++ project compiles with Xcode but not with gcc/g++

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

g++ errors while compiling object files

I wrote a small makefile which follows the general structure, creating object files and then linking to create an executable. Here is how it looks..
CXX=g++
CXXFLAGS=-Wall -g
INCLUDES= -I ./
LDFLAGS= -L ./
LIBS= -lcryptopp
SRCS= test.cpp
OBJS= $(SRCS:.cpp=.o)
EXEC=test
all: $(EXEC)
$(EXEC): $(OBJS)
$(CXX) $(CXXFLAGS) $(INCLUDES) -o $(EXEC) $(OBJS) $(LDFLAGS) $(LIBS)
.cpp.o:
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $#
Cryptopp library(cryptopp) is static. Now when I try to run this makefile, when the first command which tries to create object file runs.. its gives me many errors like this..
test.cpp:289: instantiated from here
./include/algparam.h:322: warning: unused variable 'p'
./include/algparam.h: In member function 'void CryptoPP::AlgorithmParametersTemplate<T>::MoveInto(void*) const [with T = unsigned char]':
In the end, it links all fine and the executable works but how can I get rid of those warnings without removing -wall? I don't have much experience with make and makefiles.
That's not an error, it's a warning. (Technically, you can consider warnings as errors that don't prevent the compiler from finishing its job.)
And the way you fix it is to fix your code. This has nothing to do with the makefile. Delete the variable 'p' from line 322 in ./include/algparam.h. (There was a bit of a hint in the warning message from the compiler.)
for this warning, you can just comment variable p in test.cpp or .h file, because you don't use it, or like this
in your code
{
...
#ifdef _DEBUG_
xxx p;
#endif
...
}
and in your makefile, if you want to use p, just add -D_DEBUG_ in your CXXFLAGS

C++ makefile multiple headers one cpp

I am having compiling errors. I have one cpp file and many headers. For the makefile I thought I needed to list all the headers file. The LinkedBinaryTree.h contains includes for all the other header files. This what I wrote:
all: hw4a
hw4a: LinkedBinaryTree.cpp linkedBinaryTree.h booster.h arrayQueue. binaryTree.h binaryTreeNode.h myExceptions.h queue.h
g++ -o hw4a LinkedBinaryTree.cpp LinkedBinaryTree.h booster.h arrayQueue.h binaryTree.h binaryTreeNode.h myExceptions.h queue.h
clean:
rm hw4a
I was told that O just needed to do:
g++ LinkedBinaryTree.cpp -o bst.exe
Which one is correct?
The latter is correct: g++ -o result.exe source.cpp. You must not include header files in the compiler command, since they are automatically included by the preprocessor already.
Of course the header files are still dependencies and must be listed in the makefile. That's why there is a special universal syntax to refer to the first reference only:
.phony: all clean
all: result.exe
result.exe: main.o
$(CXX) -o $# $+
main.o: main.cpp class1.hpp lib2.hpp
$(CXX) -c -o $# $<
The $+ means "all dependecies" (with repetition; $^ also expands to all dependencies but uniquified), as you need for linking, while $< only means "first dependency", as you need for compiling.
While you're at it, sprinkle generous warning flags over your compiler commands.
What you were told. Includes should be included, not being compiled as separate units.