I am trying to compile and link three files into an executable with a makefile, but seem to have redefined main or somehow goofed the compile/link process. The project is for a class, where the objective is to implement a linear feedback shift register, but we have to use a makefile.
Where have I redefined main? How do I alter my makefile to create my executable? I notice the error points to test.o as having redefined main, but I'm not sure why or how.
Error:
g++ -c main.cpp LFSR.cpp -Wall -Werror -ansi -pedantic
g++ -c test.cpp -Wall -Werror -ansi -pedantic
g++ main.o LFSR.o test.o -o ps2a -lboost_unit_test_framework
test.o: In function `main':
test.cpp:(.text+0xa3): multiple definition of `main'
main.o:main.cpp:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'ps2a' failed
make: *** [ps2a] Error 1
My makefile:
all: ps2a
ps2a: main.o LFSR.o test.o
g++ main.o LFSR.o test.o -o ps2a -lboost_unit_test_framework
LFSR.o: LFSR.cpp LFSR.hpp
g++ -c LFSR.cpp -Wall -Werror -ansi -pedantic
main.o: main.cpp LFSR.hpp
g++ -c main.cpp LFSR.cpp -Wall -Werror -ansi -pedantic
test.o: test.cpp
g++ -c test.cpp -Wall -Werror -ansi -pedantic
clean:
rm *.o ps2a
main.cpp:
#include "LFSR.hpp"
int main(){
}
LFSR.hpp
#include <string>
#include <iostream>
class LFSR{
public:
LFSR(std::string, int);
int step();
int generate(int k);
private:
std::string bitString;
int tapPos;
};
LFSR.cpp:
#include "LFSR.hpp"
void makeBitStringValid(std::string& str);
LFSR::LFSR(std::string str, int t){
}
int LFSR::step(){
return 0;
}
int LFSR::generate(int k){
return 0;
}
void makeBitStringValid(std::string& str){
}
test.cpp (Note, this is given by the instructor-- I'm not entirely sure how it works yet)
#include <iostream>
#include <string>
#include "LFSR.hpp"
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE(fiveBitsTapAtTwo) {
LFSR l("00111", 2);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 0);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 1);
BOOST_REQUIRE(l.step() == 0);
LFSR l2("00111", 2);
BOOST_REQUIRE(l2.generate(8) == 198);
}
Do not provide own main because The Boost Unit Test Framework already provides one in your test.cpp with the lines:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
Dynamic library variant of the UTF
Unlike the static library variant function main() can't reside in the
dynamic library body. Instead this variant supplies default function
main() implementation as part of the header boost/test/unit_test.hpp
to be generated as part of your test file body. The function main() is
generated only if either the BOOST_TEST_MAIN or the BOOST_TEST_MODULE
flags are defined during a test module compilation. For single-file
test module flags can be defined either in a test module's makefile or
before the header boost/test/unit_test.hpp inclusion. For a multi-file
test module flags can't be defined in makefile and have to be defined
in only one of the test files to avoid duplicate copies of the
function main().
Related
I need to access a C++ function from C but I get some error like :-
/tmp/ccUqcSZT.o: In function `main':
main.c:(.text+0x5): undefined reference to `load_alert_to_db'
collect2: error: ld returned 1 exit status
My main.c code is:-
#include <stdio.h>
extern void load_alert_to_db(void);
int main(void){
/* Create empty queue */
load_alert_to_db();
return 0;
}
C++ code implementation db_manager.cpp is:-
#include <sstream>
#include <iostream>
#include <sstream>
#include <string>
#include <ctime>
#include <cstdlib>
#include <algorithm>
#include <time.h>
#include <cstring>
#include <fstream>
//using namespace oracle::occi;
#include <iostream>
using namespace std;
extern "C" void load_alert_to_db(void)
{
cout<<"db occi"<<endl;
}
makefile is:-
CC= g++
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
clean:
rm -f *.o data
so please help me which one is my problem. I am also include
export LD_LIBRARY_PATH=/home/oracle/Desktop/storage/:$LD_LIBRARY_PATH
environmental variable in .bash_profile
gcc -o data main.c
Not sure why you have this line in your makefile since it will compile main.c without reference to the previously created library and hence cause an undefined-symbol error such as the one you're seeing.
This is especially so, since you appear to have done it the right way on the preceding line:
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
However, the entire point of using makefiles is so that it figures out the minimum necessary commands for you, based on dependencies. Lumping a large swathe of commands into a single rule tends to defeat that purpose. You would be better off making your rules a little more targeted, such as (untested but should be close):
all: data
data: main.o libdb_manager.so
gcc -o data main.o -ldb_manager
main.o: main.c
gcc -o main.o main.c
libdb_manager.so: db_manager.cpp
g++ -c -Wall -Werror -fPIC -o db_manager.o db_manager.cpp
g++ -shared -o libdb_manager.so db_manager.o
That way, if you make a small change to one part (like main.c), it doesn't have to go and compile/link everything in your build tree.
Your makefile seems to be completely broken and random, and you're not even linking the required object files. You can simplify this:
all:
$(CC) -c -Wall -Werror -fPIC db_manager.cpp
$(CC) -shared -o libdb_manager.so db_manager.o
gcc -L/home/oracle/Desktop/storage/ -Wall main.c -o data -ldb_manager
gcc -o data main.c
to just this:
all:
gcc -Wall -c main.c
g++ -Wall -c db_manager.cpp
g++ main.o db_manager.o -o data
this is what I needed to do:
Supposing the C++ function is called Debug::Write(str)
Then in your hpp file do the following:
#ifdef __cplusplus
extern "C" void DebugTmp(char *str);
#endif
Then in the corresponding cpp file do this:
void DebugTmp(char *str)
{
Debug::Write(str);
}
Then in your C file where you call DebugTmp define the prototype:
void DebugTmp(char *str);
then call it as below:
static void MyFunction( void )
{
DebugTmp("This is debug trace\n");
}
I have 3 files; main.cpp (which contains main()), FileWriter.h, and FileWriter.cpp. I'm using g++ (version Debian 4.9.2-10) on Debian Jessie. My project contains .cpp files in '/root/dev/Practice/src/', and a single header (FileWriter.h) in '/root/dev/Practice/include/'. The compilation of the two object files works, but the linking to an executable complains about undefined reference to main(), although I do indeed have a seemingly valid one defined in 'main.cpp'.
Here's the output of my make file (which is in the root '/root/dev/Practice/' directory):
g++ -c -g -Wall -o src/FileWriter.o src/FileWriter.cpp
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
g++ src/FileWriter.o src/main.o -o bin/Practice
/usr/lib/gcc/i586-linux-gnu/4.9/../../../i386-linux-gnu/crt1.o: In function '_start'"
/build/glibc-J1NNmk/glibc-2.19/csu/../sysdeps/i386/start.S:111: undefined reference to 'main'
collect2: error: ls returned 1 exit status
Makefile:10: recipe for target 'bin/Practice' failed
Here's the contents of my main.cpp file:
#include <string>
#include <iostream>
#include "/root/dev/Practice/include/FileWriter.h"
int main() {
std::cout << "Hello!" << std::endl;
FileWriter * fw = new FileWriter("foofile");
fw->AddLine("CRAP!");
fw->AddLine("NO!");
return 0;
}
My FileWriter.h:
#ifndef FILEWRITER_H_
#define FILEWRITER_H_
#include <string>
#include <iostream>
class FileWriter{
public:
FileWriter(std::string);
~FileWriter();
void AddLine(std::string);
private:
std::string fileLocation;
std::ofstream *filestream;
};
#endif /* FILEWRITER_H_ */
...and my FileWriter.cpp:
#include "/root/dev/Practice/include/FileWriter.h"
#include <fstream>
// g++ linker error if 'inline' not included - why?
inline FileWriter::FileWriter(std::string fileName)
{
this->fileLocation = fileName;
const char * x = this->fileLocation.c_str();
this->filestream = new std::ofstream();
this->filestream->open(x, std::ios::out | std::ios::app);
}
inline FileWriter::~FileWriter()
{
this->filestream->close();
}
inline void FileWriter::AddLine(std::string line)
{
*this->filestream << line << std::endl;
}
This line:
g++ -c -g -Wall -o src/main.o src/FileWriter.cpp
should be:
g++ -c -g -Wall -o src/main.o src/main.cpp
I don't have access to this compiler, but in the past if you had main() in a C++ file you needed to "decorate" it with __cdecl
int __cdecl main() {
Try that? Or:
extern "C" int main() {
So I wrote a small set of logging functions in the file cerus.h. The contents of that file can be seen below. It is being included in main.cpp, model.cpp, engine.cpp and camera.cpp. As can be seen, I have include guards so I'm not sure why I'm getting this error:
Output of $ make
jed#ArchPC:~/glPlayground$ make
g++ -std=c++11 -c model.cpp -o bin/model.o
g++ -std=c++11 -c tiny_obj_loader.cc -o bin/tinyobj.o
g++ -std=c++11 -c camera.cpp -o bin/camera.o
g++ -g -std=c++11 -o main bin/main.o bin/engine.o bin/tinyobj.o bin/model.o bin/camera.o -lGL -lGLU -lglut -lSOIL -lGLEW -lglfw
bin/engine.o: In function `LOG(char const*)':
engine.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/engine.o: In function `LOGERR(char const*)':
engine.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
bin/model.o: In function `LOG(char const*)':
model.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/model.o: In function `LOGERR(char const*)':
model.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
bin/camera.o: In function `LOG(char const*)':
camera.cpp:(.text+0x0): multiple definition of `LOG(char const*)'
bin/main.o:main.cpp:(.text+0x0): first defined here
bin/camera.o: In function `LOGERR(char const*)':
camera.cpp:(.text+0x3d): multiple definition of `LOGERR(char const*)'
bin/main.o:main.cpp:(.text+0x3d): first defined here
collect2: error: ld returned 1 exit status
Makefile:4: recipe for target 'main' failed
make: *** [main] Error 1
cerus.h
#ifndef CERUS_H
#define CERUS_H
#include <iostream>
//Need to add Windows and Mac Includes here
// Linux Include Statements
void LOG(const char* str){
std::cout << "[INFO]" << str << "\n";
}
void LOGERR(const char* str){
std::cout << "[ERROR]" << str << "\n";
}
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <GLFW/glfw3.h>
#endif
Makefile
all: main
main: bin/main.o bin/engine.o bin/model.o bin/tinyobj.o bin/camera.o cerus.h
g++ -g -std=c++11 -o main bin/main.o bin/engine.o bin/tinyobj.o bin/model.o bin/camera.o -lGL -lGLU -lglut -lSOIL -lGLEW -lglfw
bin/main.o: main.cpp cerus.h
g++ -std=c++11 -c main.cpp -o bin/main.o
bin/engine.o: engine.cpp engine.h cerus.h
g++ -std=c++11 -c engine.cpp -o bin/engine.o
bin/tinyobj.o: tiny_obj_loader.cc tiny_obj_loader.h cerus.h
g++ -std=c++11 -c tiny_obj_loader.cc -o bin/tinyobj.o
bin/model.o: model.cpp model.h cerus.h
g++ -std=c++11 -c model.cpp -o bin/model.o
bin/camera.o: camera.cpp camera.h cerus.h
g++ -std=c++11 -c camera.cpp -o bin/camera.o
clean:
rm -f bin/*.o main
If someone could explain to me why my guard isn't catching this, I would greatly appreciate the help.
EDIT: Fixed this issue by adding a file called cerus.cpp and defining my logging functions there instead of in cerus.h
This type of guard is to avoid things from being declared or defined in same translation unit.
It won't have any effect for multiple definition in different translation units (i.e. multiple source files).
In this case, you should move the definitions of functions LOG and LOGERR to another .cpp file, and put declarations of the functions in the header file.
Guards did nothing wrong, they just protect your declarations/inlines/templates.
It's the definitions that are real issue. If you have inline functions in your cpp, put them in header, same for templates. Do not include cpp files. Can't see much of your code but that is most of the cases.
I'm learning to program C++ in Linux, and I have the following problem:
I have 4 files: main.cpp, model.cpp, view.cpp and controller.cpp, each (except main) with their own header files. main.cpp includes model.h, view.h and controller.h, and view.h includes other libraries that are only relevant to it (necessary to run the graphic library). Those libraries are in different folders and have other dependencies on their own (that's why I don't want to move them). So, my makefile looks as follows:
model: model.cpp model.h
g++ -c model.cpp
view: view.cpp view.h
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
controller: controller.cpp
g++ -c controller.cpp
main: main.cpp
g++ -c main.cpp
and also a line to link all the files together (I didn't added it because I'm writing this on my Mac and copying it from the screen of my Raspberry Pi).
My problem is that when I try to compile them, all of them work, except for main, it tells me the following:
In file included from main.cpp:6:0:
view.h:4:23: fatal error: VG/openvg.h: No such file or directory
compilation terminated.
make: *** [main] Error 1
From what I can understand, when I compile view with "make view", it can find the files included without problem, because it has the paths in which it must look, but since "make main" doesn't have those paths, it doesn't know where to look for openvg.h. The problem is that if I add the paths to main, it tells me that there's multiple definitions for what's inside the library... Any help?
The #include VG/openvg.h is in /opt/vc/include and is included from view.h
When you make view you are including it from view.cpp which is compiled with -I/opt/vc/include
When you make main you are including it from main.cpp which is compiled without flags so it can't find the file.
You need to add the flags
main: main.cpp
g++ -c -I/opt/vc/include main.cpp
You may need the other flags as well, depending on what view.h includes.
The multiple definitions are caused by $(OPENVGLIBDIR)/fontinfo.h
which contains
Fontinfo SansTypeface, SerifTypeface, MonoTypeface;
so if you include that file in more than one object file and link them (main.o and view.o in this case) you will get multiple definitions.
Change it to
extern Fontinfo SansTypeface, SerifTypeface, MonoTypeface;
I then got Background etc undefined as libshapes is a C library. To get round this I changed
#include "fontinfo.h"
#include "shapes.h"
in view.h to
extern "C" {
#include "fontinfo.h"
#include "shapes.h"
}
and it builds for me (with references to model and controller removed).
In your makefile, the view/model/controller/main targets are making the .o files so they should be .o too. When you make test when no .o exists, it is looking for the .o target. If there isn't one in your makefile it will use the default which is a straight g++ -c.
Your make file should be like this:
test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg
view.o: view.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
main.o: main.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp
model.o: model.cpp
g++ -c model.cpp
controller.o: controller.cpp
g++ -c controller.cpp
here are my files, the code seems to run fine if in main.cpp I include view.cpp instead of view.h, but I don't think that's what I'm supposed to be doing:
main.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include "model.h"
#include "view.h"
#include "controller.h"
using namespace std;
int main() {
int n;
View view;
view.initialize();
view.drawBackground();
view.show();
std::cin >> n;
}
view.h:
#ifndef VIEW_H
#define VIEW_H
#include "VG/openvg.h"
#include "VG/vgu.h"
#include "fontinfo.h"
#include "shapes.h"
class View{
private:
int width, height;
public:
View();
int getWidth();
int getHeight();
void drawBackground();
void initialize();
void show();
};
#endif
view.cpp
#include "view.h"
View::View(){
int width, height;
VGfloat w2, h2, w;
}
int View::getWidth(){
return width;
}
int View::getHeight(){
return height;
}
void View::drawBackground(){
Background(0,0,0);
Stroke(255,255,255,1);
Fill(255,0,0,1.0);
Circle(width/2, height/2, 100);
}
void View::initialize(){
init(&width, &height);
Start(width, height);
}
void View::show(){
End();
}
Thanks A LOT for your help man! I've been fighting with this for the last couple of days (that's what I get for getting used to automatic compiling/linking). It's somewhat based on that example. I can make it run if I make each object by itself and then link them all together like this:
test: model.o view.o controller.o main.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)/oglinit.o
g++ -o test view.o main.o model.o controller.o $(OPENVGLIBDIR)/libshapes.o $(OPENVGLIBDIR)oglinit.o -L/opt/vc/lib -L/opt/vc/include -lGLES -ljpeg
view: view.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c view.cpp
main: main.cpp
g++ -I/opt/vc/include -I/opt/vc/include/interface/vcos/pthreads -I.. -c main.cpp view.cpp
model: model.cpp
g++ -c model.cpp
controller: controller.cpp
g++ -c controller.cpp
if I do "make view" "make main" and then "make test" everything goes fine, but if I try "make test" without any object created prior to that I get fatal error: VG/openvg.h: No such file or directory when it's trying to compile view.cpp
example.h:
#ifndef EXAMPLE_H
#define EXAMPLE_H
class Math {
public:
int pi() const;
void pi(int pi);
private:
int _pi;
};
#endif
example.cpp:
#include "example.h"
int Math::pi() const {
return this->_pi;
}
void Math::pi(int pi) {
this->_pi = pi;
}
example.swig:
%module example
%{
#define SWIG_FILE_WITH_INIT
#include "example.h"
%}
%include "example.h"
I then generate the wrappers, "example.py" and "example_wrap.c" using:
swig -python example.swig
When I try to compile the wrapper class using:
g++ -fPIC -c example.cpp example_wrap.c -I/usr/local/include/python2.6/
I get the following error:
example_wrap.cpp: In function "PyObject* Swig_var_Math_get()":
example_wrap.cpp:2725: error: expected primary-expression before "void"
example_wrap.cpp:2725: error: expected ")" before "void"
The Error is at the following line :
pyobj = SWIG_NewPointerObj(SWIG_as_voidptr(&Math), SWIGTYPE_p_class, 0 );
#define SWIG_as_voidptr(a) (void *)((const void *)(a))
Is it the right way to generate the wrapper class "example_wrap.c"?
I think the swig command should be "swig -c++ -python example.swig"
There's not enough information here to be sure what's wrong, but I have two ideas for things you can try.
Your g++ invocation is compiling a C source file as if it were C++. This is not guaranteed to work. Try instead
gcc -I/usr/local/include/python2.6 -fPIC -c example_wrap.c
gcc -I/usr/local/include/python2.6 -fPIC -c example.cpp
g++ -shared example_wrap.o example.o -o example.so
(yes, srsly, only use g++ for the link)
If that doesn't work, compile example_wrap.c like this:
gcc -I/usr/local/include/python2.6 -fPIC -c -save-temps example_wrap.c
That will fail the same way but will produce a file named example_wrap.i which is the result of preprocesing. It will be gigantic. Search that file for the function Swig_var_Math_get, and add to your question the complete text of that function (but nothing else).
Thanks for your replay!
The -C++ option generated the C++ class for the wrapper.
swig -c++ -v -python example.swig
I used g++ to compile the wrapper.
g++ -fPIC -c example.cpp example_wrap.cxx -I/usr/local/include/python2.6/
And the following command to buikd the shared object. Ofcourse, we need to remove the superflous includes (-I) and libraries (-L). The important flags are '-shared' and '-fPIC'.
g++ example_wrap.o example.o -L/u01/app/oracle/product/1020.full/lib -I/usr/local/ssl/include -L/usr/local/ssl/lib -lclntsh -lssl -lcrypto -ldl -L/usr/local/lib -L/lib64 -L/usr/local/lib/python2.6/ -lboost_system -lboost_filesystem -lboost_thread -lboost_date_time -lglog -lmodpbase64 -lpthread -ldl -lrt -shared -fPIC -o _example.so