I'm having a linker issue with mingw on codelite. When I put the .hpp and .cpp files in main where I'm unit testing, everything works fine.
Here's my .hpp file:
class ITPropertiesBase
{
public:
virtual ~ITPropertiesBase(){}
virtual const char *getName() = 0;
};
template <typename T>
class Properties : public ITPropertiesBase
{
public:
Properties(const char *name, T value);
~Properties();
const char *getName();
private:
const char *m_name;
T m_value;
};
Here's my .cpp file:
template <typename T> Properties<T>::Properties(const char *name, T value) : m_name(name), m_value(value)
{
}
template <typename T> Properties<T>::~Properties()
{
}
template <typename T> const char* Properties<T>::getName()
{
return m_name;
}
And here's my main:
#include <iostream>
#include <vector>
#include <string>
#include "Properties.hpp"
int main(int argc, char **argv)
{
const char *testInput = "test";
std::vector<ITPropertiesBase*> as;
as.push_back(new Properties<int>(testInput, 5));
return 0;
}
And here's the linker output:
C:\Windows\system32\cmd.exe /c "C:/MinGW-4.8.1/bin/mingw32-make.exe -j4 -e -f Makefile"
"----------Building project:[ Interfaces - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'E:/CodeLite/ElysiumEngine/Interfaces'
C:\MinGW-4.8.1\bin\g++.exe -c "E:/CodeLite/ElysiumEngine/Interfaces/main.cpp" -g -O0 -Wall -o ./Debug/main.cpp.o -I. -I.
C:\MinGW-4.8.1\bin\g++.exe -c "E:/CodeLite/ElysiumEngine/Interfaces/Properties.cpp" -g -O0 -Wall -o ./Debug/Properties.cpp.o -I. -I.
C:\MinGW-4.8.1\bin\g++.exe -o ./Debug/Interfaces #"Interfaces.txt" -L.
./Debug/main.cpp.o: In function `main':
E:/CodeLite/ElysiumEngine/Interfaces/main.cpp:11: undefined reference to `Properties<int>::Properties(char const*, int)'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[1]: *** [Debug/Interfaces] Error 1
mingw32-make.exe: *** [All] Error 2
Interfaces.mk:79: recipe for target 'Debug/Interfaces' failed
mingw32-make.exe[1]: Leaving directory 'E:/CodeLite/ElysiumEngine/Interfaces'
Makefile:4: recipe for target 'All' failed
2 errors, 0 warnings
Anyone know what's going on?
This might apply to you:
Move header files out of source directory.
It works when they are all in the same folder or not, it is best to relocate them. You need to tell the compiler where they are at, in relation to your project.
change to #include <Properties.hpp>
Then place header files into a include directory.
Then in compiler flags, add include directory for header files. typically a directory called include. For example:
-I../include/
This compiler flag will include the parent directory's include folder. All header files in it will become visible to the compiler. Typically all source code or cpp files, are bundled together. Meaning all in the same parent folder for each codelite project.
One other thing, try moving your templates into header files.
Reference http://codelite.org/LiteEditor/ProjectSettings.
edit:added bullets
Related
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
"undefined reference" to a template class function
(4 answers)
Closed 4 months ago.
I have searched high and low for answers on this but I'm still baffled. As far as I understand from the examples I've found online my code should be valid but it won't compile due to undefined references. I figured out how to get it to compile but I think that's not how one is supposed to do it. So the following is a question I'd very much appreciate answers to.
I'd like to implement a class in C++ with a template member similarly to how std::vector for example can contain data of any type. The following is a minimal example that reproduces the issue.
main.cpp:
#include <iostream>
#include <cstdlib>
#include "Foo.h"
int main(int argc, char** argv) {
Foo<int> foo_int;
Foo<float> foo_flt;
return 0;
}
Foo.h:
#ifndef FOO_H
#define FOO_H
template<class T> class Foo {
public:
Foo();
Foo(const Foo& orig) = delete;
virtual ~Foo();
private:
T* m_f;
};
#endif /* FOO_H */
Foo.cpp
#include <iostream>
#include <typeinfo>
#include "Foo.h"
template<class T> Foo<T>::Foo() {
std::cout << "Constructing a Foo<" << typeid(T).name() << ">!" << std::endl;
m_f = new T;
}
template<class T> Foo<T>::~Foo() {
std::cout << "Destructing a Foo<" << typeid(T).name() << ">!" << std::endl;
}
Now if I try to build the code in NetBeans IDE I get the following output.
cd '/home/pete/Dropbox/NetBeans/Foodinger'
/usr/bin/make -f Makefile CONF=Debug
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory '/home/pete/Dropbox/NetBeans/Foodinger'
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux/foodinger
make[2]: Entering directory '/home/pete/Dropbox/NetBeans/Foodinger'
mkdir -p build/Debug/GNU-Linux
rm -f "build/Debug/GNU-Linux/Foo.o.d"
g++ -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/Foo.o.d" -o build/Debug/GNU-Linux/Foo.o Foo.cpp
mkdir -p build/Debug/GNU-Linux
rm -f "build/Debug/GNU-Linux/main.o.d"
g++ -c -g -std=c++14 -MMD -MP -MF "build/Debug/GNU-Linux/main.o.d" -o build/Debug/GNU-Linux/main.o main.cpp
mkdir -p dist/Debug/GNU-Linux
g++ -o dist/Debug/GNU-Linux/foodinger build/Debug/GNU-Linux/Foo.o build/Debug/GNU-Linux/main.o
build/Debug/GNU-Linux/main.o: In function `main':
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:9: undefined reference to `Foo<float>::Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:9: undefined reference to `Foo<float>::~Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::~Foo()'
/home/pete/Dropbox/NetBeans/Foodinger/main.cpp:8: undefined reference to `Foo<int>::~Foo()'
collect2: error: ld returned 1 exit status
nbproject/Makefile-Debug.mk:63: recipe for target 'dist/Debug/GNU-Linux/foodinger' failed
make[2]: *** [dist/Debug/GNU-Linux/foodinger] Error 1
make[2]: Leaving directory '/home/pete/Dropbox/NetBeans/Foodinger'
nbproject/Makefile-Debug.mk:60: recipe for target '.build-conf' failed
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory '/home/pete/Dropbox/NetBeans/Foodinger'
nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 760ms)
My understanding is that one should only #include header files and the .cpp files should be given as arguments to the compiler. That's what the build seems to be doing according to its output. If I however add #include "Foo.cpp" to main.cpp the program seems to compile and run just fine. But isn't this how one is not supposed to do it? Or have I found some special case here where I have to #include the .cpp file? Is NetBeans doing something wrong? Is there something wrong with my implementation using templates? At least the code compiles fine if I get rid of them.
Thanks.
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
I try to include my self built .so library in the test.cpp file.
When I try to make the test.cpp file I get this exception:
root#airdrop:/home/pi/naza-interface/examples# make
g++ -c test.cpp
test.cpp:31:35: fatal error: naza_interface_manual.h: No such file or
directory
#include "naza_interface_manual.h"
^
compilation terminated.
Makefile:5: recipe for target 'test.o' failed
make: *** [test.o] Error 1
The Makefile for test.cpp looks like that:
output: test.o
g++ -L. -lnazainterface -o test test.o
test.o:
g++ -c test.cpp
clean:
rm -f *.o
test.cpp just includes the library.
#include "naza_interface_manual.h"
The library contains two files, naza_interface_manual.h and naza_interface_manual.cpp. The library's makefile looks like that:
libso: naza_interface_manual.o pca9685.o
g++ -fPIC -L/usr/local/lib -shared naza_interface_manual.o
pca9685.o -lbcm2835 -o libnazainterface.so
naza_interface_manual.o: src/naza_interface_manual.cpp src/naza_interface_manual.h
g++ -fPIC -c -Wall src/naza_interface_manual.cpp
pca9685.o: src/PCA9685/pca9685.cpp src/PCA9685/pca9685.h
g++ -c src/PCA9685/pca9685.cpp
install: naza_interface_manual.o pca9685.o
g++ -L/usr/local/lib naza_interface_manual.o pca9685.o -lbcm2835 -
shared -o /usr/local/libnazainterface.so
clean:
rm *.o output
naza_interface_manual.h:
#ifndef NAZA_INTERFACE_MANUAL_H_
#define NAZA_INTERFACE_MANUAL_H_
class naza_interface_manual_c{
public:
naza_interface_manual_c();
// A: For roll control (left/right)
// E: For pitch control (front/back)
// T: For throttle control
// R: For rudder control
// U: For Control Model Switch
void configure_pins(int A, int E, int T, int R, int U);
void fly_forward(int speed);
void fly_backward(int speed);
void fly_up(int speed);
void fly_down(int speed);
void fly_left(int speed);
void fly_right(int speed);
};
#endif
naza_interface_manual.cpp:
#include <iostream>
#include <wiringPi.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include "naza_interface_manual.h"
#include "PCA9685/pca9685.h"
naza_interface_manual_c::naza_interface_manual_c(){
std::cout << "Starting Naza Interface";
}
void naza_interface_manual_c::configure_pins(int A, int E, int T, int R, int U){
PCA9685 pca9685;
pca9685.SetFrequency(100);
pca9685.Write(CHANNEL(0), VALUE(350));
}
void naza_interface_manual_c::fly_forward(int speed){
}
void naza_interface_manual_c::fly_backward(int speed){
}
void naza_interface_manual_c::fly_up(int speed){
}
void naza_interface_manual_c::fly_down(int speed){
}
void naza_interface_manual_c::fly_left(int speed){
}
void naza_interface_manual_c::fly_right(int speed){
}
Your Makefile doesn't install the header file. In fact, it also installs the shared object in a non-standard location: /usr/local. You want the library to go into /usr/local/lib and you need the header file installed in /usr/local/include.
Your Makefile is not consistent with conventional rules: You have no all rule, you are creating the library directly in the installation directory, instead of calling /usr/bin/install... I suggest you look into "proper" Makefile layout, if you want to distribute this. Users expect a lot of things from the Makefiles you give them; there are de-facto standards to follow.
If you want to use the library without having installed it, you need to provide the compiler the relevant include directive in your test.o: target; something like -Ipath/to/your/header.
Your compilation doesn't give the compiler the include path to find the header.
Instead, specify a base location and add the path to the compile. Otherwise if you can change the naza interface library, its install target should install the headers to a system (or $PREFIX/include) location.
test.o:
g++ -I$(NAZA_INTERFACE_LIB)/src/ -c test.cpp
I am trying to make a program that can manipulate matrixes and I am getting that error in Eclipse on Ubuntu 14.04. I searched on google and on stack over flow, but I did not find anything that I could understand and I am stuck. May anybody help me out with this please?
The complete error message:
14:29:27 **** Incremental Build of configuration Debug for project MatrixSample ****
make all
Building file: ../Matrix.inl
Invoking: GCC C++ Compiler
g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"Matrix.d" -MT"Matrix.d" -o "Matrix.o" "../Matrix.inl"
g++: warning: ../Matrix.inl: linker input file unused because linking not done
Finished building: ../Matrix.inl
Building target: MatrixSample
Invoking: GCC C++ Linker
g++ -o "MatrixSample" ./Main.o ./Matrix.o
g++: error: ./Matrix.o: No such file or directory
make: *** [MatrixSample] Error 1
Here is the code:
/*
* Main.cpp
*/
#include "Matrix.hpp"
int main()
{
Matrix<int> firstMatrix();
return 0;
}
/*
* Matrix.hpp
*
*/
#ifndef MATRIX_H_
#define MATRIX_H_
template <typename T>
class Matrix
{
public:
Matrix();
private:
int nbrRows;
int nbrColumns;
};
#include "Matrix.inl"
#endif /* MATRIX_H_ */
/*
* Matrix.inl
*/
template <typename T>
Matrix<T>::Matrix()
:nbrRows(0), nbrColumns(0){}
I found what the problem was. I added .inl files as C++ Source file instead of adding it to C++ Header file. Now it's working fine.
im new to programming in C++, but have some experience with Java. Ive created a very basic class called Dog.cpp and its header file Dog.hpp. Netbeans will not build the project, giving me an error stating multiple definitions of both the constructor and the getAge function. As far as I am concerned I have declared the constructor and function in the header file, and defined them in the class file. Where have i gone wrong?
Thanks in advance!
Dog.hpp:
#include <iostream>
using namespace std;
class Dog
{
public:
Dog(int someAge); // Constructor
~Dog(); // Destructor
int getAge() const; // function prototype
private:
int itsAge; // age variable
};
Dog.cpp:
#include "Dog.hpp"
using namespace std;
Dog::Dog(int anAge)
{
cout << "Dog created \n";
}
int Dog::getAge() const
{
return itsAge;
}
** main.cpp
#include <iostream>
#include "Dog.cpp"
int main()
{
Dog aDog(5);
cout << aDog.getAge();
return 0;
}
Netbeans output:
"/usr/bin/make" -f nbproject/Makefile-Debug.mk QMAKE= SUBPROJECTS= .build-conf
make[1]: Entering directory `/home/david/NetBeansProjects/C++/SAMS - Hour 10'
"/usr/bin/make" -f nbproject/Makefile-Debug.mk dist/Debug/GNU-Linux-x86/sams_-_hour_10
make[2]: Entering directory `/home/david/NetBeansProjects/C++/SAMS - Hour 10'
mkdir -p build/Debug/GNU-Linux-x86
rm -f build/Debug/GNU-Linux-x86/main.o.d
g++ -c -g -MMD -MP -MF build/Debug/GNU-Linux-x86/main.o.d -o build/Debug/GNU-Linux-x86/main.o main.cpp
mkdir -p build/Debug/GNU-Linux-x86
rm -f build/Debug/GNU-Linux-x86/Dog.o.d
g++ -c -g -MMD -MP -MF build/Debug/GNU-Linux-x86/Dog.o.d -o build/Debug/GNU-Linux-x86/Dog.o Dog.cpp
mkdir -p dist/Debug/GNU-Linux-x86
g++ -o dist/Debug/GNU-Linux-x86/sams_-_hour_10 build/Debug/GNU-Linux-x86/main.o build/Debug/GNU-Linux-x86/Dog.o
build/Debug/GNU-Linux-x86/Dog.o: In function `Dog::Dog(int)':
/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:12: multiple definition of `Dog::Dog(int)'
build/Debug/GNU-Linux-x86/main.o:/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:12: first defined here
build/Debug/GNU-Linux-x86/Dog.o: In function `Dog::Dog(int)':
/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:12: multiple definition of `Dog::Dog(int)'
build/Debug/GNU-Linux-x86/main.o:/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:12: first defined here
build/Debug/GNU-Linux-x86/Dog.o: In function `Dog::getAge() const':
/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:18: multiple definition of `Dog::getAge() const'
build/Debug/GNU-Linux-x86/main.o:/home/david/NetBeansProjects/C++/SAMS - Hour 10/Dog.cpp:18: first defined here
build/Debug/GNU-Linux-x86/main.o: In function `main':
main.cpp:(.text+0x6d): undefined reference to `Dog::~Dog()'
main.cpp:(.text+0x7f): undefined reference to `Dog::~Dog()'
collect2: error: ld returned 1 exit status
make[2]: *** [dist/Debug/GNU-Linux-x86/sams_-_hour_10] Error 1
make[2]: Leaving directory `/home/david/NetBeansProjects/C++/SAMS - Hour 10'
make[1]: *** [.build-conf] Error 2
make[1]: Leaving directory `/home/david/NetBeansProjects/C++/SAMS - Hour 10'
make: *** [.build-impl] Error 2
BUILD FAILED (exit value 2, total time: 931ms)
It seems that you included the cpp module (Dog.cpp) with the member function definitions in the module with function main. You should include only headers.
Change Main.cpp the following way
#include <iostream>
#include "Dog.hpp"
int main()
{
Dog aDog(5);
cout << aDog.getAge();
return 0;
}
Take into account that you forgot to set data member itsAge in the construtor. It should look as
Dog::Dog(int anAge) : itsAge( anAge )
{
cout << "Dog created \n";
}
And you forgot also to define the destructor.
You could write in the class definition for example the following way
class Dog
{
public:
Dog(int someAge); // Constructor
~Dog() = default; // Destructor
int getAge() const; // function prototype
private:
int itsAge; // age variable
};
provided that the compiler supports this specifier.
Try doing either this in your 'Dog.hpp':
#ifndef HEADER_GUARD // Top of file
#define HEADER_GUARD
/* Code in your class here. */
#endif // End of file
Or this at top of the file:
#pragma once
The former block of code will tell the preprocessor to only include the code within the guard as long as the header guard definition ("FILENAME_HPP" for instance) is not defined. It immediately gets defined if that conditional passes, so the code should only be loaded once.
The latter block will also work - and possibly be more effective - on most compilers, including g++ and Visual C++. It tells the compiler to process the file only once.
Also, you seem to be missing a definition for your class's destructor.
Another Edit: One more thing, it is very bad programming practice to #include .cpp files. Always #include the header files that are associated with them.