adit -harus- bisa
adit -harus- bisa

Reputation: 1

Fail to static linking FreeImage 3.15.4 on MingW

I can't static lingking FreeImage 3.15.4 on MingW (either using .lib nor .a). I always receive error "undefined reference to" all FreeImage method. While I successfully dynamic linking the library.

Then I try build from the source, it's the same.

I also try using 3.15.3, both static and dynamic is success. But there's a bug in those version (opening some JPEG).

Need help with this.

My code only 1 file, purge.cpp

#define FREEIMAGE_LIB
#include "FreeImage.h"
#include <iostream>
#include <fstream> 
#include <vector>
#include <string>

void FreeImageErrorHandler(FREE_IMAGE_FORMAT fif, const char *message) {
  std::cerr << "FIError: " << message << std::endl;
}

int main(int argc, char** argv) {
#ifdef FREEIMAGE_LIB
  FreeImage_Initialise();
#endif
  FreeImage_SetOutputMessage(FreeImageErrorHandler);

  std::string fnameIn (argv[1]);
  std::string fnameOut (argv[2]);
  std::vector<uint8_t> data;

  std::ifstream ifs;
  ifs.open(fnameIn.c_str(), std::ios::binary);
  uint8_t c = ifs.get();
  while (ifs.good()) {
    data.push_back(c);
    c = ifs.get();
  }
  ifs.close();

  FIMEMORY *hmem = FreeImage_OpenMemory(&data[0], data.size());
  FREE_IMAGE_FORMAT fif = FreeImage_GetFileTypeFromMemory(hmem, 0);
  FIBITMAP *dib = FreeImage_LoadFromMemory(fif, hmem, 0);

  int flag = JPEG_BASELINE | JPEG_QUALITYGOOD | JPEG_SUBSAMPLING_420 | JPEG_PROGRESSIVE | JPEG_OPTIMIZE;
  bool b = FreeImage_Save(FIF_JPEG, dib, fnameOut.c_str(), flag);
  std::cout << ((b)?"Save\n":"NoSave\n");

  FreeImage_Unload(dib);
  FreeImage_CloseMemory(hmem);

#ifdef FREEIMAGE_LIB
  FreeImage_DeInitialise();
#endif

  return 0; 
}

Command:

g++ -o purge purge.cpp -L. -lfreeimage

Result:

C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x286): undefined reference to `FreeImage_Initialise'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x292): undefined reference to `FreeImage_SetOutputMessage'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x486): undefined reference to `FreeImage_OpenMemory'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x49c): undefined reference to `FreeImage_GetFileTypeFromMemory'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x502): undefined reference to `FreeImage_LoadFromMemory'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x533): undefined reference to `FreeImage_GetWidth'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x541): undefined reference to `FreeImage_GetHeight'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x701): undefined reference to `FreeImage_Rescale'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x723): undefined reference to `FreeImage_Unload'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x72e): undefined reference to `FreeImage_CloseMemory'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x7a4): undefined reference to `FreeImage_Save'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x7d9): undefined reference to `FreeImage_Unload'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x7ea): undefined reference to `FreeImage_CloseMemory'
C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o:purge.cpp:(.text+0x7ef): undefined reference to `FreeImage_DeInitialise'
c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\ADIT~1.BIS\AppData\Local\Temp\cc1LYwkh.o: bad reloc address 0xf in section `.text$_ZNSt6vectorIhSaIhEEC1Ev[__ZNSt6vectorIhSaIhEEC1Ev]'
collect2.exe: error: ld returned 1 exit status

Then when I remove "#define FREEIMAGE_LIB", it's success. But with dynamic linking :(


Solved.

After reading README.minGW carefully. The mistake I made is: I create *.a with 'pexports' & 'dlltool'. While those *.a file is for dynamic link. The *.a file for static link should compile from the source with setting "FREEIMAGE_LIBRARY_TYPE=STATIC". Don't forget to edit "makefile", since the OS has been hard-coded to "gnu".

Upvotes: 0

Views: 2686

Answers (1)

Wohlstand
Wohlstand

Reputation: 171

Try to define FREEIMAGE_LIB in your application too (before including of the header). Without that definition, your app will always spawn an "undefined reference" because FreeImage.h still thinks that it's a dynamic library and adds via macros a DLL-Export annotation, so, prototypes in the header and in the built library are different.

If you still have troubles, you would also try to apply some changes to the library itself:

Steps to do:

1. Modify FreeImage.h:

Replace this:

#ifdef __cplusplus
extern "C" {
#endif

with:

#if defined(__cplusplus) && !defined(__MINGW32__)
extern "C" {
#endif

then this:

#ifdef __cplusplus
}
#endif

with:

#if defined(__cplusplus) && !defined(__MINGW32__)
}
#endif

2. In those files:

Source/DeprecationManager/DeprecationMgr.cpp (in FreeImage older than 3.18)
Source/FreeImage/FreeImage.cpp
Source/FreeImage/Plugin.cpp

replace all #ifdef _WIN32 with #if defined(_WIN32) && !defined(__MINGW32__) (or #if defined(_WIN32) && !defined(FREEIMAGE_LIB) instead to don't break dynamic build).

Exception: don't replace #ifdef _WIN32 in the "Plugin.cpp" in the *U functions: FreeImage_GetFIFFromFilenameU, FreeImage_LoadU and FreeImage_SaveU.

3. Then try to completely rebuild the library. It should be built fine

4. In your application, you should define FREEIMAGE_LIB too (I told below why).


If you want, you can take my working code which you would use:

https://github.com/WohlSoft/libFreeImage

I made it buildable via QMake for convenience, and I also made the ability to build a lite version (which supports BMP, ICO, PNG and GIF formats only and which has a small weight). It was been included in the MinGW-buildable project and it is successfully linked statically.

Upvotes: 2

Related Questions