Compiling a multiple cpp files Error undefined reference to `main' - c++

I am currently learning how to use makefile and currently dividing my main.cpp to multiple files.
here is my current structure
├── makefile
└── src
├── Graphics
│   ├── Graphics.cpp
│   └── Graphics.h
└── main.cpp
and my makefile
CC = g++
CFLAGS = -c
LFLAGS = -Wall
OUTPUT = game
game : main.o Graphics.o
$(CC) $(LFLAGS) main.o Graphics.o -lSDL2 -lSDL2_image -o $(OUTPUT)
main.o : src/main.cpp
$(CC) $(CFLAGS) src/main.cpp
Graphics.o : src/Graphics/Graphics.cpp
$(CC) $(CFlAGS) src/Graphics/Graphics.cpp -lSDL2
Everytime I compile. I always get this Error. But I have my main declared. is it looking for a main inside my Graphics.cpp?
/usr/bin/ld: /usr/lib/debug/usr/lib/x86_64-linux-gnu/crt1.o(.debug_line): relocation 0 has invalid symbol index 2
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
make: *** [Graphics.o] Error 1
Here is my main function
#include "Graphics/Graphics.h"
int main(int argc , const char * argv[]){
Graphics graphics;
while(true){
//do things here later
}
return 0;
}
//Edit.
Btw. is there also a way not to link sdl2 on Graphics.cpp, If remove -lSDL2. it would give me all that sdl2 function undefined

You have a typo in your makefile; $(CFlAGS) is not the same as $(CFLAGS), meaning that -c is not passed as a command-line option to the compiler when trying to compile src/Graphics/Graphics.cpp.
CC = g++
CFLAGS = -c
LFLAGS = -Wall
OUTPUT = game
game : main.o Graphics.o
$(CC) $(LFLAGS) main.o Graphics.o -lSDL2 -lSDL2_image -o $(OUTPUT)
main.o : src/main.cpp
$(CC) $(CFLAGS) src/main.cpp
Graphics.o : src/Graphics/Graphics.cpp
$(CC) $(CFlAGS) src/Graphics/Graphics.cpp -lSDL2
Variables in makefiles are case-sensitive, which means that even though you wanted to include the contents of CFLAGS you instead got the contents of an undeclared variable named CFlAGS.
Note: Without -c you are telling g++ to run the linker, and as such it will look for a function named main so that it can produce an executable; graphics.cpp does not contain such function, and the diagnostic you have presented is emitted.
Note: After you have fixed the issue with $(CFlAGS) you will be able to remove -lSDL2 from the relevant line.

In your error message it says:
make: *** [Graphics.o] Error 1
That means this error occurred while compiling Graphics.o, not while linking game.
Your command for compiling Graphics.o is
$(CC) $(CFlAGS) src/Graphics/Graphics.cpp -lSDL2
-lSDL2 doesn't make sense here: You want to compile an object file, so the linker is not involved. But you're getting linker errors - why?
Because to compile without linking, you need the -c option. This is part of your CFLAGS variable. But you're not using CFLAGS, you're using CFlAGS (lowercase l). So I bet the command that make is running looks like
g++ src/Graphics/Graphics.cpp -lSDL2
without -c.
Fix: remove -lSDL2, capitalize L in variable name.

Related

Linking LLVM IR Libraries

I am following along with the LLVM Kaleidoscope Tutorial (Ch. 3), and am encountering errors (undoubtedly from my Makefile) after attempting to link LLVM IR libraries. My Makefile and project structure:
CPP=clang++
CFLAGS=-g -Wall -std=c++14
LDFLAGS:=$(shell llvm-config --cxxflags --ldflags --system-libs --libs core)
EXEC=comp.out
SRCS:=$(shell find src -type f -name '*.cpp')
OBJS:=$(patsubst %.cpp,%.o,$(SRCS))
all: $(EXEC)
$(EXEC): $(OBJS)
$(CPP) $(CFLAGS) -o $# $^
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -o $# $<
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -o $# $<
.PHONY: clean
clean:
rm -f $(shell find src -type f -name '*.o')
rm -f $(EXEC)
.
└── src
├── main.cpp
├── [.cpp files]
│
├── ast
│ ├── [.cpp files]
│ │
│   └── include
│ └── [.h files]
│
└── include
└── [.h files]
When Making, I get the error:
clang++ -g -Wall -std=c++14 -I/usr/local/Cellar/llvm/12.0.1/include -std=c++14 -stdlib=libc++ -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -L/usr/local/Cellar/llvm/12.0.1/lib -Wl,-search_paths_first -Wl,-headerpad_max_install_names -lLLVM-12 src/IMRep.cpp -o src/IMRep.o
Undefined symbols for architecture x86_64:
"_main", referenced from:
implicit entry/start for main executable
ld: symbol(s) not found for architecture x86_64
clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [Makefile:19: src/IMRep.o] Error 1
From the error above, main.cpp is never compiled before compilation errors out. It only gets to the src/IMRep.cpp file (not sure if that matters). If I add the -c flag to make it:
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $#
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) $(LDFLAGS) -c $< -o $#
I am able to run the program successfully despite the plethora of warning messages saying the linker inputs/arguments are unused. These warnings are expected because -c only compiles and doesn't link.
And in main.cpp:
#include <iostream>
int main(int argc, char *argv[])
{
return 0;
}
So this question doesn't get flagged as a dupe:
[1]: main.cpp is included in OBJS
[2]: Added -c flag and receive many warnings about unused linker arguments/input (because -c is for compilation, not linkage)
[3]: I only use $< where there is one dependency and $^ where there are multiple
[4]: Can't apply the answer to this question
[5]: All files in SRCS and OBJS are the correct files. I verified this by making a 'verbose' rule and printing those values and make verbose
Which leads me to believe that I am not linking in these libraries correctly.
Your question is, in fact, a duplicate of the #2 answer there.
When you want to create an object file you MUST use the -c option. That's what the -c option means.
If you don't want "a plethora of warning messages saying the linker inputs/arguments are unused" then, you know, don't add the linker inputs and arguments when you generate object files! Those arguments are for linking, not compiling.
Your .o rules should be:
src/%.o: src/%.cpp
$(CPP) $(CFLAGS) -c $< -o $#
src/ast/%.o: src/ast/%.cpp
$(CPP) $(CFLAGS) -c $< -o $#
Just to point out you don't need both of the above pattern rules. If you want the object files to live in the same directory as the source files you can just write:
%.o: %.cpp
$(CPP) $(CFLAGS) -c $< -o $#
And, if you switched to using the standard make variables instead of using non-standard ones:
# CPP is the C preprocessor, not C++
CXX = clang++
# CFLAGS is flags for the C compiler, not C++
CXXFLAGS := -g -Wall -std=c++14 $(shell llvm-config --cxxflags core)
LDFLAGS := $(shell llvm-config --ldflags --system-libs --libs core)
then you wouldn't need to define your own pattern rule at all because make has a built-in rule which knows how to compile a C++ source file into an object file.

Makefile linking

I ran into an issue with make. I have 3 files.
main.cpp | src/Math/Vector2.cpp | src/Math/Vector2.hpp
Here is my MakeFile:
main: vector2.o main.o
g++ -o main.o vector2.o
main.o: main.cpp
g++ -o main.o main.cpp -c
vector2.o: src/Math/Vector2.cpp src/Math/Vector2.hpp
g++ -o vector2.o src/Math/Vector2.cpp -lm -c
When i copy these commands manually , it compiles perfectly fine.
However $make main returns
g++ main.cpp -o main
/tmp/ccnRZ4UD.o: In function `main':
main.cpp:(.text+0x42): undefined reference to `
phy2d::Maths::Vector2f::Vector2f(double, double)'
main.cpp:(.text+0x66): undefined reference to `
phy2d::Maths::Vector2f::Vector2f(double, double)'
main.cpp:(.text+0x79): undefined reference to `
phy2d::Maths::Vector2f::distance(phy2d::Maths::Vector2f const&)
const'
collect2: error: ld returned 1 exit status
<builtin>: recipe for target 'main' failed
make: *** [main] Error 1
Any ideas??
There's no way that the makefile you provide will give the output you show.
In your comment you said Here is my MakeFile. Note that make will not read a file named MakeFile. It will read files named Makefile and makefile, but if you're using a case-sensitive filesystem then one explanation for the behavior you're seeing is that you've used MakeFile for your makefile name and make can't find it.
Or, you could have simply been imprecise in your question, but then this can't be the makefile that make is using for some other reason.
Also, there are numerous errors with your makefile:
You have two different targets main and main.o where the command generates the same file, -o main.o
You are adding libraries -lm to your compile line for vector2.o; libraries should go on the link line.
In general you should be using automatic variables to make sure your makefile is agreeing with what you want it to do.
Here's a reasonable makefile for your situation:
CXX = g++
main: vector2.o main.o
$(CXX) -o $# $^ -lm
main.o: main.cpp
$(CXX) -c -o $# $<
vector2.o: src/Math/Vector2.cpp src/Math/Vector2.hpp
$(CXX) -c -o $# $<

Multiple definitions of main with Makefile

I am trying to compile my C++ program using make and I've come across this problem that I can't quite understand. I have 3 files in the src folder of my project: App.h, App.cpp and main.cpp. I have my Makefile located in the root folder of my project, which has the src folder that I mentioned in it. This is what my Makefile looks like:
CC=g++
SRCDIR=./src
CFLAGS=-I$(SRCDIR)
LIBS=-lSDL -lGL
_DEPS=App.h
DEPS=$(patsubst %,$(SRCDIR)/%,$(_DEPS))
_OBJ=main.o App.o
OBJ=$(patsubst %,$(SRCDIR)/%,$(_OBJ))
_SRC=main.cpp App.cpp
SRC=$(patsubst %,$(SRCDIR)/%,$(_SRC))
%.o: $(SRC) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
tetris: $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
clean:
rm -f $(SRCDIR)/*.o $(SRCDIR)/*~
When I type make into the terminal to compile, I get an error like this:
g++ -c -o src/main.o src/main.cpp -I./src
g++ -c -o src/App.o src/main.cpp -I./src
g++ -o tetris src/main.o src/App.o -I./src -lSDL -lGL
src/App.o: In function `main':
main.cpp:(.text+0x0): multiple definition of `main'
src/main.o:main.cpp:(.text+0x0): first defined here
src/main.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `App::App()'
main.cpp:(.text+0x23): undefined reference to `App::onExecute()'
src/App.o: In function `main':
main.cpp:(.text+0x17): undefined reference to `App::App()'
main.cpp:(.text+0x23): undefined reference to `App::onExecute()'
collect2: error: ld returned 1 exit status
But I am sure that I only have 1 main function, and it is in the main.cpp file. What is causing this?
Look at these lines:
src/main.o: In function `main':
src/App.o: In function `main':
Those mean that main is defined both in main.o and App.o.
And above those:
g++ -c -o src/main.o src/main.cpp -I./src
g++ -c -o src/App.o src/main.cpp -I./src
See? Both object files are built using the same source!
You probably want to change this line for the object dependency:
%.o: %.c $(DEPS)
Look at the compilation lines.
You are compiling main.cpp as both main.o and App.o.
You are listing all your source files as prerequisites of the %.o pattern and using $< to only compile the first one (which happens to be main.cpp in this case.
You want %.c instead of $(SRC) there.

/usr/bin/ld: cannot find : No such file or directory

I'm following this SDL tutorial to try and make use of some SDL extension libraries. My code is identical to theirs but I am still unable to make the file which leads me to believe the problem is in my makefile which looks like this:
CXX = g++
# Update these paths to match your installation
# You may also need to update the linker option rpath, which sets where to look for
# the SDL2 libraries at runtime to match your install
SDL_LIB = -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib, -lSDL2_image
SDL_INCLUDE = -I/usr/local/include
# You may need to change -std=c++11 to -std=c++0x if your compiler is a bit older
CXXFLAGS = -Wall -c -std=c++11 $(SDL_INCLUDE)
LDFLAGS = $(SDL_LIB)
EXE = SDL_Lesson3
all: $(EXE)
$(EXE): main.o
$(CXX) $< $(LDFLAGS) -o $#
main.o: main.cpp
$(CXX) $(CXXFLAGS) $< -o $#
clean:
rm *.o && rm $(EXE)
That makefile worked fine for previous examples. The only thing that has changed in this example is line 5 where I added -lSDL2_image as per the tutorial. When I try make the file I get the following traceback:
rony#comet:~/Documents/cpp/helloworld/lesson3$ make
g++ main.o -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib, -lSDL2_image -o SDL_Lesson3
/usr/bin/ld: cannot find : No such file or directory
collect2: error: ld returned 1 exit status
make: *** [SDL_Lesson3] Error 1
Is there an error with my makefile? Have I not installed the library correctly?
The problem is this rogue comma:
SDL_LIB = -L/usr/local/lib -lSDL2 -Wl,-rpath=/usr/local/lib, -lSDL2_image
^
causing the linker to look for libraries in a non-existent directory with an empty name, as well as /usr/local/lib. Removing the comma should fix it.

c++ Makefile with external h and o files

I have project files and I need to use an external test file named TestSuite1.cpp that includes an external header file SignalMasker.h (Was given it and it's object file SignalMasker.o) and my main header file uthreads.h.
I'm still getting undefined refrences such as:
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
This means my Makefile isn't including the SignalMasker.o file that resides in the same directory.
This is my Makefile:
CC = g++
FLAGS = -Wall -g
OBJECTS = uthreads.o Thread.o Scheduler.o SchedulerStarter.o TestSuite1.o
.PHONY : clean
all: test1
test1: $(OBJECTS)
g++ $(FLAGS) $(OBJECTS) SignalMasker.o -L . -o test1
TestSuite1.o : TestSuite1.cpp SignalMasker.h uthreads.h
$(CC) -c $(FLAGS) TestSuite1.cpp
uthreads.o : uthreads.cpp uthreads.h SchedulerStarter.h Scheduler.h Thread.h
$(CC) -c $(FLAGS) uthreads.cpp
Scheduler.o : Scheduler.cpp Scheduler.h Thread.h
$(CC) -c $(FLAGS) Scheduler.cpp
SchedulerStarter.o : SchedulerStarter.cpp SchedulerStarter.h Scheduler.h
$(CC) -c $(FLAGS) SchedulerStarter.cpp
Thread.o : Thread.cpp Thread.h uthreads.h translateAdd.h
$(CC) -c $(FLAGS) Thread.cpp
clean:
rm -f $(OBJECTS) *~
And now I'm getting:
~/Desktop/tests$ make
g++ -Wall -g uthreads.o Thread.o Scheduler.o SchedulerStarter.o TestSuite1.o SignalMasker.o -L . -o test1
/usr/bin/ld: error: SignalMasker.o: incompatible target
TestSuite1.cpp:36: error: undefined reference to 'SignalMasker::SignalMasker(int)'
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:63: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:68: error: undefined reference to 'SignalMasker::SignalMasker(int)'
TestSuite1.cpp:111: error: undefined reference to 'SignalMasker::~SignalMasker()'
TestSuite1.cpp:111: error: undefined reference to 'SignalMasker::~SignalMasker()'
collect2: ld returned 1 exit status
EDIT:
I'm now pondering with the idea that maybe incompatible target means they compiled it under 64bit. My machine is 32bit
you are missing rule to compile SignalMasker.cpp in your makefile. you have to write a rule, the same way you have written for
SchedulerStarter.o, Thread.o
SignalMasker.o : SignalMasker.cpp SignalMasker.h
$(CC) -c $(FLAGS) SignalMasker.cpp
This will ensure the SignalMasker.o is generated with the same compilation flags that you build other objects. It will eliminate incompatibility issues in case of 32-bit/ 64-bit variants.
if you are copying this SignalMasker.o from elsewhere, check the compilation flags used for generating the object. Use the same flags in your makefile.