Hi, I was trying to follow this interesting tutorial:
https://hookrace.net/blog/writing-a-2d-platform-game-in-nim-with-sdl2/
where essentially you create a little 2d platformer game in Nim programming language using sdl libraries.
I am using NixOS, and added the following packages in configuration.nix (and obviously rebuild switch), as they are requirements for the tutorial
SDL2
SDL2_ttf
SDL2_image
I also installed the wrapper for sdl with Nimble package manager.
But I get the following error:
nim -r -d:nimDebugDlOpen c platformer.nim
Hint: used config file '/nix/store/y8319d8cyqpn88fsjdx2a8rs8vrbfgi5-x86_64-unknown-linux-gnu-nim-wrapper-1.4.6/etc/nim/nim.cfg' [Conf]
Hint: used config file '/nix/store/y8319d8cyqpn88fsjdx2a8rs8vrbfgi5-x86_64-unknown-linux-gnu-nim-wrapper-1.4.6/etc/nim/config.nims' [Conf]
Hint: 19397 lines; 0.022s; 25.57MiB peakmem; Debug build; proj: ~/nim/platform/platformer.nim; out: ~/nim/platform/platformer [SuccessX]
Hint: ~/nim/platform/platformer [Exec]
libSDL2.so: cannot open shared object file: No such file or directory
could not load: libSDL2.so
Error: execution of an external program failed: '~/nim/platform/platformer '
using locate SDL2.so
I get this:
/nix/store/48vr0zs888fd8zwq3dkqcvg6h2xl8ip5-system-path/lib/libSDL2.so
/nix/store/bqr0n7k2pwwk7bz9zr2ypvmk6mj0kwnd-SDL2-2.0.14/lib/libSDL2.so
How can I make the executable find and load the library? Sorry if this is a stupid question
Installing libraries system-wide intentionally does not work with nix. All compilation-related tasks must be performed inside nix-shell. In your case, I suspect it should work with
nix-shell -p nim SDL2 SDL2_ttf SDL2_image
although nim might have specific complications.
See also FAQ/I installed a library but my compiler is not finding it. Why? - NixOS Wiki
Hi symphorien, thanks for your answer. I tried your recommendation, but I get the same result.
nix-shell -p nim SDL2 SDL2_ttf SDL2_image
# Then, inside new shell
nim -r c platformer.nim
Gave
Hint: used config file '/nix/store/y8319d8cyqpn88fsjdx2a8rs8vrbfgi5-x86_64-unknown-linux-gnu-nim-wrapper-1.4.6/etc/nim/nim.cfg' [Conf]
Hint: used config file '/nix/store/y8319d8cyqpn88fsjdx2a8rs8vrbfgi5-x86_64-unknown-linux-gnu-nim-wrapper-1.4.6/etc/nim/config.nims' [Conf]
Hint: 19397 lines; 0.022s; 25.375MiB peakmem; Debug build; proj: ~/nim/platform/platformer.nim; out: ~/nim/platform/platformer [SuccessX]
Hint: ~/nim/platform/platformer [Exec]
could not load: libSDL2.so
(compile with -d:nimDebugDlOpen for more information)
Error: execution of an external program failed: '~/nim/platform/platformer '
I will read documention on nix-shell, never used it working with Go programming language, but I see how using C libraries this is useful/needed. If you or anyone have other suggestions I am interested
UPDATE
I’ve missed a thing: I was trying to compile and run in a single command with nim -r c platformer.nim
.
Separating the two steps I see that compilation complete without errors using nim c platformer.nim
(without -r
for run
), a binary is produced in the same directory, BUT it will not run giving:
./platformer
# -->
libSDL2.so: cannot open shared object file: No such file or directory
could not load: libSDL2.so
So, the real problem is about running the executable, not compiling it!
I have tried to run it in a nix-shell declaring libs but with the same result as before. Now, this is… interesting. How to run it?
rereading your initial post, it looks like nim is using dlopen. To make dlopen work you need to force the linker to link to the libraries at compile time with -lfoo
instead of trusting they will be found at run time. The nim compiler may or may not have flags to do that, but nixpkgs’s gcc comes with a way to do that behind nim’s back:
export NIX_LDFLAGS="-lSDL2 -lwhatever $NIX_LDFLAGS"
Again, this only works inside nix-shell.
You can check what exact flags are passed to the c compiler and linker with export NIX_DEBUG=1
Thanks again symphorien, you really are a great contributor.
I am in the process of trying your advice, passing arguments to gcc exporting variables, but I am a little discouraged, this seems to be overly complex (for me) and I don’t see how I can adopt Nim as an hobby programming language with all this overhead. My scarce understanding of Nix, added to my low knowledge of C make all this a difficult territory to navigate. Where I can study about this intersection (Nim + C or Nim development)?
UPDATE
It now works!!! Symphorien, your command from your first message:
nix-shell -p nim SDL2 SDL2_ttf SDL2_image
actually works, I just needed to delete the binary generated from other previous attempts, as it is not replaced by Nim if not changed.
I can follow the tutorial now. I will make a little shell script to enter the nix-shell without typing every single library every time (maybe there is another solution)
Thank you, very much
I will make a little shell script to enter the nix-shell without typing every single library every time (maybe there is another solution)
In the directory of your source code, you can put a file call shell.nix
with this content:
with import <nixpkgs>;
mkShell {
buildInputs = [ nim SDL2 SDL2_ttf SDL2_image ];
}
and when you run nix-shell
without arguments in this directory, you will get the same effect as nix-shell -p nim SDL2 SDL2_ttf SDL2_image
.
If you find it inconvenient to have to remember to enter the shell every time you cd
the directory, and to exit it and enter it again when you modify shell.nix, there are tools to enhance your workflow like GitHub - nix-community/lorri: Your project’s nix-env [maintainer=@Profpatsch] or GitHub - nix-community/nix-direnv: A fast, persistent use_nix/use_flake implementation for direnv [maintainer=@Mic92]. But these tools are absolutely not required and add some amount of complexity and magic, so if you are satisfied with manually running nix-shell
by all means keep doing this 
2 Likes
Yes, I much prefer less magic, so I am using now your shell.nix file, it is cleaner than my approach and not invasive. You helped me so much… Many thanks