Linking error for libgmic

Godot Version

4.1

Question

I’m planning to experiment with the G’MIC image processing library (https://gmic.eu/ ) and am currently trying to add a module to access the library. I followed the steps in the documentation on how to link to external libraries (Binding to external libraries — Godot Engine (4.1) documentation in English ) and the setup seems correct and SCons does find the library and add it to the linker command, but I get errors about unresolved external symbols:

module_gmic.windows.editor.dev.x86_64.lib(godot_gmic.windows.editor.dev.x86_64.obj) : error LNK2019: unresolved external symbol "public: __cdecl gmic::~gmic(void)" (??1gmic@@QEAA@XZ) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)
module_gmic.windows.editor.dev.x86_64.lib(godot_gmic.windows.editor.dev.x86_64.obj) : error LNK2019: unresolved external symbol "public: __cdecl gmic::gmic<float>(char const * const,struct gmic_library::gmic_list<float> &,struct gmic_library::gmic_list<char> &,char const * const,bool,float * const,bool * const)" (??$?0M@gmic@@QEAA@QEBDAEAU?$gmic_list@M@gmic_library@@AEAU?$gmic_list@D@2@0_NQEAMQEA_N@Z) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)

Using nm -Cg libgmic.a it looks to me that those symbols are present in the library:

0000000000000000 T gmic::gmic<float>(char const*, gmic_library::gmic_list<float>&, gmic_library::gmic_list<char>&, char const*, bool, float*, bool*)
[...]
00000000000c0260 T gmic::~gmic()

The directory setup is as follows:

modules/
|- gmic/
   |- include/
   |  |- gmic.h
   |- lib/
   |  |- libgmic.a
   |  |- [several .dll files needed by libgmic]
   |- config.py
   |- godot_gmic.cpp
   |- godot_gmic.h
   |- register_types.cpp
   |- register_types.h
   |- SCsub

The header file and the files in modules/gmic/lib are copied from latests version (3.4.0) of the C/C++ library download (https://gmic.eu/files/windows/gmic_3.4.0_lib_win64.zip ). I also tried compiling the library myself (G'MIC - GREYC's Magic for Image Computing: A Full-Featured Open-Source Framework for Image Processing - Download ), but the result is the same.

If I am not mistaken .lib files and .a files are both just archives containing compiled .o files, so I do not think that those are the wrong files. I also double checked that everything is using 64 bit.

The module only contains a simple test() method:

godot_gmic.cpp:

#include "godot_gmic.h"
#include "gmic.h"

void GMIC::_bind_methods() {
	ClassDB::bind_method(D_METHOD("test"), &GMIC::test);
}

void GMIC::test() {
	gmic_list<float> image_list;
	gmic_list<char> image_names;

	try {
		gmic("testimage2d 512 output gmic_test.png", image_list, image_names);
	} catch (gmic_exception &e) {
		printf("GMIC ERROR: %s\n", e.what());
	}
}

The linker error about the missing symbols for gmic() and ~gmic() dissappear when I remove the call to gmic() in the test() method. The constructors for the gmic_list instances seem to be linked just fine.

The SCsub file adds the library correctly:

# SCsub

Import('env')

env_gmic = env.Clone()
env_gmic.add_source_files(env.modules_sources, "*.cpp")
env_gmic.Append(CPPPATH=["include"])

if env.msvc:
    env.Append(LIBS=[File('lib/libgmic.a')])
else:
    env.Append(LIBPATH=["gmic"])
    env.Append(LIBS=['gmic', 'cgmic'])

Am I missing a step or a configuration here?

If anyone encountered similar problems when linking to an external library, any inputs and tipps would be greatly appreciated!

Thanks in advance for any advice and best regards,
Patrick

I think you need this to for .a files
env.Append(LIBPATH=["lib"])

Referenceing this doc

1 Like

Hello @pennyloafers!

Thanks for your reply! Ich tried your suggestion, but unfortunatelly it does not solve the problem. The library is found correctly and I for example get a file not found error, when I configure the path to libgmic.a wronlgy. The linking command generated by scons correctly adds the library file, but I still get the linking errors about missing symbols.

If there are any other things I might be missing, I would appreciate any input on this issue.

Thanks again and thanks in advance for any further hints!

Best regards,
Patrick

I’m a little confused by this, when the compiler is MSVC you only leverage the .a file with LIBS, while the else would setup the LIBPATH and LIBS.

I feel like something is missing here.

https://www.scons.org/doc/0.95/HTML/scons-user/x321.html

This says the linker is looking at LIBPATH, but for MSCV env does not append the LIBPATH variable

I think you need to append both LIBS and LIBPATH

1 Like

Hello @pennyloafers!

I tried again with the exact setup that you are suggesting, but the error persists. The special handling for MSVC was from another tipp that I found, concerning the fact that LIBPATH for MSVC does not use the modules directory as base, but platform/windows/. The File() command makes sure, it uses really the named file without trying to guess location and filename from the library name.

This is my current SCsub file:

# SCsub

Import('env')

env_gmic = env.Clone()
env_gmic.add_source_files(env.modules_sources, "*.cpp")
env_gmic.Append(CPPPATH=["include"])

env.Append(LIBPATH=["gmic"])
env.Append(LIBS=['gmic', 'cgmic'])

And starting a build with scons --debug=findlibs p=windows arch=x86_64 dev_build=yes shows that the library file is indeed found (in platform/windows/gmic where I placed a copy of the library file with the name that SCons expects):

scons: Building targets ...
[  0%]   findlibs: looking for 'mongocxx.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb' ...
  findlibs: ... FOUND 'mongocxx.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb'
  findlibs: looking for 'mongocxx.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'mongocxx.lib' in 'platform\windows\gmic' ...
  findlibs: looking for 'bsoncxx.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb' ...
  findlibs: ... FOUND 'bsoncxx.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb'
  findlibs: looking for 'bsoncxx.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'bsoncxx.lib' in 'platform\windows\gmic' ...
  findlibs: looking for 'gmic.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'gmic.windows.editor.dev.x86_64.lib' in 'platform\windows\gmic' ...
  findlibs: ... FOUND 'gmic.windows.editor.dev.x86_64.lib' in 'platform\windows\gmic'
  findlibs: looking for 'gmic.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'gmic.lib' in 'platform\windows\gmic' ...
  findlibs: looking for 'cgmic.windows.editor.dev.x86_64.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'cgmic.windows.editor.dev.x86_64.lib' in 'platform\windows\gmic' ...
  findlibs: ... FOUND 'cgmic.windows.editor.dev.x86_64.lib' in 'platform\windows\gmic'
  findlibs: looking for 'cgmic.lib' in 'platform\windows\mongodb' ...
  findlibs: looking for 'cgmic.lib' in 'platform\windows\gmic' ...

But the final linking step still fails:

[ 96%] Linking Program bin\godot.windows.editor.dev.x86_64.exe ...
[ 99%] progress_finish(["progress_finish"], [])
[100%]    Creating library bin\godot.windows.editor.dev.x86_64.lib and object bin\godot.windows.editor.dev.x86_64.exp
module_gmic.windows.editor.dev.x86_64.lib(godot_gmic.windows.editor.dev.x86_64.obj) : error LNK2019: unresolved external symbol "public: __cdecl gmic::~gmic(void)" (??1gmic@@QEAA@XZ) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)
module_gmic.windows.editor.dev.x86_64.lib(godot_gmic.windows.editor.dev.x86_64.obj) : error LNK2019: unresolved external symbol "public: __cdecl gmic::gmic<float>(char const * const,struct gmic_library::gmic_list<float> &,struct gmic_library::gmic_list<char> &,char const * const,bool,float * const,bool * const)" (??$?0M@gmic@@QEAA@QEBDAEAU?$gmic_list@M@gmic_library@@AEAU?$gmic_list@D@2@0_NQEAMQEA_N@Z) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)
bin\godot.windows.editor.dev.x86_64.exe : fatal error LNK1120: 2 unresolved externals
scons: *** [bin\godot.windows.editor.dev.x86_64.exe] Error 1120

I am pretty sure the problem is not that the file is not found, but that the two symbols still cannot be resolved:

error LNK2019: unresolved external symbol "public: __cdecl gmic::~gmic(void)" (??1gmic@@QEAA@XZ) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)

error LNK2019: unresolved external symbol "public: __cdecl gmic::gmic<float>(char const * const,struct gmic_library::gmic_list<float> &,struct gmic_library::gmic_list<char> &,char const * const,bool,float * const,bool * const)" (??$?0M@gmic@@QEAA@QEBDAEAU?$gmic_list@M@gmic_library@@AEAU?$gmic_list@D@2@0_NQEAMQEA_N@Z) referenced in function "public: void __cdecl GMIC::test(void)" (?test@GMIC@@QEAAXXZ)

Thanks again for your help! If anyone has an idea what else could be the cause of this error, any hints would be very appreciated!

Best regards,
Patrick

I got it to work with this

Import('env')
Import("env_modules")

gd_gmic = env.Clone()
gd_gmic.add_source_files(env.modules_sources, "*.cpp")
gd_gmic.Append(CPPPATH=['gmic'])

env.Append(LIBPATH=['C:/Users/pennyloafers/Desktop/godot_src/modules/godot_gmic/gmic'])
env.Append(LIBS=[
    'gmic',
    'gomp', 
    File('gmic/libjpeg-8.dll'),
    File('gmic/libfftw3-3.dll'),
    File('gmic/libfftw3_threads-3.dll'),
    File('gmic/libtiff-6.dll'),
    File('gmic/libcurl-4.dll'),
    ])

Not sure every line is necessary but for getting all the library depedencies to link I needed to use the File operation.

As a side effect of dynamically linking the DLL’s these also need to be available to the godot editor executable. i was also using mingw compiler and seeing the same issues you were.

scons --debug=findlibs p=windows arch=x86_64 dev_build=yes use_mingw=yes

I think the tipping point for me was using the absolute path for the libgmic.a

  findlibs: looking for 'libgmic.a' in 'modules\godot_gmic\gmic' ...
  findlibs: ... FOUND 'libgmic.a' in 'modules\godot_gmic\gmic'

I didn’t run any tests…

1 Like

Hello @pennyloafers!

Thank you so much for your help, your tipps brought me on the right track!

I was able to get it to build with your changes to the SCsub file, unfortunatelly I only got it to work with MinGW yet. Since this would affect other parts of the project I’m not free to just substitute the build toolchain.

The library is found, and the link command generated by scons seems fine, but the linking aborts with the following error:

modules\gmic\lib\libgomp-1.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x340

I’m investigating that error right now, but was hoping that the error message might be familiar and you might have an idea about what’s going wrong.

Below is my current SCsub file for the module. I had to add “gdi32” to the linked libraries and specify the path to libgomp-1.dll directly with File(), otherwise the build aborted because it was not found. I also had to rename the libgmic.a file to gmic.windows.editor.dev.x86_64.lib because building with MSVC expects a different naming convention.

Import('env')
Import("env_modules")

gd_gmic = env.Clone()
gd_gmic.add_source_files(env.modules_sources, "*.cpp")
gd_gmic.Append(CPPPATH=['include'])

env.Append(LIBPATH=['E:/godot-source/modules/gmic/lib'])
env.Append(LIBS=[
    'gmic',
    File('lib/libgomp-1.dll'), 
    'gdi32',
    File('lib/libjpeg-8.dll'),
    File('lib/libfftw3-3.dll'),
    File('lib/libfftw3_threads-3.dll'),
    File('lib/libtiff-6.dll'),
    File('lib/libcurl-4.dll'),
])

This is the output for the linking step of the Godot build:

scons: Building targets ...
[  0%]   findlibs: looking for 'gmic.windows.editor.dev.x86_64.lib' in 'modules\gmic\lib' ...
  findlibs: ... FOUND 'gmic.windows.editor.dev.x86_64.lib' in 'modules\gmic\lib'
  findlibs: looking for 'gmic.lib' in 'modules\gmic\lib' ...
  findlibs: ... FOUND 'gmic.lib' in 'modules\gmic\lib'
  findlibs: looking for 'gdi32.windows.editor.dev.x86_64.lib' in 'modules\gmic\lib' ...
  findlibs: looking for 'gdi32.lib' in 'modules\gmic\lib' ...
[ 22%] lib /nologo /OUT:modules\module_gmic.windows.editor.dev.x86_64.lib modules\gmic\godot_gmic.windows.editor.dev.x86_64.obj modules\gmic\register_types.windows.editor.dev.x86_64.obj
[ 99%] progress_finish(["progress_finish"], [])
[100%] Using tempfile C:\Users\Patrick\AppData\Local\Temp\tmpcafge28x.lnk for command line:
link /nologo /SUBSYSTEM:WINDOWS /INCREMENTAL:NO winmm.lib dsound.lib kernel32.lib ole32.lib oleaut32.lib sapi.lib user32.lib gdi32.lib IPHLPAPI.lib Shlwapi.lib wsock32.lib Ws2_32.lib shell32.lib advapi32.lib dinput8.lib dxguid.lib imm32.lib bcrypt.lib Crypt32.lib Avrt.lib dwmapi.lib dwrite.lib wbemuuid.lib psapi.lib dbghelp.lib opengl32.lib /NATVIS:platform\windows\godot.natvis /STACK:8388608 /DEBUG:FULL psapi.lib /OUT:bin\godot.windows.editor.dev.x86_64.exe /LIBPATH:modules\gmic\lib main\main.windows.editor.dev.x86_64.lib modules\modules.windows.editor.dev.x86_64.lib modules\module_msdfgen.windows.editor.dev.x86_64.lib modules\module_theora.windows.editor.dev.x86_64.lib modules\module_vorbis.windows.editor.dev.x86_64.lib modules\module_astcenc.windows.editor.dev.x86_64.lib modules\module_basis_universal.windows.editor.dev.x86_64.lib modules\module_bmp.windows.editor.dev.x86_64.lib modules\module_camera.windows.editor.dev.x86_64.lib modules\module_csg.windows.editor.dev.x86_64.lib modules\module_cvtt.windows.editor.dev.x86_64.lib modules\module_dds.windows.editor.dev.x86_64.lib modules\module_denoise.windows.editor.dev.x86_64.lib modules\module_enet.windows.editor.dev.x86_64.lib modules\module_etcpak.windows.editor.dev.x86_64.lib modules\module_freetype.windows.editor.dev.x86_64.lib modules\module_gdscript.windows.editor.dev.x86_64.lib modules\module_glslang.windows.editor.dev.x86_64.lib modules\module_gltf.windows.editor.dev.x86_64.lib modules\module_gmic.windows.editor.dev.x86_64.lib modules\module_gridmap.windows.editor.dev.x86_64.lib modules\module_hdr.windows.editor.dev.x86_64.lib modules\module_jpg.windows.editor.dev.x86_64.lib modules\module_jsonrpc.windows.editor.dev.x86_64.lib modules\module_lightmapper_rd.windows.editor.dev.x86_64.lib modules\module_mbedtls.windows.editor.dev.x86_64.lib modules\module_meshoptimizer.windows.editor.dev.x86_64.lib modules\module_minimp3.windows.editor.dev.x86_64.lib modules\module_mobile_vr.windows.editor.dev.x86_64.lib modules\module_multiplayer.windows.editor.dev.x86_64.lib modules\module_navigation.windows.editor.dev.x86_64.lib modules\module_noise.windows.editor.dev.x86_64.lib modules\module_ogg.windows.editor.dev.x86_64.lib modules\module_openxr.windows.editor.dev.x86_64.lib modules\module_raycast.windows.editor.dev.x86_64.lib modules\module_regex.windows.editor.dev.x86_64.lib modules\module_squish.windows.editor.dev.x86_64.lib modules\module_summator.windows.editor.dev.x86_64.lib modules\module_svg.windows.editor.dev.x86_64.lib modules\module_text_server_adv.windows.editor.dev.x86_64.lib modules\module_tga.windows.editor.dev.x86_64.lib modules\module_tinyexr.windows.editor.dev.x86_64.lib modules\module_upnp.windows.editor.dev.x86_64.lib modules\module_vhacd.windows.editor.dev.x86_64.lib modules\module_webp.windows.editor.dev.x86_64.lib modules\module_webrtc.windows.editor.dev.x86_64.lib modules\module_websocket.windows.editor.dev.x86_64.lib modules\module_webxr.windows.editor.dev.x86_64.lib modules\module_xatlas_unwrap.windows.editor.dev.x86_64.lib modules\module_zip.windows.editor.dev.x86_64.lib platform\platform.windows.editor.dev.x86_64.lib drivers\drivers.windows.editor.dev.x86_64.lib editor\editor.windows.editor.dev.x86_64.lib scene\scene.windows.editor.dev.x86_64.lib servers\servers.windows.editor.dev.x86_64.lib core\core.windows.editor.dev.x86_64.lib modules\text_server_adv\harfbuzz_builtin.windows.editor.dev.x86_64.lib modules\text_server_adv\graphite_builtin.windows.editor.dev.x86_64.lib modules\text_server_adv\icu_builtin.windows.editor.dev.x86_64.lib modules\freetype\freetype_builtin.windows.editor.dev.x86_64.lib modules\msdfgen\msdfgen_builtin.windows.editor.dev.x86_64.lib gmic.windows.editor.dev.x86_64.lib modules\gmic\lib\libgomp-1.dll gdi32.windows.editor.dev.x86_64.lib modules\gmic\lib\libjpeg-8.dll modules\gmic\lib\libfftw3-3.dll modules\gmic\lib\libfftw3_threads-3.dll modules\gmic\lib\libtiff-6.dll modules\gmic\lib\libcurl-4.dll platform\windows\godot_windows.windows.editor.dev.x86_64.obj platform\windows\crash_handler_windows.windows.editor.dev.x86_64.obj platform\windows\os_windows.windows.editor.dev.x86_64.obj platform\windows\display_server_windows.windows.editor.dev.x86_64.obj platform\windows\key_mapping_windows.windows.editor.dev.x86_64.obj platform\windows\joypad_windows.windows.editor.dev.x86_64.obj platform\windows\tts_windows.windows.editor.dev.x86_64.obj platform\windows\windows_terminal_logger.windows.editor.dev.x86_64.obj platform\windows\vulkan_context_win.windows.editor.dev.x86_64.obj platform\windows\gl_manager_windows.windows.editor.dev.x86_64.obj platform\windows\godot_res.windows.editor.dev.x86_64.obj
link @C:\Users\Patrick\AppData\Local\Temp\tmpcafge28x.lnk
modules\gmic\lib\libgomp-1.dll : fatal error LNK1107: invalid or corrupt file: cannot read at 0x340
scons: *** [bin\godot.windows.editor.dev.x86_64.exe] Error 1107
scons: building terminated because of errors.
[Time elapsed: 00:00:13.790]

The gmic library is found, and the DLL files are listed in the linking command, but the libgomp-1.dll file cannot be used to link agains.

I appreciate your help so far and thank you in advance for any thoughts on how to get this to build with MSVC.

Thanks and best regards,
Patrick

I guess from the error and what the Internet says MSVC doesn’t like raw .dll files and wants .libs

I found this but not sure if there are better ways to get a .lib file from a . dll

https://www.asawicki.info/news_1420_generating_lib_file_for_dll_library

1 Like

Hello @pennyloafers!

Thank you for the link and all your help so far!

I will look into the .dll vs .lib issue and give an update when I managed to get it to work with MSVC.

Best regards,
Patrick