rres icon indicating copy to clipboard operation
rres copied to clipboard

Undefined reference to `qoi_decode'

Open acoto87 opened this issue 8 months ago • 0 comments

Description

If I try to build the rres example rres_data_loading.c linking against raylib shared library I get the following error.

gcc rres_data_loading.c -I ..\..\raylib\src -I ..\src -lraylibdll -lpthread -lopengl32 -lgdi32 -lwinmm
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\ALEJAN~1\AppData\Local\Temp\cc63myfU.o:rres_data_loading.c:(.text+0x2b0b): undefined reference to `qoi_decode'
collect2.exe: error: ld returned 1 exit status

Repro-steps

  1. Download raylib code
  2. Build it as shared library 2a. mingw32-make.exe -f Makefile PLATFORM=PLATFORM_DESKTOP RAYLIB_LIBTYPE=SHARED RAYLIB_BUILD_MODE=DEBUG 2b. This will generate both raylib.dll and import library libraylibdll.a
  3. Try to build rres example rres_data_loading.c linking against the raylib shared library built on step 2.
  4. I get the following error from the linker: undefined reference to 'qoi_decode'

Analysis

The default build of raylib include the qoi implementation (QOI_IMPLEMENTATION) in its rtexture.c module, given that SUPPORT_FILEFORMAT_QOI is set to 1 by default in config.h. But that implementation doesn't export the qoi_encode or qoi_decode functions when building as a shared library. You can test this with dumpbin /exports raylib.dll > output.txt from the VS Developer Command Prompt if you have that or using tools like depends)

When I try then to use rres-raylib.h (which by default include qoi.h but rely on raylib's implementation, see https://github.com/raysan5/rres/blob/91bfd475c04fa6b6b975e6d0e65223b618328c89/src/rres-raylib.h#L126) in my project I get the linker error.

Possible Solutions

You can try to define #define QOI_IMPLEMENTATION before including rres-raylib.h so the implementation of qoi is in your program too, but I'm not sure if that's ideal as you have to be aware of the dependencies of rres-raylib to use it if you build raylib as a shared library. (There is a point to be made though, that if you are including a single-header file into your program, the reposibility is yours, since you are compiling that as part of your program).

Another way is that rres-raylib.h add the QOI_IMPLEMENTATION before including qoi.h, but then you hit a redefinition problem when compiling raylib and your program as static libraries.

C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ..\..\raylib\src\libraylib.a(rtextures.o): in function `qoi_encode':
C:\Users\Alejandro\Projects\binaryland\deps\raylib\src/external/qoi.h:356: multiple definition of `qoi_encode'; C:\Users\ALEJAN~1\AppData\Local\Temp\ccb5CGCz.o:rres_data_loading.c:(.text+0x1580): first defined here
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ..\..\raylib\src\libraylib.a(rtextures.o): in function `qoi_decode':
C:\Users\Alejandro\Projects\binaryland\deps\raylib\src/external/qoi.h:488: multiple definition of `qoi_decode'; C:\Users\ALEJAN~1\AppData\Local\Temp\ccb5CGCz.o:rres_data_loading.c:(.text+0x1d3d): first defined here
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ..\..\raylib\src\libraylib.a(rtextures.o): in function `qoi_write':
C:\Users\Alejandro\Projects\binaryland\deps\raylib\src/external/qoi.h:595: multiple definition of `qoi_write'; C:\Users\ALEJAN~1\AppData\Local\Temp\ccb5CGCz.o:rres_data_loading.c:(.text+0x22fb): first defined here
C:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/13.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ..\..\raylib\src\libraylib.a(rtextures.o): in function `qoi_read':
C:\Users\Alejandro\Projects\binaryland\deps\raylib\src/external/qoi.h:619: multiple definition of `qoi_read'; C:\Users\ALEJAN~1\AppData\Local\Temp\ccb5CGCz.o:rres_data_loading.c:(.text+0x23ab): first defined here
collect2.exe: error: ld returned 1 exit status

Since, rres-raylib.h relies on raylib for the QOI implementation and it's the default (when other compression algorithms are not specified), maybe the best idea I got is to export dedicated functions on raylib for compression using QOI and rres-raylib.h use that by default, so it doesn't depends on qoi library directly anymore by default. The two usage of qoi_decode are different though, in raylib it's used for image compression/decompression, on LoadImageFromMemory for instance, but on rres it's used for general purpose compression/decompression in UnpackResourceChunk.

Thoughts on this?

acoto87 avatar Aug 24 '25 18:08 acoto87