0

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".

Cœur
  • 37,241
  • 25
  • 195
  • 267
  • 1
    Please show your link step and the exact errors you get. Also make sure you aren't mismatching 32 bit and 64 bit libraries. – Thomas Jan 06 '14 at 10:22
  • source and compiling result has been added. I'am using 32 bit. As mentioned above, using dynamic linking is a success and program working properly (and no bug from 3.15.3). – adit -harus- bisa Jan 06 '14 at 10:54
  • Where did you even find the *.a library file? I can't find it in the pre-built package. Please be aware, that the *.lib files are most likely MSVC import libraries, their size is way too thin. – Thomas Jan 06 '14 at 12:37
  • As mentioned in README.minGW, to create *.a use pexports & dlltool. For 3.15.3, I use either *.lib or *.a, And it's success. Still buggy for some JPEG :( – adit -harus- bisa Jan 06 '14 at 13:11
  • Err...I think you got something wrong there. You can't create a static library from a *.dll! All you can do is creating import libraries from it (the README also cleary states import library). Btw: MinGW doesn't need import libraries, MinGW is able to read the symbols directly from the *.dll. However, you probably don't want static linking anyway because static linking would also mean to link all depedencies static as well. – Thomas Jan 06 '14 at 14:00
  • Doh.. (#>.<) I just remembered, the .a for 3.15.3 is from compiling as static library. Well, it has been looong time ago, and I just left it there with my source and the .dll. And then I try the same for 3.15.4, it's a success. Thx @Thomas :) – adit -harus- bisa Jan 07 '14 at 09:20

1 Answers1

2

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.

Wohlstand
  • 161
  • 1
  • 9
  • Source/DeprecationManager/DeprecationMgr.cpp, there is no such file in version 3.18. Have to stick to DLL linking... – Dmitry Babich Dec 05 '22 at 14:34
  • @DmitryBabich, just ignore that file. – Wohlstand Dec 06 '22 at 15:09
  • @DmitryBabich, I added the note that the file is presented at the FreeImabe before 3.18 only. – Wohlstand Dec 06 '22 at 15:15
  • p.s. that article I wrote in 2015, and that was three years before 3.18 got released. – Wohlstand Dec 06 '22 at 15:51
  • I'll try to verify, however, you could use my modded version, it absolutely works fine with MinGW and static builds. I modded it for my own needs (including disabling/removing everything except PNG, JPEG, GIF, BMP and ICO support). Default stuff is a mess in many cases, and a lot of unneeded (for me) things are just ballast. – Wohlstand Dec 14 '22 at 02:42
  • I compiled FI as static. Now when linking I got a lot of such errors: FreeImageLib.lib(MultiPage.obj) : error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MT_StaticRelease' doesn't match value 'MD_DynamicRelease' in Main.obj (this is my file) – Dmitry Babich Jan 14 '23 at 22:56
  • The official version of the build requires you also define the global macro at your application. In my modded version I tweaked this behaviour to don't require that damned macro. – Wohlstand Jan 15 '23 at 06:20