g++ isn't compiling all of the files in my project - c++

I'm trying to build a c++ project in VS Code but when i try to build it g++ throws an error saying:
g++ -std=c++17 -ggdb -Iinclude src/main.cpp -o bin/main
Undefined symbols for architecture x86_64:
"MessageBus::MessageBus()", referenced from:
_main in main-244f95.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [bin/main] Error 1
The terminal process "/bin/zsh '-c', 'make'" terminated with exit code: 2.
Here are the files that i think are causing the problem:
MessageBus.h
#pragma once
#include "../Utils/Queue.h"
#include "../Utils/SimpleList.h"
#include "Messages/Message.h"
class System;
class MessageBus
{
public:
MessageBus();
~MessageBus();
void addReciever(System* system);
void postMessage(Message* msg);
void notify();
private:
Queue<Message> msgQueue;
SimpleList<System*> systems;
};
MessageBus.cpp
#include "MessageBus.h"
#include "System.h"
MessageBus::MessageBus() {}
MessageBus::~MessageBus() {}
void MessageBus::postMessage(Message* msg) {
msgQueue.add(msg);
}
void MessageBus::addReciever(System* system) {
systems.add(system);
}
void MessageBus::notify() {
int queueLength = msgQueue.getLength();
for (int i = 0; i < queueLength; i++) {
Message msg = msgQueue.pop();
for (int j = 0; j < systems.getLength(); j++) {
System* system = systems.get(j);
system->handleMessage(&msg);
}
}
}
main.cpp
#include "EventSystem/MessageBus.h"
int main(int argc, char* argv[])
{
MessageBus* msgBus = new MessageBus();
}
Makefile
CXX := g++
CXX_FLAGS := -std=c++17 -ggdb
BIN := bin
SRC := src
INCLUDE := include
LIBRARIES :=
EXECUTABLE := main
all: $(BIN)/$(EXECUTABLE)
run: clean all
clear
./$(BIN)/$(EXECUTABLE)
$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp
$(CXX) $(CXX_FLAGS) -I$(INCLUDE) $^ -o $# $(LIBRARIES)
clean:
-rm $(BIN)/*
But when i try to compile these files together using the terminal:
g++ main.cpp EventSystem/MessageBus.cpp -o maintest
it works just fine, so i think the problem is that my files aren't compiled together. I think this might have something to do with the linker being unable to find the correct files and it might have something to do with my project structure?
This is my current structure
As you can see the header files are located together with the source code. Should i separate the header files from the cpp files or is it that i have put them in subdirectories? Or is it something else entirely? I'm somewhat new to c++ and Makefiles and i can't seem to understand what is causing the problem.
Edit:
Solution:
As #MadScientist suggested i replaced $(SRC)/*.cpp in my Makefile with $(shell find $(SRC) -name \*.cpp -print) which solved the problem. But as #WhozCraig mentioned i should probably switch to cmake to avoid Makefiles in the future.

You list the "working" command as:
g++ main.cpp EventSystem/MessageBus.cpp -o maintest
but your recipe is:
$(BIN)/$(EXECUTABLE): $(SRC)/*.cpp
The glob expression $(SRC)/*.cpp won't match the file main.cpp.
If we could see your link line, we'd probably be able to see that main.cpp is missing.

Related

Can't cross compile c++ class with sqlite included (undefined reference) on linux (i686-w64-mingw32-g++)

I tried to compile my c++ class with sqltie3 include.
I run Ubuntu 20.04.
For this I use the i686-w64-mingw32-g++ cross compiler, I also tested it with g++ and it works perfectly but not with the i686-w64-mingw32-g++ compiler.
I always get the same error:
/usr/bin/i686-w64-mingw32-ld: DBWrapper.o:DBWrapper.cpp:(.text+0x61): undefined reference to `sqlite3_open'
/usr/bin/i686-w64-mingw32-ld: DBWrapper.o:DBWrapper.cpp:(.text+0x12c): undefined reference to `sqlite3_close'
My Makefile:
mingw = i686-w64-mingw32-g++
SQLCOMPILE = -I/usr/local/sqlite/include
CFLAGS = -Wall
SRCFILES = *.cpp
OBJFILES = *.o
TARGETWIN = progwx.exe
all: $(TARGETWIN)
$(TARGETWIN): $(OBJFILES)
$(mingw) $(CFLAGS) $(OBJFILES) $(SQLCOMPILE) -o $(TARGET) -l sqlite3
$(OBJFILES): $(SRCFILES)
$(mingw) $(CFLAGS) $(SQLCOMPILE) -c $(SRCFILES)
.PHONY: clean
clean:
rm -f *.o
I put the sqlite source code in $(SQLCOMPILE) and the compiler can include everything unless I call the sqlite3_open() function.
I also compiled the source code to a library (libsqlite3.a) so that the -l tag can find it.
Because the g++ compiler brings also the same "undefined reference" error if I don't put the -lsqlite3 tag in.
$ i686-w64-mingw32-gcc -c sqlite3.c
$ ar rcs libsqlite3.a sqlite3.o
Here is my Headerfile (DBWrapper.h):
#pragma once
#include <string>
#include <stdexcept>
#include <sqlite3.h>
class DBWrapper {
sqlite3 *db_;
const int errCode;
public:
DBWrapper(const std::string &dbname);
DBWrapper(const DBWrapper&) = delete;
DBWrapper& operator=(const DBWrapper&) = delete;
sqlite3* operator*();
~DBWrapper();
};
Here is my CPP-File (DBWrapper.cpp):
#include "DBWrapper.h"
DBWrapper::DBWrapper(const std::string &dbname) : db_(nullptr), errCode(sqlite3_open(dbname.c_str(), &db_)){
if(errCode) {
throw std::runtime_error("ERROR at opening database!");
}
}
DBWrapper::~DBWrapper() {
sqlite3_close(db_);
}
sqlite3* DBWrapper::operator *() {
return db_;
}
(sorry for my bad english)
I figured it out I just needed sqlite3 as a compiled object file (sqlite3.o) for the compiler.

How to create Makefile for multiple files in multiple directories?

Good morning,
I new in c++ and I am trying to compile my simple code to executable form. I will explain structure of project.
- main.cpp
- /utility/server.h
- /utility/server.cpp
I enclose file sources for complete information.
main.cpp
#include <iostream>
#include "utility/server.h"
using namespace std;
using namespace server;
int main() {
std::cout << "Content-type:text/html\r\n\r\n";
std::cout << "Your server name is: " << server::get_domain() << '\n';
return 0;
}
server.cpp
#include <cstdlib>
#include "server.h"
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
To my Makefile I added comments to understand what I want to do.
#
# 'make' build executable file
# 'make clean' removes all .o and executable files
#
# define the C compiler to use
CC = g++
# define any compile-time flags
CFLAGS = -Wall -g
# define any directories containing header files other than /usr/include
INCLUDES = -I../utility
# define the C++ source files
SRCS = main.cpp utility/server.cpp
# define the C++ object files
OBJS = $(SRCS:.cpp=.o)
# define the executable file
MAIN = executable.cgi
#
# The following part of the makefile is generic
#
.PHONY: depend clean
all: $(MAIN)
$(MAIN): $(OBJS)
$(CC) $(CFLAGS) $(INCLUDES) -o $(MAIN) $(OBJS)
# this is a suffix replacement rule for building .o's from .cpp's
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) -cpp $< -o $#
clean:
$(RM) *.o *~ $(MAIN)
depend: $(SRCS)
makedepend $(INCLUDES) $^
And finally error from compilation
g++ -Wall -g -I../utility -o executable.cgi main.o utility/server.o
Undefined symbols for architecture x86_64:
"server::get_domain()", referenced from:
_main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [executable.cgi] Error 1
From error message I understood there is problem with utility folder, but I don't know how to fix it.
Thank you for your help :)
In server.cpp, here:
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
You have made char* server::get_domain() a static function, making
its definition visible only within this translation unit and invisible to
the linker. Remove the keyword static here, and also in server.h if you have declared the function static there.
A namespace is not a class or struct. Confusingly,
namespace server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
}
server::get_domain() is a static function in that namespace. But
struct server {
static char* get_domain() {
return getenv("SERVER_NAME");
}
};
it is a global function in that class, which the linker can see.

Having issue linking with an external array declared in a header file and defined in a source file

I need to declare a very large n-d array. It is defined in a header file and never changes. Unfortunately compiling the main file takes a very long time, so I decided to bring it out into it's own object file.
Here is the header file tables.hpp:
#pragma once
namespace TABLES
{
extern const int A[10][10][10];
extern const int B[10][10][10];
}
Here is the source file tables.cpp:
namespace TABLES
{
const int A[10][10][10] = {}; // use default for brevity
const int B[10][10][10] = {}; // use default for brevity
}
and my main file:
#include "tables.hpp"
int main()
{
printf("%d", TABLES::A[0][0][0]);
}
and here is my Makefile:
CXX = clang++
CFLAGS = -std=c++17 -g -flto -Wall -Iinclude/
SRC = src/
INC = include/
tables.o: $(SRC)tables.cpp $(INC)tables.hpp
$(CXX) $(CFLAGS) -c $(SRC)tables.cpp
main: main.cpp tables.o
$(CXX) $(CFLAGS) -o main main.cpp tables.o
the tables.o compiles successfully, however I am having issues linking the tables.o to the main program:
undefined reference to `TABLES::A'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Makefile:30: recipe for target 'main' failed
make: *** [refactor] Error 1

Dependency injection via template specialization

lib.h:
#include <iostream>
namespace lib {
template <class T>
void f(T t)
{
std::cout << "lib f " << t << std::endl;
}
}
client.cpp:
#include "lib.h"
// explicit instantiation
template
void lib::f(char);
int main()
{
lib::f('x');
}
libmock.h:
#include <iostream>
#include "lib.h"
namespace lib {
template <>
void f(char c)
{
std::cout << "libmock f " << c << std::endl;
}
}
Makefile:
run: prod test
./prod
./test
prod: client.o
${CXX} -o $# $^
test: client.o libmock.o
${CXX} -o $# $^
clean:
-rm *.o prod test
Using GCC 4.3.2 (and also "IBM XL C/C++ for AIX, V11.1 (5724-X13)"), I get the results that I expect:
$ make
g++ -c -o client.o client.cpp
g++ -o prod client.o
g++ -c -o libmock.o libmock.cpp
g++ -o test client.o libmock.o
./prod
lib f x
./test
libmock f x
That is, I've injected new functionality into the client by linking it with an object that provides a more-specialized function template than the one offered by the library.
However, if I use "CC: Sun C++ 5.12 SunOS_sparc Patch 148506-14 2013/09/24", then I get this error:
$ CXX=CC make
CC -c -o client.o client.cpp
CC -o prod client.o
CC -c -o libmock.o libmock.cpp
CC -o test client.o libmock.o
ld: fatal: symbol 'void lib::f<char>(__type_0)' is multiply-defined:
(file client.o type=FUNC; file libmock.o type=FUNC);
Makefile:9: recipe for target 'test' failed
make: *** [test] Error 2
My solution must work with all three of these compilers. Am I just getting lucky with some undefined behavior in GCC and AIX? Are there some options I could pass to the Sun compiler to get this to work? Does what I'm trying to do show that I'm not fully understanding these template concepts? Enlighten me, please!
Your test binary that links libmock.o and client.o together violates the one definition rule (in the client translation unit it uses the default version and in the libmock translation unit it uses the specialized version) and thus both linker behaviors are ok.
I will continue thinking about alternatives but right now the only solutiion I can think of is to conditionally include libmock.h in client.cpp based on whether you're doing the mock test build or not.

Undefined reference in main Makefile

I did a sample project in linux but i am getting error while running main Makefile
Project Info:
project/database folder having files database.h , database.cpp , bulid-database ,Makefile
database.h
/*data base file*/
#include<iostream>
using namespace std;
class mydatabase
{
public:
mydatabase(int a , int b);
int sum(){return m_a +m_b;}
int diff(){return m_a -m_b;}
int mul(){return m_a *m_b;}
float div(){return m_a /m_b;}
int reminder(){return m_a %m_b;}
private:
int m_a , m_b;
};
database.cpp
#include "database.h"
mydatabase::mydatabase(int a ,int b):m_a(a) , m_b(b)
{
}
bulid-database
make
if [ -f libdatabase.a ];
then
echo "Database-Library Build Success"
cp libdatabase.a ../LIBs/
else
echo "databse-Library Build Failure"
fi
Makefile
HEADERFILES = $(wildcard *.h)
CPPFILES = $(wildcard *.cpp)
OBJFILES = $(patsubst %.cpp,%.o ,$(wildcard *.cpp))
$(OBJFILES): %.o : %.cpp $(HEADERFILES)
g++ -c -o $# $<
ar ruv libdatabase.a $#
ranlib libdatabase.a
project/Main folder having files main.cpp , Makefile
main.cpp
#include "database.h"
#include <iostream>
int main()
{
mydatabase *obj = new mydatabase(10 ,5);
std::cout<<"sum is"<<obj->sum()<<endl;
std::cout<<"diff is"<<obj->diff()<<endl;
std::cout<<"mul is"<<obj->mul()<<endl;
std::cout<<"div is"<<obj->div()<<endl;
std::cout<<"reminder is"<<obj->reminder()<<endl;
getchar();
return 0;
}
Makefile
CC = g++
INCPATH = -I. \
-I.. \
-I../database
LIBPATH = -L../LIBs
LDFLAGS = ${LIBPATH}/libdatabase.a
CFLAGS = ${INCPATH}
testdate:main.o
$(CC) $(CFLAGS) -o testdate main.o $(LDFLAGS)
main.o:main.cpp
$(CC) $(CFLAGS) -c -o main.o main.cpp
ISSUE: database make file is working fine but main Makefile i am having some issue like
Error: main.o: In function main':
main.cpp:(.text+0x92): undefined reference tomydatabase::mydatabase(int, int)'
collect2: ld returned 1 exit status
This line is wrong:
$(CC) $(CFLAGS) -o testdate $(LDFLAGS) main.o
because the library should be specificed AFTER the object main.o on the line. This is due to the way the linker handles the objects. Look at this example:
gcc -o test someobject.o library.a
The linker will:
look up all undefined references of someobject.o and store them
then it opens library.a and resolves the undefined references via library.a
then it closes library.a
If the object and the library are in the other way around, then the linker opens library.a, sees no undefined references in its table and closes it. Then it tries and compiles someobject.o and the undefined references are never satisfied
EDIT:
This is a well-known caveat of GCC, a more detailed stack-overflow explanation can be seen here, and options --start-group and --end-group can help resolve cases where A depends on B, and B depends on A.
It's your Makefile. You want:
libdatabase.a
or
-ldatabase
at the end of your main compile line