PMunch/futhark

libwayland: wl_signal_add undeclared identifier

Shinyzenith opened this issue · 21 comments

wl_signal_add is defined in: "wayland-server-core.h"
image
and I have imported the same in my project via importc.
However while calling wl_signal_add I get the error mentioned in the title.
I tried to do some basic debugging by checking opir cache (rg -i wl_signal_add | bat ) and it turns out wl_signal_add was picked up by opir:
image
image

but the function was never bound in nim.

To reproduce, install libwayland using your distributions package manager and try to bind wayland-server.h, wayland-server-core.h, wayland-server-protocol.h
and then simply attempt to call wl_signal_add with no parameters.

Ah yes, this should probably be better explained in the README. Essentially Futhark only generates the definitions for everything, it doesn't actually link against the project. This is because there are so many ways of doing this, and there is no reason you can't just do it yourself outside of Futhark. What you would do is probably to link against something like libwayland with --passL:"-lwayland".

I don't think wayland is a valid link target and I already link with wayland-server which is done by its equivalent c app

You can use nm -a on dynamic, static, and executable files to see which symbols they export. Basically you need to link with whatever supplies that symbol. Or if the header file is actually supplying the implementation you need to do a similar thing to what I do in the example, or maybe even just import the header file with an emit statement or something.

Or if the header file is actually supplying the implementation you need to do a similar thing to what I do in the example

Do what exactly?

I think this is possibly a bug with futhark as I can call this function just fine in zig by linking with wayland-server

Here's the same in C. At the very least GCC acknowledges the existence of the function so I'm really confused.

image
Here's the same with the Zig C compiler.

Wait, is the error you get a Nim error, or an error from the C compiler Nim calls? And how is wl_signal_add defined? If it is inlined Futhark won't touch it.

~/Desktop/compositor/herbwm
 ❯ make
  Verifying dependencies for herb@0.1.0
    Reading official package list
   Checking for futhark@any version
      Info: Dependency on futhark@any version already satisfied
  Verifying dependencies for futhark@#head
    Reading official package list
   Checking for https://github.com/PMunch/libclang-nim@#head
      Info: Dependency on https://github.com/PMunch/libclang-nim@#head already satisfied
  Verifying dependencies for clang@#head
    Reading official package list
   Checking for termstyle@any version
      Info: Dependency on termstyle@any version already satisfied
  Verifying dependencies for termstyle@0.1.0
    Reading official package list
   Checking for macroutils@any version
      Info: Dependency on macroutils@any version already satisfied
  Verifying dependencies for macroutils@1.2.0
   Building herb/herb using c backend
  Executing /usr/bin/nim c --colors:on --noNimblePath -d:release --passL:-lwayland-server --passL:-lwlroots --passL:-lpixman-1 --maxLoopIterationsVM:99999999 -d:NimblePkgVersion=0.1.0 --path:'/home/aakash/.nimble/pkgs/futhark-#head' --path:'/home/aakash/.nimble/pkgs/clang-#head' --path:/home/aakash/.nimble/pkgs/termstyle-0.1.0 --path:/home/aakash/.nimble/pkgs/macroutils-1.2.0 -o:/home/aakash/Desktop/compositor/herbwm/herb /home/aakash/Desktop/compositor/herbwm/src/herb.nim
Hint: used config file '/etc/nim/nim.cfg' [Conf]
Hint: used config file '/etc/nim/config.nims' [Conf]
...............................
/home/aakash/.nimble/pkgs/futhark-#head/futhark.nim(489, 10) Hint: Using cached Futhark output: /home/aakash/.cache/nim/herb_r/futhark_265C434E59F8B1C4.nim [User]
/home/aakash/Desktop/compositor/herbwm/src/herb.nim(43, 1) Error: undeclared identifier: 'wl_signal_add'
     Error: Build failed for package: herb
        ... Execution failed with exit code 1
        ... Command: /usr/bin/nim c --colors:on --noNimblePath -d:release --passL:-lwayland-server --passL:-lwlroots --passL:-lpixman-1 --maxLoopIterationsVM:99999999 -d:NimblePkgVersion=0.1.0 --path:'/home/aakash/.nimble/pkgs/futhark-#head' --path:'/home/aakash/.nimble/pkgs/clang-#head' --path:/home/aakash/.nimble/pkgs/termstyle-0.1.0 --path:/home/aakash/.nimble/pkgs/macroutils-1.2.0 -o:/home/aakash/Desktop/compositor/herbwm/herb /home/aakash/Desktop/compositor/herbwm/src/herb.nim
make: *** [Makefile:12: build] Error 1

entire error log

and yes it is inline

How do I get futhark to pick up on them?

Just to test the theory, I manually edited the header and removed inline and it worked. But that isn't a viable solution.

You can't currently. Essentially an inlined procedure in a header file is just something that the C compiler will automatically add for you. Thus the symbol won't be available in a library if you link against one so the Futhark definition wouldn't work. I'm thinking of ways to get around this, but it's a tricky problem. For now what I've done is simply implement the logic in Nim instead. The logic is typically very straight forward, normally just an alias or something simple like that.

:( I see.

huh if i was able to get the function to work by just removing inline keyword, can't opir do the same as a workaround?

No, as I mentioned earlier Øpir and Futhark doesn't actually give anything but definitions to Nim. So if it lied and said it wasn't inline the C compiler would complain about missing symbols. I have an idea for fixing it, but it's not a very pretty solution.

So as a workaround for now, what should I do ? Redefine the function in nim after looking at the source?

Yeah as I said that's what I've been doing. The things that are inline are typically not much more than a single call to a different function with some default arguments or a cast, so pretty easy stuff to reimplement. It's annoying though, so I really want to get Futhark to handle these better..

Was talking to @Shinyzenith about this problem in the real time chat, could you not emit a template or a procedure that copies the code into a string literal and emits it like the following:

proc wl_signal_add(signal: ptr wl_signal, listener: ptr listener) {.inline.} =
  {.emit: """wl_list_insert(signal->listener.prev, &listener->link);"""".}

That's what I've had in mind. Gotta be careful though that all the symbols from the C code are valid and visible. And in the scenario where you're building against the actual sources and not against the a linked library you'll have to make sure they don't collide..