Rust-SDL2 / rust-sdl2

SDL2 bindings for Rust
MIT License
2.74k stars 468 forks source link

undefined references: SDL_JoystickRumble and SDL_GameControllerRumble #865

Open Lokathor opened 5 years ago

Lokathor commented 5 years ago

So I tried to build the master branch of sdl2-rust on my fresh install of Retropie 4.4. According to apt-get I have libsdl2-dev 2.0.8+1rpi installed

pi@retropie:~/rust-sdl2 $ apt-cache policy libsdl2-dev
libsdl2-dev:
  Installed: 2.0.8+1rpi
  Candidate: 2.0.8+1rpi
  Version table:
 *** 2.0.8+1rpi 100
        100 /var/lib/dpkg/status
     2.0.5+dfsg1-2+rpt1 500
        500 http://archive.raspberrypi.org/debian stretch/ui armhf Packages
     2.0.5+dfsg1-2 500
        500 http://raspbian.raspberrypi.org/raspbian stretch/main armhf Packages

And I get two missing references when I try to build

  = note: /home/pi/rust-sdl2/target/debug/deps/libsdl2-8663cbe83c9e210b.rlib(sdl2-8663cbe83c9e210b.29daxunmqjdw9icw.rcgu.o): In function `sdl2::joystick::Joystick::set_rumble':
          /home/pi/rust-sdl2/src/sdl2/joystick.rs:366: undefined reference to `SDL_JoystickRumble'
          collect2: error: ld returned 1 exit status

and

  = note: /home/pi/rust-sdl2/target/debug/deps/libsdl2-8663cbe83c9e210b.rlib(sdl2-8663cbe83c9e210b.rk4bjp3n3fd9lne.rcgu.o): In function `sdl2::controller::GameController::set_rumble':
          /home/pi/rust-sdl2/src/sdl2/controller.rs:424: undefined reference to `SDL_GameControllerRumble'
          collect2: error: ld returned 1 exit status

In the repo it looks like you currently have 2.0.9, is this version mismatch possibly the problem?

Lokathor commented 5 years ago

I installed 2.0.9 and it works now. Did I just have a bad version of 2.0.8 or should these functions have some sort of conditional compilation applied maybe?

Cobrand commented 5 years ago

Perhaps they were added after 2.0.9

I thought the functions weren't linked unless actual code uses it, but it looks like either I was wrong, or you had some code that called GameController.

The conditional compilation would be the ideal solution, but it looks like it would be a pain to handle in the long term. I'm open to PRs though.

Lokathor commented 5 years ago

It was just the examples directory of the repo, but i bet at least one example uses the controller stuff.

steveklabnik commented 5 years ago

I'm using 2.0.7 and also getting this, with a project that depends on sdl2 and, as far as I know, doesn't use it.

Cobrand commented 5 years ago

I don't know what the is the rust idiomatic way to do this... My guess would be that we could have features

For instance, you'd have to use --features "use-sdl-2.0.8".

That, or we could say "screw this, force everyone to use the latest version" but this seems pretty risky as well.

steveklabnik commented 5 years ago

One slightly extreme way of doing it would be to have the crate have the ability to build the SDL version it wraps. https://doc.rust-lang.org/stable/cargo/reference/build-scripts.html#case-study-building-some-native-code

That's a big undertaking, of course, but then you'd know that the right version exists. Some crates let you do this via a flag, so like, by default it doesn't, but you can request it.

I don't know enough about SDL's versioning policies to really give great advice here.

Lokathor commented 5 years ago

The official position of SDL2 is that you should generally attempt to be dynamically linked to the sdl2 library, in the hopes that even if you stop updating your app the user can grab the latest sdl2 when there's fixes and your app will then go through their newest version. There's a technical explanation of the details they use for those who are interested. Long story short, the first call into sdl2 does all the dynamic setup you'll need, including setting up the function pointer jump table. The jump table setup is version aware, and will always successfully load the same or newer version, but if it detects that you're trying to load in the DLL of a previous version it'll abort. The example is that if you've compiled against 2.0.4 and they have 2.0.3 installed the jump table startup will abort with an error, but if they have 2.0.4 or later it'll work. (Note that the jump table thing can be disabled if absolutely necessary).

So, where feasible I think that functions from each new version of sdl2 should be gated behind feature flags associated with their versions, and if you want to build using an older sdl2 version for greater compatibility then those functions just quietly don't exist to you. Obviously tagging every single function with what version it's from is probably not an easy task, but it shouldn't be too hard to pick out the 2.0.9 functions and feature flag them so that people can build even with 2.0.8 headers installed.

sunjay commented 5 years ago

I installed SDL2 using apt-get and I have 2.0.8 installed:

$ apt-cache policy libsdl2-dev
libsdl2-dev:
  Installed: 2.0.8+dfsg1-1ubuntu1.18.04.3
  Candidate: 2.0.8+dfsg1-1ubuntu1.18.04.3
  Version table:
 *** 2.0.8+dfsg1-1ubuntu1.18.04.3 500
        500 http://archive.ubuntu.com/ubuntu bionic-updates/universe amd64 Packages
        100 /var/lib/dpkg/status
     2.0.8+dfsg1-1ubuntu1 500
        500 http://archive.ubuntu.com/ubuntu bionic/universe amd64 Packages

Is there a way for me to install SDL2 2.0.9 using apt-get? I am running a workshop using this crate on Thursday and I want to make sure people can install without any issues. Would it be better to just use an older version of the sdl2 crate from before the 2.0.9 changes?

Obviously tagging every single function with what version it's from is probably not an easy task, but it shouldn't be too hard to pick out the 2.0.9 functions and feature flag them so that people can build even with 2.0.8 headers installed.

Is there an upgrade policy for when functions from the latest version of SDL2 are allowed to be added to the crate? I think it would make sense to at least wait until package managers get the new version. Otherwise we're going to see a lot of breakage given that dynamic linking is the recommended way to use this crate.

sunjay commented 5 years ago

Looks like my previous comment is a bit of a false alarm. Sorry about that! It looks like 0.32 builds fine with SDL2 2.0.8. That means that I should have no issues after all. :smile:

I think I was only running into this issue earlier because I was trying to use master.