Undefined reference to GpgME::Data::seek(long, int) on MinGW
Testing, NormalPublic

Description

The problem occurs when building KMyMoney on MinGW in CI system. Log of compilation is here . Although libgpgmepp.dll.a and libgpgme.dll.a are linked, the linker cannot resolve GpgME::Data::seek(long, int). It can resolve e.g.

ssize_t GpgME::Data::write(const void *buffer, size_t length)

which is from the same header.

I narrowed it down to the use of

off_t offset

in

off_t GpgME::Data::seek(off_t offset, int whence)

If I would use

GpgME::Data::Data(const char *filename, off_t offset, size_t length)

, which also contains off_t, then this constructor would be undefined as well.

GpgMe++ is being build according to this script, so nothing special.

The problem is present on MS Windows. It's not present neither on Linux nor on MacOS.

werner triaged this task as Normal priority.
werner added subscribers: aheinecke, werner.

You are not cross-compiling. This is not suggested and I don't have the environment to replicate this. Maybe @aheinecke can help.

Uhm, yeah I would be willing to help. But I tried to understand it and don't see the problem.

So what the error tells us is that "off_t" is defined as long in the declaration but as something else in the definition.

But how can that be? data.cpp includes the data.h header so they both should have the same definition of off_t.

The only thing I could imagine is that something which is included in the cpp but not in the header undef's off_t and defines it to something else.

Or more likely that the archive was compiled with a different definition of off_t then what is included in the headers when kmymoney is built.

Are you using the same mingw version as the buildchain which compiles the gpgme binary?

Uhm, yeah I would be willing to help. But I tried to understand it and don't see the problem.

So what the error tells us is that "off_t" is defined as long in the declaration but as something else in the definition.

But how can that be? data.cpp includes the data.h header so they both should have the same definition of off_t.

The only thing I could imagine is that something which is included in the cpp but not in the header undef's off_t and defines it to something else.

Or more likely that the archive was compiled with a different definition of off_t then what is included in the headers when kmymoney is built.

Are you using the same mingw version as the buildchain which compiles the gpgme binary?

I used the same version of mingw for gpgme and kmymoney.

It includes this kind of off_t. I don't know why but it chooses

typedef off32_t off_t;

instead of

typedef off64_t off_t;
aheinecke changed the task status from Open to Testing.May 29 2018, 9:29 AM

The gpgme c api already had a convenience function gpgme_data_rewind to do data.seek (0, SEEK_SET); As this is by far the most common seek operation. KMymoney also only uses such seeks.

I've now added this to GpgME++, too as it avoids the whole off_t mess. This was easier for me then to try to understand why such a mismatch occurs in your build.

So in KMymoney you can do:

#include <gpgme++/gpgmepp_version.h>
...

#if GPGMEPP_VERSION > 0x10B01 // min 1.11.2
d->m_data.rewind ();
#else 
d->m_data.seek(0, SEEK_SET);
#endif

Hope this helps, of course you will need gpgme master for windows until we publish 1.11.2, although we will probably publish it soonish <=3weeks.

Ok. Thanks.

Maybe the off_t mess comes from following line

checking for off_t... yes

All other libraries (e.g. libtasn1) check for 64 bit version.

checking for 64-bit off_t... yes

I get it from compilation log that I've linked earlier.

Following patch fixes the issue.

Thank you for pointing this out.

The problem with the patch is that it includes gpgme.h in a gpgme++ header. It's a design decision that this is not done as it should not be required for example to have gpgme.h available in the include path when compiling against gpgme++

But we should might just add some similar handling. And also need to do it in a way that won't break ABI.

Not really. off_t is a real portability problem and this why we moved that problem out of the GPGME ABI to the application. Thus the application needs to care about mapping gpgme_off_t to whatever off_t it uses. Without that we can't provide a stable _and_ toolchain independent ABI.

(This is similar to the problem of using printf with any type which does not have direct support in printf. off-t definitely has none and uintXX_t also has no printf support so that you need to case it to unsigned long long for printf. All ugly, but that is who things are. We will see the same problem in future with time_t :-( )