Trying to install tsdl on windows

I’m trying to have tsdl package installed on windows.

$ opam --version
2.3.0

$ opam switch
#  switch   compiler                                                                        description
→  default  arch-x86_64.1,ocaml-base-compiler.5.2.1,ocaml-options-vanilla.1,system-mingw.1  ocaml >= 4.05.0

As usual with OCaml packages, everything becomes difficult when installing/linking foreign language code; SDL2 library, in this case.

According to tsdl package (opam show tsdl):

Tsdl depends on the [SDL 2.0.10][sdl] C library (or later)

I later discovered in tsdl changelog that we need 2.0.18:

$ head CHANGES.md | ag "SDL "
Require SDL >= 2.0.18.

2025-01-04 Edit (Daniel regenerated the opam file): TODO: PR against tsdl opam file

So, I’m going to try SDL 2.0.18. Unfortunately, I can’t use conf-sdl2 package without modification: it relies on depext, but cygwin package is an older version.

So, as an experiment, I’m going manually. I wonder wether if we could have conf-sdl2 (or another package) do the same thing?

SIDE STEP: because conf-wget depext is not defined for cygwin:

$ opam source conf-wget
$ cd conf-wget.1
$ cat <<FIN > wget.patch
> --- opam        2024-12-25 10:07:28.339965700 +0100
+++ opam.new    2024-12-24 17:09:48.385631000 +0100
@@ -23,4 +23,5 @@
   ["wget"] {os-distribution = "alpine"}
   ["wget"] {os-distribution = "centos"}
   ["wget"] {os = "freebsd"}
+  ["wget"] {os-distribution = "cygwin"}
 ]
FIN
$ patch < wget.patch
$ opam install .

Note: conf-wget PR submitted as Add depext for cygwin & opensuse to conf-wget by ttamttam · Pull Request #27176 · ocaml/opam-repository · GitHub.
2025-01-04 Edit: the PR was merged.

Back to SDL2. Not sure why this patch is needed?

$ opam source conf-sdl2
$ cd conf-sdl2.1
$ wget https://github.com/libsdl-org/SDL/releases/download/release-2.0.18/SDL2-devel-2.0.18-mingw.tar.gz
$ sha256sum SDL2-devel-2.0.18-mingw.tar.gz
bbad7c6947f6ca3e05292f065852ed8b62f319fc5533047e7708769c4dbae394 *SDL2-devel-2.0.18-mingw.tar.gz
$ tar xzf SDL2-devel-2.0.18-mingw.tar.gz
$ cd SDL2-2.0.18
$ cat <<FIN > pkgconfig.patch
--- x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc    2021-11-30 05:24:06.000000000 +0100
+++ /usr/local/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc 2024-12-25 10:59:53.557284700 +0100
@@ -10,6 +10,6 @@
 Version: 2.0.18
 Requires:
 Conflicts:
-Libs: -L\${libdir}  -lmingw32 -lSDL2main -lSDL2 -mwindows 
+Libs: -L\${libdir}  -lSDL2
 Libs.private:  -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid
 Cflags: -I\${includedir}/SDL2  -Dmain=SDL_main
FIN
$ patch -p0 < pkgconfig.patch
$ mkdir -p /usr/local/x86_64-w64-mingw32
$ make cross

Now, tsdl:

$ opam source tsdl
$ cd tsdl.1.1.0/
$ opam install ocamlfind ocamlbuild topkg ctypes ctypes-foreign conf-pkg-config -y

Unfortunately, conf-pkg-config installs pkgconf.exe. But tsdl expects pkg-config.exe.

$ ln -s "$(dirname $(which pkgconf.exe))/pkgconf.exe" "$(dirname $(which pkgconf.exe))/pkg-config.exe"

Actual tsdl compilation:

$ ocaml pkg/pkg.ml build --tests true

Running tests one by one.

  • test_audio: I don’t know how to interrupt this test. When I close the example’s window, the `Quit event is catched, but Sdl.quit(); does not return
  • test_tsdl: needs some adjustments (because of warnings “-27” and “-32”, mainly). And fails in some places:
    • Getting ‘Unknown sensor type’ error just after Sdl.init Sdl.Init.everything.
    • assert (Sdl.get_clipboard_text () = Ok "öpooo"); fails. But in a strange way: I was able to retrieve and log the expected string. So, seems like it is a multithreading/synchronisation error?

Too many issues. How could we solve them, step by step?

Best regards

Matt

Hello, If you have difficulties to compile tsdl on windows, maybe you could try ocamlsdl2.
This other package doesn’t have other dependencies than ocaml, and sdl2. It uses the default ffi from ocaml, not ctypes.
And if you group all your sdl2 calls inside a display callback, you can easily rewrite it later when you get tsdl working.
Personally, I had no difficulties to compile “ocamlsdl2” on windows.
The only issue I got with ocamlsdl2 is that I can not access the joypad on crostini, but this a probably an issue with sdl2, so we will probably get the same issue with any bindings.
But if you really prefer the tsdl interface, we could also imagine to fork “ocamlsdl2” as “ocamlsdl2t” where we rewrite the interface with tsdl function names, in hope to get compatible code.

Well. My goal is not tsdl: I’d like to play with bogue. But only if I can port what I would write on Windows, even if I prefer working on Linux.

I focussed on the tsdl package, because it’s the first dependency listed in bogue.opam.

I did not look at tsdl-image and tsdl-ttf yet.

I managed to install SDL 2.0.18 by hand in order to satisfy conf-sdl2: installation of a pre-compiled (mingw) version + adjustment of the associated pkgconfig sdl2.pc file

The next issue is the fact that conf-pkg-config installs pkgconf.exe while tsdl expects pkg-config.exe. I solved this locally with a symlink. I also updated tsdl ocamlbuild script to first look for pkgconf before falling back to pkg-config, but did not test it yet: if it works, I’ll propose this update.

Best regards

If someone could educate me on the difference between pkgconf and pkg-config that would be great. In any case if I ask for a conf-pkg-config dependency in opam I expected the tool pkg-config to be installed, so I think this should be somehow solved at the opam level rather than in individual build systems.

I think that @jbeckford was able to install bogue on windows, you should maybe ping him

I may be wrong, but for some reason, it seems that cygwin is installing pkgconfig instead of pkg-config. I wonder wether if it is to avoid some issues with the ‘-’ char?

I proposed a small update of ´tsdl´’s ´ocamlbuild.ml´ script to look for ´pkgconfig´ in the PATH or fallback to ´pkgconfig´.

Since I do not know why ´pkgconfig´ was used instead of ´pkg-config´, I don’t know if an alias or copy would be accepted upstream.

That doesn’t really answer my question.

As I hinted, I don’t think that’s the right place to fix that.

He is using his own distribution, I guess. I’d rather stick to the default opam (with it’s own cygwin) install.

Since the only packages using ´conf-sdl2´ are ´tsdl2´ and ´ocamlsdl2´, we may be able to find a solution. Maybe by disabling ´depext´, and providing instructions, for SDL2 installation? Or through a contribution to cygwin, to provide a more recent version.

You’ll need to:

  1. Make a copy of pkgconf.exe (which is a Windows-friendly spec-compatible alternative to pkg-config) as pkg-config.exe in your PATH. I think the default Win32 opam 2.2 already does this, although I can’t remember the exact mechanism for that. (DkML does this inside conf-pkg-config)
  2. Re: “stick to the default opam (with it’s own cygwin) install” and “Or through a contribution to cygwin, to provide a more recent version.”. Given the constraints you listed, making your own contribution to Cygwin seems to be the only path forward. That would be helpful for other OCaml users as well.

For anybody else coming to this thread who does not have a technical requirement to use Cygwin, you can play with Bogue and tsdl by doing:

PS> git clone https://github.com/diskuv/dkcoder.git
PS> echo "" > Ok.ml
PS> dkcoder/dk DkRun_V2_2.Run repl -g dune ./Ok.ml
...
INFO: Using SDL 2.30.0
--- DkCoder 2.2.1 (OCaml 4.14.2) REPL
Down be49e02b0 loaded. Type Down.help () for more info.
...

# open Tr1Stdlib_V414All ;;
# Topfind.load_deeply ["bogue"] ;;

(* This is "Hello World" directly from
    https://github.com/sanette/bogue?tab=readme-ov-file#hello-world *)

# open Bogue

let () =
  Widget.label "Hello world"
  |> Layout.resident
  |> Bogue.of_layout
  |> Bogue.run
;;

Just to try to clarify some of what’s definitely confusing about this in opam-repository at the moment. There are multiple issues at play:

  • In both MSYS2 and Cygwin, pkg-config is in fact from the pkgconf project
  • In MSYS2, the toolchain is native and both the pkgconf or pkg-config relate to libraries available for gcc which is actually the mingw-w64 gcc
  • In Cygwin, pkgconf adds a symlink for pkg-config (which isn’t readily accessible to native Windows processes, therefore). However, mingw-w64 gcc in Cygwin is a cross-compiler so even if pkg-config were made available, it is not the command which is required

opam-repository-mingw shimed this by creating a pkg-config.exe which silently added the additional flags to kinda make this work. I’m rather against that kind of magic (at least, I’m certainly not willing to maintain and support it). What’s needed is for the conf- packages and associated packages to recognise that the exact command varies, and add --personality and so forth as required. That’s been being gradually done in some PRs and at some point this year might even get applied “wholesale” to the conf- packages. (cf., amongst others’ efforts, opam - opam 2.2.0~beta2 - Windows OCaml and Update conf-libssl for the mingw-w64 ports by dra27 · Pull Request #26072 · ocaml/opam-repository · GitHub)

Just to be clear. So you suggest that build systems should be ready to support pkgconf and pkg-config which are basically two names for the exactly the same thing ?

It is still unclear to me what is the value added here. I mean does it mean that we are going to have conf-pkg-config and conf-pkgconf opam packages and that if I want to probe for a C library in my build system I need to add these two packages ? That feels like a lot of bureaucracy.

If pkgconf is:

why doesn’t it simply install itself as pkg-config or at least does so if it doesn’t find a pkg-config binary ?

I agree with @dra27 that it’s likely not a good idea to do it ourselves in opam but what about suggesting that upstream ?

The pkgconf / pkg-config part is an unfortunate wart - it’s much more that I think that build systems need to be aware that neither pkg-config nor pkgconf are necessarily sufficient on their own. My feeling is that once the build system needs to worry about whether it’s calling pkg-config or pkg-config --personality=x86_64-w64-mingw32 that whether it’s actually pkgconf or pkg-config before the --personality is somewhat moot! (that part’s “a feeling” - I’m fairly certain, as was briefly the case the case with opam’s pkg-config package, that installing a binary called pkg-config which magically calls pkgconf --personality=x86_64-w64-mingw32 is more trouble in the long-term than it’s worth).

What I’d really like (and have done for a while), is to have opam packages conf- packages correctly wrap all this - i.e. the installing of conf-tsdl, etc., is responsible for providing the information to build systems as to what the required, libs, flags, etc., are, hiding all this difference in the language package manager, rather than punting it down to build systems (one day, I may even propose something looking it…!)

Well FWIW I find that a rather bad idea. I’m not interested in my software to depend on a particular package manager. Package managers come and go and cater for different needs (e.g. system packagers). Depending on opam to build my software makes the task of system packagers needlessly complicated and is not compositional (as we now famously know with rust).

So I’m fine with my software to simply depend on the de facto compilation manager for C, the only thing I’m annoyed here is that it seems there are now two of them doing the same thing for C whereas I was used to have to only deal with a single one.

Oh, indeed - I don’t mean that it would create an absolutely dependency on opam (or anything else)… it’s more that we have a slightly odd half-way house where a lot of packages (and their builds system) do depend on, say, conf-pkg-config to provide pkg-config so that it can be used by another conf-libfoo package to determine that libfoo is “installed” for some value of installed. If an opam conf- package is being used to get the system to a state where it’s providing the package (which is something a build system could choose to do), then it’d be quite nice for that conf- package to be providing all that information. In particular, I think it’s then somewhat more natural to be able to override exactly how the package was provided (e.g. by building it from sources, etc.). Being able to do that then stems back to an old idea… GitHub - dra27/windows-native: OPAM Repository for mingw64/msvc Libraries :blush:

So apparently pkgconf devs leaves symlinking itself to pkg-config to platform integrators, so I guess I have to be prepared for the mess of checking multiple tools.

But one question remains for the OCaml opam repository. When I publish my package, which conf package should I depend on to make sure either tool is available ? Could at least the OCaml opam repository abstract me that, i.e. if I request conf-pkg-config, either tool will be available ?

Yes, it (definitely) could - but that still leaves divining the additional options depending on the platform (and the provider of the platform)?