Problems linking static library to c++ project with MinGW - c++

Edit: ***Sorry I realize there must have been some misunderstanding when posting this question, I want to specify that I DO realize this question was asked a few times, none of the answers work for me however***
I've been trying to link a simple static library test to one of my c++ projects, but I can't seem to get it quite right. I know that this is a very widespread topic and that a lot of people have already asked a similar question, but even after reading some of the answers, I still cannot, for the love of god, figure out what I am doing wrong.
My code is very simple, first I have a .cpp source file titled "Math.cpp" that looks like this:
#include "Math.h"
int max(int a, int b) {
return a > b ? a : b;
}
int min(int a, int b) {
return a < b ? a : b;
}
int floor(double a) {
return (int) a;
}
int ceil(double a) {
return (int) a + 1;
}
..And to go with that I made a header file called "Math.h" that looks like this:
#pragma once
int max(int, int);
int min(int, int);
int floor(double);
int ceil(double);
I then compile "Math.cpp" with the following command on cmd:
g++ -c Math.cpp -o Math.o
...and then compile it into a static library like so:
ar rcs libMath.a Math.o
After all of this I make a new c++ soure file titled "Main.cpp" that looks like this:
#include <iostream>
#include "Math.h"
int main() {
std::cout << max(9, 8) << std::endl;
return 0;
}
("Math.h" is in the same directory as "Main.cpp")
So finally in order to link "Main.cpp" with my static library ("libMath.a"), I use the following command in cmd:
g++ -o Main.exe Main.cpp -L. -lMath
however, at this point, it throws the following error:
C:\Users\zalmar\AppData\Local\Temp\ccmOnvyg.o:Main.cpp:(.text+0x18): undefined reference to `max(int, int)'
collect2.exe: error: ld returned 1 exit status
... I cannot figure out why it can't find the reference to the specific function. Some people appeared to have the same problem (here for example). Their solution was to declare the Main.cpp source file before declaring the library path. However, that was not the case for me, even though I made sure I was linking the library after the Main.cpp it still came up with the same error. I would greatly appreciate it if someone could point out anything I might be doing wrong because clearly I must be doing something wrong. Otherwise it might be a problem with my MinGW compiler, maybe?
I also want to re-mention that this is just a test library and I am fully aware that it might be a bit overkill to compile an entire static library from such a simple program. I am simply trying to figure out how to link libraries to my c++ projects...

Related

Should I #include .cpp files to header of TestSuite to make cxxtest work?

Situation is as follows: I've got a simple project consisting of two files - Calc.h and Calc.cpp.
Calc.h:
#pragma once
class Calc {
public:
int add(int,int);
static const int a = 42;
}
Calc.cpp:
#include "Calc.h"
class Calc {
public:
int add(int a,int b){
return a + b;
};
}
CalcTestSuite.h:
#pragma once
#include "Calc.h"
#include <cxxtest/TestSuite.h>
class CalcTestSuite : public CxxTest::TestSuite {
public:
void testAddition(void)
{
Calc calculator;
TS_ASSERT_EQUALS(calculator.a, 42);
TS_ASSERT_EQUALS(calculator.add(1,2), 3);
}
}
The problem
The problem being is, when I do cxxtestgen --error-printer -o runner.cpp CalcTestSuite.h && g++ -I$cxxtest -o runner.o runner.cpp && ./runner.o, an error occurs:
runner.cpp: (.text._ZN13...(many letters)): undefined reference to `Calc::add(int,int)`
Undoubtedly, the reason of that is wrong compiling as I compile code outside of Visual Studio 2019 or other IDE.
How I tried to solve the problem:
I see a couple of solutions:
1.) Leave build command as is and add #include "Calc.cpp" to TestSuite file, which will obviously work but would be a bad practice.
2.) Add Calc.cpp to g++ command: g++ -I$cxxtest -o runner.o Calc.cpp runner.cpp && ./runner.o, however, it leads to another problem:
Calc.cpp:3:7: error: redefinition of 'class Calc'
In that case I also tried changing #pragma once to #ifndef CALC_H... block in Calc.h, but the error remained.
I tried searching for real-world cxxtest code examples, but didn't find the site I've seen long ago. I would be glad to recieve any tips on what's the best way to deal with this issue.
And if you know the site where I can search for real-life code snippets I would be glad if you shared it.
There are two problems:
You are violating One Definition Rule! You can't redefine Calc like this:
#include "Calc.h"
class Calc {
public:
int add(int a,int b){
return a + b;
};
}
It must be:
#include "Calc.h"
int Calc::add(int a,int b) {
return a + b;
};
const int Calc::a;
Now this problem do not surfaces since you do not build this cpp and you should.
You didn't explain how you are building you code. Simplest way when it is done manually it can look like this:
cxxtestgen --error-printer -o CalcTestSuite.cpp CalcTestSuite.h
g++ -std=c++17 -Wall -Wextra Calc.cpp CalcTestSuite.cpp -o test
Offtopic: this cxxtest test framework is strange and has strange/complex build process of test. It would be better if you learn to use something more useful, Catch2 is great and easy to use (no funny build process) and it is supported by godbolt.

Is there any linker flag that tells to defer the loading of dynamic library after dlopen [duplicate]

This question already has answers here:
C++ static initialization order
(6 answers)
Closed 6 years ago.
I have following code
File hello.cc
static A dummyl;
A:: A() {
fun();
}
void A::fun() {
int y = 10;
int z = 20;
int x = y + z;
}
File hello.h
class A {
public:
A a;
void fun();
};
File main.cc
#include <dlfcn.h>
#include "hello.h"
typedef void (*pf)();
int main() {
void *lib;
pf greet;
const char * err;
printf("\n Before dlopen\n");
lib = dlopen("libhello.so", RTLD_NOW | RTLD_GLOBAL);
if (!lib) {
exit(1);
}
A *a = new A ;
a->fun();
dlerror(); /*first clear any previous error; redundant in this case but a useful habit*/
dlclose(lib);
return 0;
}
Build phases:
g++ -fPIC -c hello.cc
g++ -shared -o libhello.so hello.o
g++ -o myprog main.cc -ldl -L. -lhello
Since my shared library in real case is libQtCore.so , I need to link it as using -lQtCore in linker because I cannot use the symbols directly and since there are many of functions then libQtCore, it will not practically advisable to use dlysym for each function of libQtCore.so
Since I link, my static global variables gets initialized before dlopen. Is there any flag for linker g++ that tells compiler to load the shared library only after _dlopen _?
Is there any flag for linker g++ that tells compiler to load the shared library only after _dlopen _?
Yes. On Windows. It's known as delay loading. It doesn't exist on Linux/OS X. It's possible to implement it, but it'd require modifications to binutils and ld.so. See this article for some background on that.
But you don't need to care about any of it. Really.
You are facing a well known problem. So well known that it even has a name: The Static Initialization Order Fiasco.
The solution to all your woes is trivial: don't use static global variables the way you do.
To fix it, use Q_GLOBAL_STATIC, or reimplement something like it yourself. That way the value will be constructed at the time it's first used, not prematurely. That's all there's to it.
Side note: Your recent questions suffer badly by being an XY Problem. You're trying to come up with all sorts of Rube Goldberg-esque solutions to a rather simple issue that it took you a week+ to finally divulge. Ask not about a potential solution, but about the underlying issue is you're attempting to solve. All the library loading stuff is completely and utterly unrelated to your problem, and you don't need to concern yourself with it at all.

Get undefined reference when compiling C++ client for ZooKeeper

I try to compile my very first program in C++ in which I try to connect to ZooKeeper and do some other stuff. In my code I have these lines:
//test.cpp
#include "zookeeper.h"
... all other header files from zookeeper/include
void main_watcher (zhandle_t *zkh,
int type,
int state,
const char *path,
void* context)
{
if(type == ZOO_SESSION_EVENT){
if(state == ZOO_CONNECTED_STATE){
...
}
...
}
}
int main(){
return 0;
}
But when I compile this test.cpp file (indeed, I provide link to the zookeeper/.../build/usr/lib and path to all included files), I get a list of these error messages:
undefined reference to ZOO_SESSION_EVENT
undefined reference to ZOO_CONNECTED_STATE
...
What am I doing wrong?
You're forgetting to link agains zookeeper, most probably. Typically, you'd have to do something like
g++ -lzookeper -o yourprogram yourprogram.c
maybe it's
-lzookeeper-mt
maybe not. Usually, it's job of a build system to figure these things out for you.

C++ compiler issue (?): can't pass arguments to functions in separate class files [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is an undefined reference/unresolved external symbol error and how do I fix it?
I recently started working on an interpreter in C++, but I got annoyed that vectors or arrays could not be passed to external class methods no matter what I tried and so I deleted everything I had worked on. As it turns out, I can't pass even an int to another class. I decided to give C++ another chance before resorting to C or Java, but the compiler still doesn't work as I would expect. Maybe I'm forgetting something simple about C++, as I haven't used it in a while, but this seems simple enough. My problem is: I can't pass arguments to methods in other classes when they're not defined in the same file. Here's what I'm trying to do:
Main: main.cpp
#include "myclass.h"
int main() {
MyClass test;
int n = test.add(25, 30);
return n;
}
Header: myclass.h
class MyClass {
public:
int add(int a, int b);
};
Class implementation: myclass.cpp
#include "myclass.h"
int MyClass::add(int a, int b) {
return a + b;
}
Compiling this with g++ main.cpp yields
/tmp/ccAZr6EY.o: In function main':
main.cpp:(.text+0x1a): undefined reference toMyClass::add(int, int)'
collect2: error: ld returned 1 exit status
What the heck am I doing wrong? Also, the compiler yells at me for the same thing even if my functions aren't parameterized, so it must be a problem with the header.
Any help is much appreciated - thanks!
You need to compile both files
g++ main.cpp myclass.cpp
If you only compile main.cpp, the compiler finds the declaration of MyClass::add in your header but the linker later fails to find an implementation of MyClass::add to jump to.

Nested class, undefined reference, static method

I have problem and no idea how to resolve it. I believe this is stupid trivial:
I have 3 files:
Util.hpp
class Util
{
public:
class BitParser
{
public:
static bool getBitAt(int buf, int idx);
};
};
Util.cpp
#include "Util.hpp"
bool Util::BitParser::getBitAt(int buf, int idx)
{
return true;
}
application.cpp
#include "Util.hpp"
int main(int argc, char* argv[])
{
Util::BitParser::getBitAt(1,1);
}
Of couse, files listed above are in the same directory. And now when I try to link and compile I recieve linker error:
$ g++ -o app application.cpp
application.cpp:(.text+0x19): undefined reference to `Util::BitParser::getBitAt(int, int)'
collect2: ld returned 1 exit status
What is screwed up?
You told g++ to compile your 'main' program, but didn't tell it about the Util module. Add Util.cpp to the command line and all should work well.
The compiler has brewn an "application.o" file that refers to the Util::bitparser functions.
The linker should 'link' these referrals to the "util.o" file, containing the actual code for these functions. But it has no .o file containing a function satisfying the link. That's what it calls "undefined reference": "application.o" refers to a function the linker doesn't find.
You need to compile (and link) all the .cpp files. So in your case, the command would be
$ g++ -o app application.cpp Util.cpp
Better still, write a Makefile to do this for you.
You have to include both application.cpp and Util.cpp in the build.