undefined reference to B::B & B::~B - c++

I keep getting complaint from the g++ compiler that the following code has problems.
After careful examination, I still cannot figure out why it cannot find the constructor and destructor of class B from embedMain.cpp.
Can someone give me a little hint?
Thank you
// embedMain.cpp
#include "embed.h"
int main(void)
{
B b("hello world");
return 0;
}
,
// embed.h
#ifndef EMBED_H
#define EMBED_H
#include <string>
class B
{
public:
B(const std::string& _name);
~B();
private:
std::string name;
};
#endif
,
// embed.cpp
#include <iostream>
#include <string>
#include "embed.h"
B::B(const std::string& _name) : name(_name) {}
B::~B() {
std::cout << "This is B::~B()" << std::endl;
}
,
~/Documents/C++ $ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
~/Documents/C++ $ g++ -o embedMain embedMain.cpp
/tmp/ccdqT9tn.o: In function `main':
embedMain.cpp:(.text+0x42): undefined reference to `B::B(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
embedMain.cpp:(.text+0x6b): undefined reference to `B::~B()'
embedMain.cpp:(.text+0x93): undefined reference to `B::~B()'
collect2: ld returned 1 exit status
// Updated //
Based on comments from experts here, I have found the right way to link the embedMain.cpp with the embed library.
Here is the detail step:
user#ubuntu:~/Documents/C++$ tree
.
├── embed.cpp
├── embed.h
├── embedMain.cpp
user#ubuntu:~/Documents/C++$ g++ -Wall -c embed.cpp
user#ubuntu:~/Documents/C++$ ar -cvq libembed.a embed.o
user#ubuntu:~/Documents/C++$ g++ -o embedMain embedMain.cpp -L/home/user/Documents/C++ -lembed
user#ubuntu:~/Documents/C++$ tree
.
├── embed.cpp
├── embed.h
├── embedMain
├── embedMain.cpp
├── embed.o
├── libembed.a

You need to compile embed.cpp and link it into your executable, like so:
g++ -o embedMain embedMain.cpp embed.cpp
This compiles both files and links everything. To separate the three steps:
g++ -c embed.cpp
g++ -c embedMain.cpp
g++ -o embedMain embedMain.o embed.o

You also have to include embed.cpp in your compile/link.

Related

C++ undefined reference in Makefile

I created my Makefile for a simple program but it returns undefined reference for class functions constantly:
g++ -c src/main.cpp -o lib/main.o
g++ -c src/functions.cpp -o lib/functions.o
g++ -c src/Circular.cpp -o lib/Circular.o
g++ lib/main.o -o bin/app.exe
c:/mingw/bin/../lib/gcc/mingw32/9.2.0/../../../../mingw32/bin/ld.exe: lib/main.o:main.cpp:(.text+0x20): undefined reference to `Circular::Circular()'
collect2.exe: error: ld returned 1 exit status
make.exe: *** [app.exe] Error 1
Here is my Makefile:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o -o bin/app.exe
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
Here is a short snippet of main.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include "../include/Circular.h"
#include "../include/functions.h"
using namespace std;
int main(int argc, const char * argv[]) {
Circular item;
return 0;
}
Circular.h:
#include "node.h"
class Circular
{
public:
Circular();
node *start;
node *last;
int counter;
}
Circular.cpp:
#include "../include/Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
}
and node.h:
struct node
{
int data;
struct node *next;
struct node *prev;
};
I know the problem is about linker and with Makefile but even though I tried different possible solutions, somehow it doesn't work. Therefore, maybe someone can see the mistake I am making. Thanks!
I managed to create a Makefile from this source .
The Makefile looks like this:
CXX = g++
CXXFLAGS = -std=c++17 -Wall
LXXFLAGS = -std=c++17
OBJECTS = main.o Circular.o functions.o
TARGET = main
$(TARGET): $(OBJECTS)
$(CXX) $(LXXFLAG) $(OBJECTS) -o $(TARGET)
main.o: main.cpp Circular.cpp Circular.h functions.cpp functions.h
$(CXX) $(CXXFLAGS) -c main.cpp
Circular.o: Circular.cpp
$(CXX) $(CXXFLAGS) -c Circular.cpp
functions.o: functions.cpp
$(CXX) $(CXXFLAGS) -c functions.cpp
clean:
rm -f $(TARGET) $(OBJECTS)
And also added cout to you Circular constructor to check the execution as below:
#include "Circular.h"
#include <iostream>
using namespace std;
Circular::Circular()
{
start = NULL;
last = NULL;
cout << "Yes!" << endl;
}
Here's the result:
Output
Don't forget to put a semicolon for your Circular class in your Circular.h.
NOTE: If you aren't able to use make in cmd,use choco install make.
The Makefile should be structured to build the dependencies, then the final assembly into a .exe. Each path should be specified exactly as it is, not approximated:
app.exe: lib/main.o lib/Circular.o lib/functions.o
g++ lib/main.o lib/Circular.o lib/functions.o -o app.exe
lib/main.o: src/main.cpp
g++ -c src/main.cpp -o lib/main.o
lib/functions.o: src/functions.cpp
g++ -c src/functions.cpp -o lib/functions.o
lib/Circular.o: src/Circular.cpp
g++ -c src/Circular.cpp -o lib/Circular.o
The key here is be consistent and that includes things like the order of things specified in this file. Whatever order you pick, stick to it. This makes tracking down problems way easier.
If this project gets more complex you probably want to pivot to using a dependency tracking Makefile template instead of this homebrew one. Note how in those you don't need to specify a rule for each file, but instead a rule for each type of file, as in .cpp -> .o, and the rest happens automatically.

Using shared library within shared library

I want to use a shared library within a shared library but g++ is complaining...
That is how my test sample looks:
.
├── extA
│   ├── a.cpp
│   ├── a.h
│   └── libA.so
├── extB
│   ├── b.cpp
│   ├── b.h
│   └── libB.so
└── main.cpp
a.h:
#pragma once
int f(void);
a.cpp:
#include "a.h"
int f(void) {
return 42;
}
b.h:
#pragma once
#include "a.h"
int g(void);
b.cpp:
#include "b.h"
int g(void) {
return f();
}
main.cpp:
#include <cstdlib>
#include <iostream>
#include "b.h"
int main(int, char **) {
std::cout << g() << std::endl;
return EXIT_SUCCESS;
}
I pretty sure that my way of compiling is wrong. That is what I do:
g++ -c -fpic a.cpp
g++ -shared -o libA.so a.o
to create libA.so,
g++ -c -fpic -I../extA b.cpp -L../extA -lA
g++ -shared -o libB.so b.o
to create libB.so (I think this way is incorrect) and finally:
g++ -IexB main.cpp -LextB -lB -o main
The last g++-call leads to the error msg:
In file included from main.cpp:4:0:
extB/b.h:3:15: fatal error: a.h: No such file or directory
#include "a.h"
^
compilation terminated.
Can someone tell me, what is the right way to compile/create libB.so?
main.cpp:4:15: fatal error: b.h: No such file or directory
#include "b.h"
^
The error is nothing to do with libB.so it means main.cpp cannot find b.h, which is a problem finding headers, nothing to do with the shared library file.
If b.h is not in the same directory as main.cpp then you need to tell the compiler how to find the header, e.g. by using -IextB when compiling main.cpp
The file main.cpp includes the header b.h and uses the function g() defined in libB.so so why are you compiling main.cpp telling it how to find a.h and linking to libA.so? It doesn't need that header or that library!
You probably just want to change A to B since that's what main.cpp actually depends on:
g++ -IextB main.cpp -LextB -lB -o main
I found the solution.
The correct way to compile libB.so is:
g++ -c -fpic -I../extA b.cpp
g++ -shared -o libB.so b.o -L../extA -lA

A simple makefile with chain dependencies. "linker input file unused because linking not done" and g++ -c

I just started using makefiles and came across a problem. (C++ project)
I'm trying to make a dependency chain:
main.cpp depends on class a. And class a depends on class b.
The main idea is to recompile class a using the allready compiled class b, while class a doesn't have the main() function. (When class a is modified)
Here is my makefile:
makefile
all: main.o
main.o: main.cpp classa.o
g++ main.cpp classa.o -o main.o
classa.o: classa.h classa.cpp classb.o
g++ -c classa.cpp classb.o -o classa.o
classb.o: classb.h classb.cpp
g++ -c classb.cpp -o classb.o
And the code:
main.cpp
#include "classa.h"
int main() {
ClassA a;
return 0;
}
classa.h
#ifndef CLASSA_H
#define CLASSA_H
#include "classb.h"
class ClassA {
private:
ClassB b;
public:
ClassA();
};
#endif // CLASSA_H
classa.cpp
#include "classa.h"
ClassA::ClassA() {
}
classb.h
#ifndef CLASSB_H
#define CLASSB_H
class ClassB {
public:
ClassB();
};
#endif // CLASSB_H
classb.cpp
#include "classb.h"
ClassB::ClassB() {
}
The Problem:
When i use make -f makefile i get the following error:
g++ -c classb.cpp -o classb.o
g++ -c classa.cpp classb.o -o classa.o
g++: warning: classb.o: linker input file unused because linking not done
g++ main.cpp classa.o -o main.o
classa.o: In function `ClassA::ClassA()':
classa.cpp:(.text+0x18): undefined reference to `ClassB::ClassB()'
collect2: error: ld returned 1 exit status
makefile:4: recipe for target 'main.o' failed
make: *** [main.o] Error 1
I believe that it starts on reusing classb.o with the parameter -c.
To me -c is a magical "use when i compile code without the main() function" parameter.
I would be happy if you could enlighten me where i did go wrong, and wether what i'm trying to do is possible.
Regards, chocolateftw
Your makefile should look more like this:
all: main
main: main.cpp classa.o classb.o
g++ main.cpp classa.o classb.o -o main
classa.o: classa.h classa.cpp
g++ -c classa.cpp -o classa.o
classb.o: classb.h classb.cpp
g++ -c classb.cpp -o classb.o
You build .o files from .cpp files and then link .o files into the final output (also built from a .cpp file).
You need to list all relevant object files when linking and do not need to list them when only compiling (which is what happens when you use the -c flag which tells gcc to skip the linking step).
The key here is that classa.o does not depend on classb.o or classb.cpp (it probably does depend on classb.h though in which case you might want to add that to the requirements). The fully linked binary depends on both of them and they then depend on each other as needed.
That said you can dramatically simplify the above makefile by not specifying your own rules and simply using the built-in rules. The following makefile should do what you want.
all: main
main: classa.o classb.o
classa.o: classa.h
classb.o: classb.h
If you need custom compiler/linker flags later you can use the default variables to have them used on the appropriat lines. See 10.3 Variables Used by Implicit Rules and 10.2 Catalogue of Built-In Rules for the variables and what rules use them.

Undefined reference to function in g++ while using static linking on Linux

I am learning programming under Linux, and I faced the following problem during linking.
My directory structure
libraries
|-- archive_sample
| |-- calc.h
| |-- calc.cpp
| |-- makefile
|
|-- test_archive
|-- main.cpp
|-- makefile
calc.h
#ifndef __CALC__H__
#define __CALC__H__
int add(int a, int b);
int sub(int a, int b);
#endif
calc.cpp
#include "calc.h"
int add(int a, int b)
{
return (a + b);
}
int sub(int a, int b)
{
return (a - b);
}
File archive_sample/makefile:
libcalc.a : calc.o
ar rcs libcalc.a calc.o
calc.o : calc.cpp calc.h
g++ $(CFLAGS) -c calc.cpp
clean :
rm -f libcalc.a calc.o
When I run "make" from archive_sample directory, it executes successfully and calc.o and libcalc.a are created in the same directory.
main.cpp
int main()
{
int a, b;
std::cin >> a >> b;
std::cout << "a + b : " << add(a, b) << std::endl;
std::cout << "a - b : " << sub(a, b) << std::endl;
return (0);
}
Compiling with
g++ -c -I../archive_sample main.cpp
succeeds and main.o is created. However linking with
g++ -L../archive_sample -lcalc main.o -o test
gives the following error:
main.o: In function main:
main.cpp:(.text+0x3e): undefined reference to add(int, int)
main.cpp:(.text+0x84): undefined reference to sub(int, int)
collect2: error: ld returned 1 exit status
Where am I going wrong?
Also "make" is also not working for the following makefile.
test_archive/makefile
test : main.o
g++ -L../archive_sample -lcalc main.o
main.o : main.cpp calc.h
g++ $(CFLAGS) -c -I../archive_sample main.cpp
clean :
rm -f test *.o
with error
make: *** No rule to make target `calc.h', needed by `main.o'. Stop.
How can I fix this problem?
For the first error, since main.cpp and archive_sample are in the same directory, you shouldn't specify -Larchive_sample rather than -L../archive_sample.
For the second error, your calc.h is in the archive_sample directory, so the dependency should be listed as archive_sample/calc.h.

C++ Undefined Reference (Even with Include)

I cannot get this simple piece of code to compile without including the TestClass.cpp file explicitly in my main.cpp file. What am I doing wrong? Thanks in advance!
Here is the code:
TestClass.h
#ifndef TESTCLASS_H_
#define TESTCLASS_H_
class TestClass
{
public:
static int foo();
};
#endif
TestClass.cpp
#include "TestClass.h"
int TestClass::foo() { return 42; }
main.cpp
#include <iostream>
#include "TestClass.h"
using namespace std;
int main()
{
cout << TestClass::foo() << endl;
return 0;
}
Here is the error:
g++ main.cpp -o main.app
/tmp/ccCjOhpy.o: In function `main':
main.cpp:(.text+0x18e): undefined reference to `TestClass::foo()'
collect2: ld returned 1 exit status
Include TestClass.cpp into the commandline, so the linker can find the function definition:
g++ main.cpp TestClass.cpp -o main.app
Alternatively, compile each to their own object file, then tell the compiler to link them together (it will forward them to the linker)
g++ -c main.cpp -o main.o
g++ -c TestClass.cpp -o TestClass.o
g++ main.o TestClass.o -o main.app
You're not compiling and linking against TestClass.cpp (where the implementation of foo() is). The compiler is thus complaining that your trying to use an undefined function.