0

i had made a game on C using SDL2, SDL2_image, SDL2_mixer and SDL2_ttf libraries installed on Linux (Ubuntu) by sudo apt-get install libsdl2-dev (for example), and i wanted to improve it so it will be compileable on Linux, macOS and Windows (with MinGW) without pre-installing required libraries.

i downloaded libraries' sourse code from SDL Github (for example SDL2) and compiled them on Ubuntu and macOS using ../configure --prefix=/some/path; make; make install in "build" folder that i had created in folder with source code after unzipping downloaded archive. as for Windows, i downloaded SDL2-devel-2.32.0-mingw.zip (as for SDL2) from the same source and just extracted "i686-w64-mingw32" folder from it.

after that i uploaded obtained folders (i686-w64-mingw32 for Windows and that plased in /some/path from --prefix for Linux and macOS) on my game's Github repository renamed them like "SDL2", "SDL2_image", etc. respectively and at the end deleted that folders where i compiled libraries.

so the structure of my project is something like that:

  • game_dir
    • inc/header.h
    • resources
      • frameworks
        • linux
          • SDL2
            • bin/sdl-config
            • include/SDL2/.h files
            • lib
              • cmake/SDL2
                • sdl2-config.cmake
                • sdl2-config-version.cmake
              • pkgconfig/sdl2.pc
              • libSDL2.a libSDL2.la
              • libSDL2_test.a libSDL2_test.la
              • libSDL2-2.0.so.0.3200.0
              • libSDL2main.a libSDL2main.la
            • share/aclocal/sdl2.m4
          • SDL2_image this three have
          • SDL2_mixer "include" and "lib" folders
          • SDL2_ttf (same as in "SDL2" folder)
        • macos the same structure with "linux" folder (but instead .so files there are .dylib files)
        • windows there are also bin/.dll files and .dll.a files in "lib"
      • folders with images, music, etc.
    • src/.c files
    • Makefile
    • .dll files for Windows

then i cloned my repository and tried to compile the code with such Makefile:

executable:=mygame

inc_dir:=inc
src_dir:=src
obj_dir:=obj
lib_dir:=resources/frameworks/

src_files:=$(wildcard $(src_dir)/*.c)
obj_files:=$(src_files:$(src_dir)/%.c=$(obj_dir)/%.o)

compiler:=gcc
cc_flags:=-std=c11 -Wall -Wextra -Werror -Wpedantic
inc_flags=-I$(inc_dir) \
    -I$(lib_dir)/SDL2/include/SDL2 \
    -I$(lib_dir)/SDL2_image/include/SDL2 \
    -I$(lib_dir)/SDL2_mixer/include/SDL2 \
    -I$(lib_dir)/SDL2_ttf/include/SDL2
lib_flags=-L$(lib_dir)/SDL2/lib -lSDL2main -lSDL2 \
    -L$(lib_dir)/SDL2_image/lib -lSDL2_image \
    -L$(lib_dir)/SDL2_mixer/lib -lSDL2_mixer \
    -L$(lib_dir)/SDL2_ttf/lib -lSDL2_ttf

newdir:=mkdir
removedir:=rm
removefile:=rm

ifeq ($(OS),Windows_NT)
    lib_dir:=$(lib_dir)windows
    lib_flags:=$(lib_flags) -lmingw32 -mwindows
    removedir:=rmdir /s /q
    removefile:=del
else
    newdir:=mkdir -p
    removedir:=rm -rf
    removefile:=rm -f
    ifeq ($(shell uname),Darwin)
        lib_dir:=$(lib_dir)macos
    else
        lib_dir:=$(lib_dir)linux
    endif
endif

all: $(executable)

$(executable): $(obj_files)
    $(compiler) $(cc_flags) $^ -o $@ $(inc_flags) $(lib_flags)

$(obj_dir)/%.o: $(src_dir)/%.c | $(obj_dir)
    $(compiler) $(cc_flags) -c $< -o $@ $(inc_flags)

$(obj_dir):
    $(newdir) $(obj_dir)

clean:
    $(removedir) $(obj_dir)

uninstall: clean
    $(removefile) $(executable)

reinstall: uninstall all

.PHONY: all clean uninstall reinstall

it works perfectly on Windows, but on Linux and macOS when it comes to compile executable file, such errors occur:

  • on Linux:
/usr/bin/ld: resources/frameworks/linux/SDL2/lib/libSDL2.a(SDL_stdlib.o): In function «SDL_fmod_REAL»:
/path/to/directory/where/i/compiled/library/(that_does_not_exist_now)/src/stdlib/SDL_stdlib.c:279:(.text+0x35d): undefined reference to `fmod'
...
collect2: error: ld returned 1 exit status
make: *** [Makefile:46: mygame] Error 1
  • on macOS:
Undefined symbols for architecture x86_64:
    "_CFArrayAppendValue", referenced from:
        _GetDisplayMode in libSDL2.a(SDL_cocoamodes.o)
    ...
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [mygame] Error 1

there are a lot of errors on every of that os, they just have the same syntax so i gave only one of them for each os for example. also problems are not only with SDL2 but with other libraries too.

actually, when i use frameworks (that things like SDL2.framework) on macOS (of cource with a bit different Makefile), it works too, but i want everything to be "in one style" with "include" and "lib" folders for each os. can it be possible?

i thought adding -static or -Wl,-Bstatic to lib_flags or using -l: instead of -l or specifying the path to library like for example $(lib_dir)/SDL2/lib/libSDL2.a can solve that problems, but it still doesn't work.

maybe i need to compile libraries with some extra flags or upload dependency libraries like freetype2 for SDL2_ttf or just somehow improve my Makefile?

thank you in advance!

versions of operating systems on which i worked: Ubuntu 24.04, macOS 11.1.0 installed on VirtualBox.

(also sorry if i have some mistakes in my english, it's not my native language)

1 Answer 1

0

To get fmod work on Linux, add -lm to your gcc command line, to link against the math library.

The order in which you specify libraries in the gcc command line matters, especially for static libraries (.a files). The general rule of thumb is: if library X depends on library Y, then specify -lX before -lY, or libX.a before libY.a. So -lm should be somewhere near the end.

You don't have to specify -lc, because libc is automatically added to the end.

See answers to Compiling with GLFW3, linker errors 'undefined reference' about which -l... flags you should add for _CFArrayAppendValue on macOS.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.