I ran into a problem today, using a tool I have made some times ago : a Singleton templated class.
template <class C>
class Singleton {
/*! \class Singleton
* \brief Singleton Template
*/
public:
/*!
* \brief Public access interface
* \return Singleton instance
*/
static C *getInstance (){
// Create new instance if not initialised
if (_singleton == NULL){
_singleton = new C;
}
return (static_cast<C*> (_singleton));
}
/*!
* \brief Public access destructor
*/
static void kill(){
// Clean Singleton object and free memory
if (_singleton != NULL){
delete _singleton;
_singleton = NULL;
}
}
protected:
/*!
* \brief Empty constructor
*/
Singleton() = default;
/*!
* \brief Destructor
*/
virtual ~Singleton() = default;
private:
static C *_singleton; /*!< Unique instance */
};
template <class C>
C *Singleton<C>::_singleton = NULL;
The problem arise when i try to call TextureManager::getInstance() on the (very basic) inherited class which is the following :
class TextureManager : public Singleton<TextureManager> {
friend class Singleton<TextureManager>;
/*! \class TextureManager
* \brief Textures Container
*/
public:
protected:
/*!
* \brief Empty constructor
*/
TextureManager();
/*!
* \brief Destructor
*/
~TextureManager() override;
private:
};
During compilation, the linker shows me an error that i understand but I do not really understand the reason :
build/main.o: In function `Singleton<TextureManager>::getInstance()':
main.cpp (.text._ZN9SingletonI14TextureManagerE11getInstanceEv[_ZN9SingletonI14TextureManagerE11getInstanceEv]+0x24): undefined reference to `TextureManager::TextureManager()'
It seems that it can't find the definition of the constructor which is in TextureManager.cpp
TextureManager::TextureManager() = default;
TextureManager::~TextureManager() = default;
This code worked on an older project I compiled using premake so my guess is that my current makefile is rubbish but i can't find why...
INCLUDE = -I/usr/X11R6/include/
LIBDIR = -L/usr/X11R6/lib
SRCDIR := sources
BUILDDIR := build
TARGET := bin/game
SRCEXT := cpp
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o))
FLAGS = -std=c++11 -Wall
CC = g++
CFLAGS = $(FLAGS) $(INCLUDE)
LIBS = -lglut -lGL -lGLU -lGLEW -lm
$(TARGET): $(OBJECTS)
#echo "Linking..."
#echo "$(CC) $(CFLAGS) $^ -o $# $(LIBDIR) $< $(LIBS)"; $(CC) $(CFLAGS) -o $# $(LIBDIR) $< $(LIBS)
$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT)
#mkdir -p $(#D)
#echo "$(CC) $(CFLAGS) -o $# $(LIBDIR) $< $(LIBS)"; $(CC) $(CFLAGS) -c -o $# $(LIBDIR) $< $(LIBS)
clean:
#echo "Cleaning..."
#echo "$(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
.PHONY: clean
Now stuck for hours,
all my hopes are on you :p
Edit : full make output
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/main.o -L/usr/X11R6/lib sources/main.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Tools/ThreadManager.o -L/usr/X11R6/lib sources/Tools/ThreadManager.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Graphics/GraphicalEngine.o -L/usr/X11R6/lib sources/Graphics/GraphicalEngine.cpp -lglut -lGL -lGLU -lGLEW -lm
g++ -std=c++11 -Wall -I/usr/X11R6/include/ -o build/Graphics/TextureManager.o -L/usr/X11R6/lib sources/Graphics/TextureManager.cpp -lglut -lGL -lGLU -lGLEW -lm
Linking...
g++ -std=c++11 -Wall -I/usr/X11R6/include/ build/main.o build/Tools/ThreadManager.o build/Graphics/GraphicalEngine.o build/Graphics/TextureManager.o -o bin/game -L/usr/X11R6/lib build/main.o -lglut -lGL -lGLU -lGLEW -lm
build/main.o: In function `Singleton<TextureManager>::getInstance()':
main.cpp:(.text._ZN9SingletonI14TextureManagerE11getInstanceEv[_ZN9SingletonI14TextureManagerE11getInstanceEv]+0x24): undefined reference to `TextureManager::TextureManager()'
collect2: error: ld returned 1 exit status
makefile:18: recipe for target 'bin/game' failed
make: *** [bin/game] Error 1
The problem is that you are only using the first dependency in the $(TARGET) rule:
$(CC) $(CFLAGS) -o $# $(LIBDIR) $< $(LIBS)
# ^^
My comment was actually wrong because you have a different command between the #echo and the actual command:
#echo "$(CC) $(CFLAGS) $^ -o $# $(LIBDIR) $< $(LIBS)"
# ^^ ^^
I do not see a point in adding this echo line here, I would do as follow:
$(TARGET): $(OBJECTS)
#echo "Linking..."
$(CC) $(CFLAGS) $^ -o $# $(LIBDIR) $(LIBS)
# ^^
Had you done so, you would have seen your error sooner I think.
Related
I've looked at several posts of the same questions on here and as far as I've figured I've done what they said to do. However, I still get a "undefined reference to `cmb::functionA()'" warning.
I have the header:
//combine.h
#ifndef COMBINE_H
#define COMBINE_H
namespace cmb
{
void functionA();
}
#endif
Function source file:
// combine.cc
#include <iostream>
#include "combine.h"
using namespace std;
namespace cmb
{
void functionA()
{
cout << "print something\n";
}
}
And main:
//main.cc
#include "combine.h"
using namespace std;
using namespace cmd;
int main(int argc, char *argv[])
{
functionA();
}
It is now working when compiling manually (g++ -o Test *.cc -Wall --std=c++17) but using make still gives me the same error. I really don't understand make files so any help would be appreciated.
makefile:
CXX := g++
CXXFLAGS += -Wall -std=c++17
LIBSRCS = $(filter-out main.cc,$(shell find -name \*.cc))
LIBOBJS = $(patsubst %.cc,%.o,$(LIBSRCS))
main: main.o combine.o libproject.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDFLAGS) -o $# $<
$(LIBOBJS): %.o: %.cc
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $# $<
libproject.a: $(LIBOBJS)
ar rcs $# $^
clean:
rm -f libproject.a $(LIBOBJS)
.PHONY: clean
I just use make main in terminal.
You must add combine.o after main: in the makefile.
Since you use a library, you need to tell the linker to use it (LDFLAGS), and it should be after the main in g++ command. As in previous comments, the using namespace cmd needed to be changed to cmb
This one worked for me:
CXX := g++
CXXFLAGS += -Wall -std=c++17
LIBSRCS = $(filter-out ./main.cc,$(shell find -name \*.cc))
LIBOBJS = $(patsubst %.cc,%.o,$(LIBSRCS))
LDFLAGS += -L. -lproject
main: main.o libproject.a
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $# $< $(LDFLAGS)
libproject.a: $(LIBOBJS)
ar rcs $# $^
.PHONY: clean
clean:
rm -f libproject.a $(LIBOBJS) main main.o
I also needed to add ./ in filtering out main.cc
Example run:
jontte#jontte-Latitude-E5420:~/Temp/maketest$ make
g++ -Wall -std=c++17 -c -o main.o main.cc
g++ -Wall -std=c++17 -c -o combine.o combine.cc
ar rcs libproject.a combine.o
g++ -Wall -std=c++17 -o main main.o -L. -lproject
jontte#jontte-Latitude-E5420:~/Temp/maketest$ ./main
print something
jontte#jontte-Latitude-E5420:~/Temp/maketest$ make clean
rm -f libproject.a ./combine.o main main.o
jontte#jontte-Latitude-E5420:~/Temp/maketest$
I am having trouble compiling using a makefile and including gflags. I have not done Makefiles in a while. The compile error I am getting is related to gflags
This is my makefile:
CXX = g++
CPPFlags = -g -Wall -std=c++11
LDLIBS = -lgflags
pa1: Main.cpp PA1.o Node.o
$(CXX) $(CPPFlags) $(LDFLAGS) Main.cpp Node.o PA1.o -o PA1
PA1.o:PA1.h PA1.cpp
$(CXX) $(CPPFlags) -c PA1.cpp -o PA1.o
Node.o:Node.h Node.cpp
$(CXX) $(CPPFlags) -c Node.cpp -o Node.o
This is my main.cpp
#include "PA1.h"
#include <string>
#include <iostream>
#include <fstream>
#include <string>
#include <gflags/gflags.h>
DEFINE_string(root, "0,0", "Root");
int main(int argc, char *argv[])
{
gflags::ParseCommandLineFlags(&argc, &argv, true);
PA1 run= PA1(argv[2]);
std::string rc=FLAGS_root;
int r= rc[0];
int c= rc[2];
if(run.ReadMaze()==-1)
{
return -1;
}
run.SolveMaze(r,c);
return 0;
}
edit:
This is the error message
g++ -g -Wall -std=c++11 Main.cpp Node.o PA1.o -o PA1
/tmp/ccIdQf46.o: In function `main':
/home/peteryan/Documents/Main.cpp:10: undefined reference to
`google::ParseCommandLineFlags(int*, char***, bool)'
/tmp/ccIdQf46.o: In function `__static_initialization_and_destruction_0(int,
int)':
/home/peteryan/Documents/Main.cpp:7: undefined reference to
`google::FlagRegisterer::FlagRegisterer(char const*, char const*, char
const*, char const*, void*, void*)'
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'pa1' failed
make: *** [pa1] Error 1
The linker does not appear to be linking with with -lgflags and your Makefile is likely the cause. You should put your LDLIBS at the end of your build arguments. This generic Makefile will compile all the .cpp sources and link all the object files in the same directory. It also should track your header file dependencies. Notice the LDLIBS at the end of the build directive. Give it a try for your program.
program_name := PA1
CXX := g++
CXXFLAGS := —g -Wall std=c++11
LDLIBS := -lgflags
source_files := $(wildcard *.cpp)
objects := ${source_files:.cpp=.o}
all: $(program_name)
$(program_name): $(objects)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -o $(program_name) $(objects) $(LDLIBS)
depend: .depend
.depend: $(source_files)
rm -f ./.depend
$(CXX) $(CXXFLAGS) -MM $^>>./.depend;
clean:
rm -f $(objects)
distclean: clean
rm -f *~ .depend
include .depend
I am sure this is stupid but i get this linker error
undefined reference to insert_record ,which is a function declared in Operations.hpp,implemented in Operations.cpp and used in main, and i can't find what is wrong in this makefile.
Maybe a pair of rested eyes can spot the problem.
It seems that operations isn't linked although the object is being created.
OBJS = main.o Operations.o CDR.o TBucketList.o RBucketList.o DateTime.o HashTable.o
CC = g++
CXXFLAGS = -W -Wall -Wno-unused -pedantic -c -g
LDFLAGS = -W -Wall -Wno-unused -pedantic -g
werhaus: $(OBJS)
$(CC) $(LDFLAGS) $(OBJS) -o werhaus
main.o : CDR.hpp Operations.hpp HashTable.hpp
$(CC) $(CXXFLAGS) main.cpp
Operations.o : Operations.hpp HashTable.hpp
$(CC) $(CXXFLAGS) Operations.cpp
TBucketList.o : TBucketList.hpp RBucketList.hpp
$(CC) $(CXXFLAGS) TBucketList.cpp
RBucketList.o : RBucketList.hpp
$(CC) $(CXXFLAGS) RBucketList.cpp
HashTable.o : HashTable.hpp TBucketList.hpp
$(CC) $(CXXFLAGS) HashTable.cpp
CDR.o : CDR.hpp DateTime.hpp
$(CC) $(CXXFLAGS) CDR.cpp
DateTime.o : DateTime.hpp
$(CC) $(CXXFLAGS) DateTime.cpp
clean:
\rm *.o werhaus
Update:
main.cpp :
insert_record(originator_number, aCDR, destination_number, hashtable1, hashtable2, BucketSize);
Operations.hpp:
void insert_record(const char*, CDR*, const char*, const Hashtable*, const Hashtable*, int);
Operations.cpp:
void insert_record(const char* originator_number, CDR* aCDR, const char* destination_number, Hashtable* hashtable1, Hashtable* hashtable2, int Bsize)
All seem fine in main..
There does not seem to be an error in your Makefile. As #G.M. noted, the dependencies of .o to corresponding .cpp are missing, these need to be added.
It can be that insert_record declaration in Operations.hpp does not match the definition in Operations.cpp and you end up with two functions insert_record. Check that the function declaration and definitions match: same return type and argument types, both in the same namespace.
I think you should better use something like this:
NAME= werhaus
CXX= g++ # Use CXX for C++
CXXFLAGS= -W -Wall -Wno-unused -pedantic -g
LDFLAGS= -g # No need for warning flags at linking
SRC= main.cpp \
Operations.cpp \
CDR.cpp \
TBucketList.cpp \
RBucketList.cpp \
DateTime.cpp \
HashTable.cpp
OBJS= $(SRC:.cpp=.o)
$(NAME): $(OBJS)
$(CXX) $(LDFLAGS) $(OBJS) -o $(NAME)
all: $(NAME)
%.o: %.cpp
$(CXX) -o $# -c $< $(CXXFLAGS)
clean:
rm -f $(OBJ)
fclean: clean
rm -f $(NAME)
re: fclean all
.PHONY: all clean fclean re
This type of makefile will avoid you a lot of errors.
Also, you don't need to put hpp files as dependencies.
Good luck.
In Operations.hpp you have a declaration with signature:
void insert_record(
const char*, CDR*,
const char*,
const Hashtable*,
const Hashtable*,
int)
In Operations.cpp you define a function with the different signature:
void insert_record(
const char* CDR*,
const char*,
Hashtable*,
Hashtable*,
int)
So the declaration in Operations.hpp is not in fact implemented in Operations.cpp
and is undefined.
I have a makefile where I compile a number of cpp files to make different executables.
CFLAGS=-std=c++11 -O3 -Wall -pedantic
CC=g++1
LDFLAGS=
all: auto_variables explict_kw for_each functor member_initializer member_initializer2 reference ref_ptr smart_pointers vector
auto_variables : auto_variables.o
$(CC) $(CFLAGS) auto_variables.o $(LDFLAGS) -o $#
explict_kw : explict_kw.o
$(CC) $(CFLAGS) explict_kw.o $(LDFLAGS) -o $#
for_each : for_each o
$(CC) $(CFLAGS) for_each.o $(LDFLAGS) -o $#
functor : functor.o
$(CC) $(CFLAGS) functor.o $(LDFLAGS) -o $#
member_initializer : member_initializer.o
$(CC) $(CFLAGS) member_initializer.o $(LDFLAGS) -o $#
member_initializer2 : member_initializer2.o
$(CC) $(CFLAGS) member_initializer2.o $(LDFLAGS) -o $#
reference : reference.o
$(CC) $(CFLAGS) reference.o $(LDFLAGS) -o $#
ref_ptr : ref_ptr.o
$(CC) $(CFLAGS) ref_ptr.o $(LDFLAGS) -o $#
smart_pointers : smart_pointers.o
$(CC) $(CFLAGS) smart_pointers.o $(LDFLAGS) -o $#
vector : vector.o
$(CC) $(CFLAGS) vector.o $(LDFLAGS) -o $#
clean:
rm -rf auto_variables explict_kw for_each functor member_initializer member_initializer2 reference ref_ptr smart_pointers vector
rm -rf *.o
I have specified -std=c++11 as CFLAGS but when I type make it doesn't seem to take that option.
g++ -c -o auto_variables.o auto_variables.cpp
auto_variables.cpp:8:27: error: ISO C++ forbids declaration of ‘sum’ with no type [-fpermissive]
auto sum(int x, int y) -> int
^
auto_variables.cpp:8:27: error: top-level declaration of ‘sum’ specifies ‘auto’
auto_variables.cpp:8:27: error: trailing return type only available with -std=c++11 or -std=gnu++11
auto_variables.cpp: In function ‘int main()’:
auto_variables.cpp:16:8: error: ‘var_1’ does not name a type
auto var_1 = 5;
^
auto_variables.cpp:18:8: error: ‘var_2’ does not name a type
auto var_2 = 'c';
^
auto_variables.cpp:20:16: error: ‘var_1’ was not declared in this scope
std::cout << var_1 << std::endl;
^
auto_variables.cpp:21:16: error: ‘var_2’ was not declared in this scope
std::cout << var_2 << std::endl;
^
auto_variables.cpp:23:8: error: ‘fun_sum’ does not name a type
auto fun_sum = [](int a, int b)
^
auto_variables.cpp:46:8: error: ‘itr’ does not name a type
auto itr = mapofStrs.begin();
^
auto_variables.cpp:47:9: error: ‘itr’ was not declared in this scope
while(itr != mapofStrs.end())
^
<builtin>: recipe for target 'auto_variables.o' failed
make: *** [auto_variables.o] Error 1
Why is this happening.
I suggest using CXXFLAGS instead of CFLAGS.
CFLAGS is for C flags while CXXFLAGS is for C++ flags.
CXXFLAGS=-std=c++11 -O3 -Wall -pedantic
Also, it's not clear to me what you meant by:
CC=g++1
Is that a typo? I suspect you meant to use
CC=g++
Keeping with the previous change, you should change that to:
CXX=g++
Then, change all the places where you are using $(CC) $(CFLAS) to $(CXX) $(CXXFLAGS).
This is happening because you are misusing Make.
For C++, use the correct variables, as documented on the GNU Make page: CXXFLAGS.
CXXFLAGS=-std=c++11 -O3 -Wall -pedantic
You shouldn't need to set anything else at least at first.
This will make sure that you are using the correct implicit rules. If this doesn't help, make a Minimal, complete, and verifiable example which shows the code, too.
I read different answers about VLA on SO but couldn't find the answer. In my case, I have one function that allocates memory:
template<typename T>
void allocMemory(T *&data, const size_t numElems)
{
#ifdef PINNED_MEMORY
// allocate pinned memory
#else
data = new T[numElems];
#endif
}
Now, I have a vector class where I use this method:
template<typename T>
class MyVec
{
T *data;
size_t size;
public:
MyVec(size_t _size): size(_size)
{ allocMemory<T>(data, size); } // gives VLA warning
};
It happens when I compile it using nvcc (V0.2.1221) compiler which I guess uses gcc compiler underneath (?) The actual warning is:
myvec.h:16:6: warning: ISO C++ does not support variable-length array types [-Wvla]
data = new T[numElems];
I think you don't compile your project the right way.
Try to using the flowing make file.
CUDA_INSTALL_PATH := /usr/local/cuda
CXX := g++
CC := gcc
LINK := g++ -fPIC
NVCC := nvcc
#Includes
INCLUDES = -I. -I$(CUDA_INSTALL_PATH)/include
#Common flags
COMMONFLAGS += $(INCLUDES)
NVCCFLAGS += $(COMMONFLAGS)
CXXFLAGS += $(COMMONFLAGS)
CFLAGS += $(COMMONFLAGS)
LIB_CUDA := -L$(CUDA_INSTALL_PATH)/lib -lcudart
#OBJS = GpuSolver.cu.o main.cpp.o
OBJS = main.cu.o a.cpp.o # your files
TARGET = a.out
LINKLINE = $(LINK) -o $(TARGET) $(OBJS) $(LIB_CUDA)
.SUFFIXES: .c .cpp .cu .o
%.c.o: %.c
$(CC) $(CFLAGS) -c $< -o $#
.cu.o: %.cu
$(NVCC) $(NVCCFLAGS) -c $< -o $#
%.cpp.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $#
$(TARGET): $(OBJS) "makefile" #your makefile file name
$(LINKLINE)