1

Overview

I am attempting to convert a C++ project from a Visual Studio solution to a makefile project (using g++), as a first step to supporting multiple platforms with ease. This project requires the Simple DirectMedia Layer 2 (SDL2) and SDL_image libraries. The project previously compiled without errors, and I have since corrected any errors halting the g++ compiler. I am still using Windows x64 and MinGW x64 at this point.

Problem

When linking, g++ throws errors as though there is something wrong with the SDL2 library, claiming that all functions of SDL2 can't be found. However, I know it is finding the libraries, because when I provide an incorrect name or path, I get an explicit error.

Here is my new makefile, apologies if it isn't up to standard:

# Source files
SRC_ENTITIES = Entity_Block.cpp Entity_Controller.cpp Entity_Cursor.cpp Entity_GreenEye.cpp Entity_Harry.cpp
SRC_ENGINE   = Game.cpp Sound.cpp SoundManager.cpp Sprite.cpp Texture.cpp TextureManager.cpp Entity.cpp EntityManager.cpp
SRC_ENTRY    = main.cpp

# Source and destination
SOURCE    = $(SRC_ENTITIES) $(SRC_ENGINE) $(SRC_ENTRY)
DEST      = crystal_engine.bin

# Compiler options
OUTPUT    = -o $(DEST)
INCLUDES  = -I . -I.\include\windows\SDL2-devel-2.0.4-mingw\SDL2-2.0.4\x86_64-w64-mingw32\include\SDL2 -I.\include\windows\SDL2_image-devel-2.0.1-mingw\SDL2_image-2.0.1\x86_64-w64-mingw32\include\SDL2
LIBPATHS  = -L.\include\windows\SDL2-devel-2.0.4-mingw\SDL2-2.0.4\x86_64-w64-mingw32\lib -L.\include\windows\SDL2_image-devel-2.0.1-mingw\SDL2_image-2.0.1\x86_64-w64-mingw32\lib
LIBRARIES = -lSDL2 -lSDL2main -lSDL2_image
STANDARD  = -std=c++0x
FLAGS     = -Wall

default:
    echo No task selected

compile:
    g++ $(STANDARD) $(INCLUDES) $(FLAGS) $(SOURCE) $(OUTPUT) $(LIBPATHS) $(LIBRARIES)

run:
    ./$(DEST)

run_win:
    $(DEST)

Therefor the command line currently looks like this:

g++ -std=c++0x -I . -I.\include\windows\SDL2-devel-2.0.4-mingw\SDL2-2.0.4\x86_64-w64-mingw32\include\SDL2 -I.\include\windows\SDL2_image-devel-2.0.1-mingw\SDL2_image-2.0.1\x86_64-w64-mingw32\include\SDL2 -Wall Entity_Block.cpp Entity_Controller.cpp Entity_Cursor.cpp Entity_GreenEye.cpp Entity_Harry.cpp Game.cpp Sound.cpp SoundManager.cpp Sprite.cpp Texture.cpp TextureManager.cpp Entity.cpp EntityManager.cpp main.cpp -o crystal_engine.bin -L.\include\windows\SDL2-devel-2.0.4-mingw\SDL2-2.0.4\x86_64-w64-mingw32\lib -L.\include\windows\SDL2_image-devel-2.0.1-mingw\SDL2_image-2.0.1\x86_64-w64-mingw32\lib -lSDL2 -lSDL2main -lSDL2_image

Disregarding warnings (removing -Wall), the output of the compile looks like this:

C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x169): undefined reference to `SDL_GetTicks'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x2b4): undefined reference to `SDL_GetMouseState'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x2c2): undefined reference to `SDL_PollEvent'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x2d0): undefined reference to `SDL_GetTicks'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x363): undefined reference to `SDL_GetTicks'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x3ef): undefined reference to `SDL_GetTicks'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x46c): undefined reference to `SDL_GetTicks'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x4e3): undefined reference to `SDL_RenderClear'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x4fd): undefined reference to `SDL_RenderPresent'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x597): undefined reference to `SDL_ShowCursor'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x5b1): undefined reference to `SDL_Init'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x633): undefined reference to `SDL_CreateRenderer'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x663): undefined reference to `SDL_CreateWindowAndRenderer'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x678): undefined reference to `SDL_SetWindowTitle'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x836): undefined reference to `SDL_SetRenderDrawColor'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x844): undefined reference to `SDL_RenderClear'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x852): undefined reference to `SDL_RenderPresent'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x865): undefined reference to `SDL_SetHint'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x881): undefined reference to `SDL_RenderSetLogicalSize'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x895): undefined reference to `SDL_GL_SetAttribute'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x8a3): undefined reference to `SDL_GetError'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x8d8): undefined reference to `SDL_GL_SetAttribute'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0x8e6): undefined reference to `SDL_GetError'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0xa3d): undefined reference to `SDL_Quit'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0xaba): undefined reference to `SDL_DestroyWindow'
C:\Users\[...]\ccSkHjgE.o:Game.cpp:(.text+0xad1): undefined reference to `SDL_DestroyRenderer'
f:/mingw/mingw-4.8.1/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\[...]\ccSkHjgE.o: bad reloc address 0x1b in section `.text$printf[_printf]'
collect2.exe: error: ld returned 1 exit status
make: *** [compile] Error 1

Troubleshooting

I have tried a number of things from supplying exact paths to libraries to updating SDL from 2.0.3 to 2.0.4. The behavior is the same. There are two include/lib folders in the MinGW devel folder for each architecture, and changing which one I include does not make a difference.

There seems to be a lot of commotion about the order of which arguments are supplied to g++, given the three posts below:

SDL2 Undefined references to functions

Try to change the sequence of the input params:

I've stumbled over this before (on Linux)

https://askubuntu.com/questions/68922/cant-compile-program-that-uses-sdl-after-upgrade-to-11-10-undefined-reference

Ok, solved. Apparently, for some mysterious reason, the order of the gcc options now matters.

http://smf.cataclysmdda.com/index.php?topic=11028.0

It looks like the SDL2_image library is included, but the main SDL2 library is not (the references could be out of order).

Unfortunately, regardless of how I have reordered the arguments, I can't seem to change this result. Unlike with most issues, I haven't even been able to make it any worse! Any and all help is greatly appreciated.

I don't believe this has anything to do with my code, considering a compile without linking -c completes fine, but if it assists with the solution I would be more than happy to post some of it (it is a LOT of code).

Edits

Per request, here is a dump of the full compile with the -v and -Wall options. It is too large for this question so I threw it in a pastebin.

http://pastebin.com/ydET621i

When using the -DDECLSPEC=__declspec(dllimport) option, the output becomes:

C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x169): undefined reference to `_imp__SDL_GetTicks'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x2b6): undefined reference to `_imp__SDL_GetMouseState'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x2c6): undefined reference to `_imp__SDL_PollEvent'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x2d6): undefined reference to `_imp__SDL_GetTicks'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x36b): undefined reference to `_imp__SDL_GetTicks'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x3f9): undefined reference to `_imp__SDL_GetTicks'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x478): undefined reference to `_imp__SDL_GetTicks'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x4f1): undefined reference to `_imp__SDL_RenderClear'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x50d): undefined reference to `_imp__SDL_RenderPresent'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x5a9): undefined reference to `_imp__SDL_ShowCursor'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x5c5): undefined reference to `_imp__SDL_Init'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x649): undefined reference to `_imp__SDL_CreateRenderer'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x67b): undefined reference to `_imp__SDL_CreateWindowAndRenderer'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x692): undefined reference to `_imp__SDL_SetWindowTitle'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x852): undefined reference to `_imp__SDL_SetRenderDrawColor'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x862): undefined reference to `_imp__SDL_RenderClear'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x872): undefined reference to `_imp__SDL_RenderPresent'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x887): undefined reference to `_imp__SDL_SetHint'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x8a5): undefined reference to `_imp__SDL_RenderSetLogicalSize'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x8bb): undefined reference to `_imp__SDL_GL_SetAttribute'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x8cb): undefined reference to `_imp__SDL_GetError'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x902): undefined reference to `_imp__SDL_GL_SetAttribute'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0x912): undefined reference to `_imp__SDL_GetError'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0xa6b): undefined reference to `_imp__SDL_Quit'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0xaea): undefined reference to `_imp__SDL_DestroyWindow'
C:\Users\[...]\ccZ61vi9.o:Game.cpp:(.text+0xb03): undefined reference to `_imp__SDL_DestroyRenderer'
f:/mingw/mingw-4.8.1/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: C:\Users\[...]\ccZ61vi9.o: bad reloc address 0x1b in section `.text$printf[_printf]'
collect2.exe: error: ld returned 1 exit status
make: *** [compile] Error 1

Running ar -t libSDL2.a produces the following:

SDL.o
SDL_assert.o
SDL_error.o
SDL_hints.o
SDL_log.o
SDL_atomic.o
SDL_spinlock.o
SDL_audio.o
SDL_audiocvt.o
SDL_audiodev.o
SDL_audiotypecvt.o
SDL_mixer.o
SDL_wave.o
SDL_cpuinfo.o
SDL_dynapi.o
SDL_clipboardevents.o
SDL_dropevents.o
SDL_events.o
SDL_gesture.o
SDL_keyboard.o
SDL_mouse.o
SDL_quit.o
SDL_touch.o
SDL_windowevents.o
SDL_rwops.o
SDL_haptic.o
SDL_gamecontroller.o
SDL_joystick.o
e_atan2.o
e_log.o
e_pow.o
e_rem_pio2.o
e_sqrt.o
k_cos.o
k_rem_pio2.o
k_sin.o
k_tan.o
s_atan.o
s_copysign.o
s_cos.o
s_fabs.o
s_floor.o
s_scalbn.o
s_sin.o
s_tan.o
SDL_power.o
SDL_d3dmath.o
SDL_render.o
SDL_yuv_mmx.o
SDL_yuv_sw.o
SDL_render_d3d.o
SDL_render_d3d11.o
SDL_render_gl.o
SDL_shaders_gl.o
SDL_render_gles.o
SDL_render_gles2.o
SDL_shaders_gles2.o
SDL_render_psp.o
SDL_blendfillrect.o
SDL_blendline.o
SDL_blendpoint.o
SDL_drawline.o
SDL_drawpoint.o
SDL_render_sw.o
SDL_rotate.o
SDL_getenv.o
SDL_iconv.o
SDL_malloc.o
SDL_qsort.o
SDL_stdlib.o
SDL_string.o
SDL_thread.o
SDL_timer.o
SDL_RLEaccel.o
SDL_blit.o
SDL_blit_0.o
SDL_blit_1.o
SDL_blit_A.o
SDL_blit_N.o
SDL_blit_auto.o
SDL_blit_copy.o
SDL_blit_slow.o
SDL_bmp.o
SDL_clipboard.o
SDL_egl.o
SDL_fillrect.o
SDL_pixels.o
SDL_rect.o
SDL_shape.o
SDL_stretch.o
SDL_surface.o
SDL_video.o
SDL_nullevents.o
SDL_nullframebuffer.o
SDL_nullvideo.o
SDL_diskaudio.o
SDL_dummyaudio.o
SDL_windows.o
SDL_xinput.o
SDL_windowsclipboard.o
SDL_windowsevents.o
SDL_windowsframebuffer.o
SDL_windowskeyboard.o
SDL_windowsmessagebox.o
SDL_windowsmodes.o
SDL_windowsmouse.o
SDL_windowsopengl.o
SDL_windowsopengles.o
SDL_windowsshape.o
SDL_windowsvideo.o
SDL_windowswindow.o
SDL_winmm.o
SDL_directsound.o
SDL_xaudio2.o
SDL_dinputjoystick.o
SDL_mmjoystick.o
SDL_windowsjoystick.o
SDL_xinputjoystick.o
SDL_dinputhaptic.o
SDL_windowshaptic.o
SDL_xinputhaptic.o
SDL_syspower.o
SDL_sysfilesystem.o
SDL_sysmutex.o
SDL_syssem.o
SDL_systhread.o
SDL_systls.o
SDL_syscond.o
SDL_systimer.o
SDL_sysloadso.o
Community
  • 1
  • 1
Bit Fracture
  • 651
  • 1
  • 9
  • 24
  • 1
    If you can't post a minimal example that replicates the issue at least add `-v` to your compile flags and dump the output somewhere. – user657267 Jan 18 '16 at 06:29
  • The only thing that comes to my mind is some sort of __declspec(dllexport) / __declspec(dllimport) related mess. – J.J. Hakala Jan 18 '16 at 06:31
  • @user657267 I have thrown the -v -Wall output in a pastebin, see the original question. – Bit Fracture Jan 18 '16 at 06:33
  • @J.J.Hakala That's a good point, OP please try adding `-static` to your compile flags. – user657267 Jan 18 '16 at 06:33
  • @user657267 The only change in output with the -static flag was the line `f:/mingw/mingw-4.8.1/bin/../lib/gcc/mingw32/4.8.1/../../../../mingw32/bin/ld.exe: final link failed: Invalid operation` following the original errors. – Bit Fracture Jan 18 '16 at 06:36
  • what about compiling with `-DDECLSPEC=__declspec(dllimport)` after `make clean`? – J.J. Hakala Jan 18 '16 at 06:40
  • @J.J.Hakala I have added the changed output to the bottom of the question. – Bit Fracture Jan 18 '16 at 06:44
  • 1
    What are the contents of `include\windows\SDL2-devel-2.0.4-mingw\SDL2-2.0.4\x86_64-w64-mingw32\lib`? Run `86_64-w64-mingw32-nm` on `libSDL2.a` if it's in there and see if the function symbols are in there. – user657267 Jan 18 '16 at 06:59
  • @user657267 Contents include `libSDL2.a` `libSDL2.dll.a` `libSDL2.la` `libSDL2_test.a` `libSDL2main.a` and two directories. I do not know how to run the command `86_64-w64-mingw32-nm`. – Bit Fracture Jan 18 '16 at 07:08
  • @user657267 I added the output from `ar -t libSDL2.a` if that is helpful. – Bit Fracture Jan 18 '16 at 07:27
  • Sorry I meant `x86_64-w64-mingw32-nm libSDL2.a` or just `nm libSDL2.a` depending on your distribution. – user657267 Jan 18 '16 at 07:32
  • @user657267 The output is the same as `ar` but each line says "File format not recognized" – Bit Fracture Jan 18 '16 at 07:33
  • 1
    If you used `x86_64-w64-mingw32-nm`, it sounds you have the 32 bit version of the SDL libs, are you sure your compiler and the libs match each other and the target platform? – user657267 Jan 18 '16 at 07:35
  • I used `nm` directly. I am pretty sure my compiler is 64 bit. I thought I was linking the right section of libs, `i686-w64-mingw32` being the 32 bit? I see the MinGW32 on there, but the site doesn't offer an alternative. – Bit Fracture Jan 18 '16 at 07:38
  • The code in here http://stackoverflow.com/questions/17386032/sdl2-wont-link-properly would probably do as a minimal test case. – J.J. Hakala Jan 18 '16 at 07:39
  • @J.J.Hakala I reinstalled MinGW and actually got more errors, all of the same nature, but from all of the CPP files not just Game.cpp. Changing to the 32 bit libs cleared up all of the errors except `c:/mingw/bin/../lib/gcc/mingw32/4.8.1/../../../libmingw32.a(main.o):(.text.startup+0xa7): undefined reference to `WinMain@16'` which is supposed to be resolved by SDL2main. I'll keep messing with it. – Bit Fracture Jan 18 '16 at 08:00
  • The `WinMain()` issue was cleared up by including the `-lmingw32` library. Not only is this build smaller than Visual Studio, but the graphics functions and game logic don't even register in milliseconds. Fantastic. Please feel free to post your answer, I want to give credit where it it due. – Bit Fracture Jan 18 '16 at 08:09
  • I'm going to go ahead and post the answer. – Bit Fracture Jan 18 '16 at 18:04

1 Answers1

1

Thanks to suggestions from @J.JHakala and @user657267 I have reached the conclusion that my installation of MinGW is actually 32 bit! Given that I was using the 64 bit libraries, they would read in like any other library, but the functions within them were not recognized.

For anyone else having this problem, you can download the 64 bit version of MinGW or alternatively just switch which libraries you are importing.

x86: i686-w64-mingw32

x64: x86_64-w64-mingw32

Bit Fracture
  • 651
  • 1
  • 9
  • 24