maia-s / sdl3-sys-rs

Low level Rust bindings for SDL 3
zlib License
9 stars 1 forks source link

Option to build/link SDL #2

Closed maia-s closed 1 month ago

maia-s commented 2 months ago

The SDL maintainers have requested that SDL isn't distributed until the ABI is stable, so this is blocked on that. https://github.com/libsdl-org/SDL/issues/10792 (issue about vcpkg, but applies in general)

maia-s commented 1 month ago

So the plan for this was to have a separate crate for building and linking SDL from source, as an optional feature enabled dependency of sdl3-sys, so people who just wanted to link to a pre-existing library wouldn't need the extra download, and the from-source crate could have features to configure the build without cluttering sdl3-sys with them. But I've discovered a flaw with this plan: The cargo links property.

Crates that link with a native library are expected to set the links property in the cargo manifest. Cargo ensures that only one crate in the dependency tree can set its links property to a given value.

The issue with this is that the source crate would link with its built version, so it should have the links property set to the library name for SDL 3. But if sdl3-sys isn't built with the feature to build from source, it would link a dynamic library or framework on its own, so it should also have the links property set. But then when building from source, we'd have two crates in the dependency tree with the same links property. I don't think it can be set or not based on a feature flag.

We could split out linking pre-existing libraries into a separate crate too and set the links property for that, but then we'd have mutually exclusive features to select which to depend on in sdl3-sys (afaik it's not possible to depend on a crate only if a feature is disabled), and we couldn't enable one by default without requiring every dependent of sdl3-sys except for the main crate to disable default features, or the main crate would lose the ability to enable build from source (if linking a pre-existing library is the default)

Our options then are:

  1. Abandon the multi-crate plan and put the source and features for it in sdl3-sys
  2. Set the links property for sdl3-sys, but don't set it for the source crate (under the assumption that nothing will depend on the source crate without sdl3-sys)
  3. Split linking into its own crate too, with the drawbacks above

I think I'm leaning towards 2 myself, but I'd like to hear opinions if anyone has any

maia-s commented 1 month ago

I resolved this by making it so the source crate only builds and doesn't link. It requires passing the include path from that crate to sdl3-sys so sdl3-sys can link, but it seems to work.

maia-s commented 1 month ago

SDL 3 went ABI stable yesterday. I'm going to publish a new preview release with everything, but sdl3-sys doesn't link some required libs so I'm going to fix that first.

Lokathor commented 1 month ago

is the list as simple as "check what the cmake script does and make the build.rs tell those to cargo"? that's what it was for sdl2

maia-s commented 1 month ago

When building from source, SDL generates a pkg-config .pc file with the required information, so I wrote a little tool to parse that. (We can't use the pkg-config crate for that, because pkg-config typically isn't installed on macos or windows, and it doesn't have an option to read an arbitrary pc file anyway)

When linking a pre-existing library, we can use pkg-config or vcpkg, or use a framework on macos.

maia-s commented 1 month ago

I've published sdl3-sys 0.0.10 now, which includes this. I've tested and verified that it works on macos, linux, windows and emscripten.

felipetesc commented 1 month ago

I've published sdl3-sys 0.0.10 now, which includes this. I've tested and verified that it works on macos, linux, windows and emscripten.

If I run cargo add sdl3-sys to my project, what missing steps I'll need to add so I can test on Windows ? (if possible, could you add this info to the readme.md) Thanks.

maia-s commented 1 month ago

If you want to link a pre-existing dynamic/shared SDL library (version 3.1.3 or later) that's already in the default link path so it can be found by Rust, you don't have to do anything.

Otherwise, on Windows, you can choose to use either pkg-config or vcpkg to find and link the library with the use-pkg-config or use-vcpkg feature flags, respectively (tho the vcpkg package isn't available yet), or you can choose to build and link SDL from source with the build-from-source feature. On Windows this currently works best if you build and link a static library (link-static, or build-from-source-static to enable both). link-static is not recommended if you don't use the build from source option.

So in summary, do one of

I'll add this to the readme, thanks for the reminder!

felipetesc commented 4 weeks ago

Thanks.