[ANN] raylib-ocaml 0.1.0

Hello,

I’d like to announce the first version of raylib-ocaml, a binding to the awesome raylib game development library. The release can be found on opam as “raylib”.

The bindings are nearly complete, as far as functions and types go, but only a subset was tested so far. I will work on bringing more of the numerous examples of the C version to OCaml in the future.

Currently, raylib-ocaml only works on Linux, but I plan to support Windows (and possibly other targets) in the future.

Feel free to give it a spin and please report any issues you run into.

12 Likes

Cool! Are you also going to write a game using these bindings?

Yes, hopefully some day. The plan is to use these bindings for prototyping and seeing where this gets me :wink:

1 Like

I installed last git version with opam install .
Then when I try an example I get a segmentation fault:

ocamlfind ocamlopt -o shapes_collision_area.opt -linkpkg -package raylib  shapes_collision_area.ml
./shapes_collision_area.opt 
INFO: Initializing raylib 3.0
WARNING: GLFW: Error: 65543 Description: GLX: Failed to create context: GLXBadFBConfig
WARNING: GLFW: Failed to initialize Window
INFO: TIMER: Target time per frame: 16.667 milliseconds
Segmentation fault (core dumped)

After trying to compile the pure C examples of the original lib, I get the same error.
Found this issue:
https://github.com/raysan5/raylib/issues/796
indeed:

glxinfo | grep -i "OpenGL version"
OpenGL version string: 2.1 Mesa 20.0.7

If I compile raylib with:

make PLATFORM=PLATFORM_DESKTOP GRAPHICS=GRAPHICS_API_OPENGL_21 -B
make PLATFORM=PLATFORM_DESKTOP GRAPHICS=GRAPHICS_API_OPENGL_21 -B RAYLIB_LIBTYPE=SHARED

Then the pure C examples provided with raylib do work as expected.

How to compile the ocaml bindings to use this make option?

Does the ocaml binding include the underlying C lib? Is it allowed in opam?

Thanks for testing out the bindings :slight_smile:

The ocaml library does indeed include the C library. I thought it would be more convenient to compile it at build time than requiring the user to (globally) install the C lib themselves. I don’t know whether this is allowed or not in opam. If it’s not, I will change it.

Compiling the C lib automatically of course leads to problems like yours, where the compile options you need don’t match with the ones I chose. As an alternative, dune could look for a globally installed version and only compile the C lib if it cannot find one. This would solve your problem, I think.

Is there a way to specify options through opam (and dune subsequently)? Such that a user could install raylib, but with backend gl2.1 instead of gl3.3 for example?

1 Like

Environment flags are passed through to the opam sandbox. That could be an option

1 Like

Yes, I just realized!

@fccm If you pass (at build time) the GRAPHICS option through an environment variable, it should be picked up by the Makefile. On my PC, I could create a opengl 2.1 executable by setting it export GRAPHICS=GRAPHICS_API_OPENGL_21:

INFO: DISPLAY: Device initialized successfully
INFO:     > Display size: 2560 x 1440
INFO:     > Render size:  800 x 450
INFO:     > Screen size:  800 x 450
INFO:     > Viewport offsets: 0, 0
INFO: GLAD: OpenGL extensions loaded successfully
INFO: GL: OpenGL 2.1 profile supported

Does this work for you?

1 Like

Yes, it does work on my computer!

Before to get this answer I was trying to edit the file raylib-ocaml/src/c/dune as follow:

diff --git a/src/c/dune b/src/c/dune
index 8c32d27..34f3674 100644
--- a/src/c/dune
+++ b/src/c/dune
@@ -34,22 +34,22 @@
 (rule
  (alias build-raylib)
  (targets libraylib.a dllraylib.so)
  (enabled_if
   (or
    (= %{system} linux)
    (= %{system} linux_elf)))
  (deps
   (source_tree vendor)
   linux.patch)
  (action
   (no-infer
    (progn
     (run chmod +w vendor/src/config.h)
     (with-stdin-from
      linux.patch
      (run patch --binary -p1))
-    (run make -C vendor/src RAYLIB_LIBTYPE=STATIC -j 8)
+    (run make -C vendor/src RAYLIB_LIBTYPE=STATIC GRAPHICS=GRAPHICS_API_OPENGL_21 -B -j 2)
     (copy vendor/src/libraylib.a libraylib.a)
     (run make -C vendor/src clean)
-    (run make -C vendor/src RAYLIB_LIBTYPE=SHARED -j 8)
+    (run make -C vendor/src RAYLIB_LIBTYPE=SHARED GRAPHICS=GRAPHICS_API_OPENGL_21 -B -j 2)
     (copy vendor/src/libraylib.so.3.0.0 dllraylib.so)))))

But when I tryed to install it with opam install --working-dir . I get the following error:

$ opam install --working-dir .
[...]
# File "src/c/dune", line 9, characters 16-48:
# 9 |   (include_dirs %{project_root}/src/c/vendor/src))
#                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Error: Include directory "vendor/src" does not exist.

I have another question about this build, if I compile a mini-game with this binding using gl2.1 and upload it on itch.io, will it work for people using a more recent computer with gl3.3?

(with my sdl2 binding it seems that my binary executables work on other computers, for both linux and windows, I built on Windows 7 and it still works on Windows 10 targets. And seems like the linux build also works for other people using linux too)

Good to know!
The error comes from the fact that the raylib source code is a submodule of the bindings repo, and git doesn’t clone these automatically, if you don’t tell to explicitly with --recursive. If you initialize the submodules with git submodule update --init --recursive your code should work. I will put up a notice into the README about this.

Generally, an opengl 3+ driver should be able to work with gl2.1, so yes, this will work.
The raylib C library is linked statically, so the executables only link against some common Linux libs (X, pthread, m), which are available on nearly every distro. As long as you build on a distro, which sticks to the usual directory layout (ie not NixOS), the build should be portable.
The same goes for windows, where only some windows libs are linked.

1 Like

Is this ready for windows already?

Yes, it is. Since version 0.2 it works with the mingw64 variant of the compiler.
Unfortunately, ctypes does not support the msvc switches, so no luck there.

When I last used it on windows, installing worked flawlessly from opam.

Oh sorry for my concise question. What I wanted to know is if I can use it to build windows, Linux and MacOS binaries. I’m interested on raygui so I can build quick tools for my family and coworkers on a cross-platform fashion but using a nice language that doesn’t bloat their computers.

What I wanted to know is if I can use it to build windows, Linux and MacOS binaries.

Totally. That’s what @tjammer is doing with his open-source game:

2 Likes

That is very cool, thabks dot the links.
I took a look at the repository and I saw it uses a build matrix for cross compile, but there are no releases available.
How does he handle the cross compilation then?

I do use github actions for cross compilation, but don’t upload every build as a new release on github.
Instead I use an upload-artifact action to save the build artifacts instead of discarding them. They show up in the actions tab next to each run, see Build in release mode and strip · tjammer/tacs@662e2a2 · GitHub

The action can be found here
I guess one could also automatically create a github release on each new tag or so but I haven’t looked into that.

As for the raygui bindings: They work in principle, as demonstrated by the example. But the usability is sub-optimal compared to something like dear imgui. The reason for that is that raygui makes the user handle all the widget state, which makes the API more verbose than necessary. Hopefully one day we can have dear imgui bindings.

1 Like

I am doing this on some of my projects if you want to have a look how it van be done (not sure if it is the cleanest way)

1 Like

Thanks for your detailed answer. I just assumed that the artifacts action was uploading it as part of a release, but your need to create a release before I guess. There are plenty of actions for automatically bump version tags and create releases, but I don’t know which to recommend.

About the raygui library, how different is that from, let’s say, manage the state on the browser for example? Will it be possible to implement some kind of Elm like flow or it is much more than that?
Imgui looks impressive, indeed, but I don’t know how well can it be translated to a functional way of working like the one OCaml has.