enigo-rs / enigo

Cross platform input simulation in Rust
MIT License
986 stars 100 forks source link

Unable to link a static library with a C program #330

Closed pythonbrad closed 3 days ago

pythonbrad commented 5 days ago

Describe the bug

When I try to link my static rust library to a C program, I got a link error.

Without enigo, everything is working.

To Reproduce

git clone https://github.com/fodydev/ibus-afrim -b enigo
cd ibus-afrim
cmake -Bbuild --install-prefix /tmp && cmake --build build

Expected behavior

Build successfully

Environment:

Additional context

Screenshot from 2024-09-13 11-39-49

pythonbrad commented 5 days ago

I tested with different features, but I still have the same issues. With the feature x11rb, it builds, but in runtime I saw a log who said "fast text entry is not yet implemented with x11rb".

pentamassiv commented 4 days ago

Thank you for opening an issue. I haven't tried statically linking with enigo. I'll have to investigate it.

The warning you see in the log is not important. Even though the fast_text method is not yet implemented with the x11rb feature, it falls back to entering each key individually. Enigo should enter the text correctly. At some point in the future, I want to make x11rb the default, so if you don't see any other bugs, I would recommend using it.

pythonbrad commented 4 days ago

At the output, no keyboard commands have been executed by enigo. Below is the log

Screenshot from 2024-09-14 15-57-01

pentamassiv commented 3 days ago

I tried to reproduce the linking issue on my computer. Please keep in mind that I never tried statically linking before, so I might state a few things that are incorrect or obvious to someone who did this before. :-)

The build also fails for me but I get a different error:

...
Copying byproducts `libservice.a` to /var/home/penta/Documents/Code/ibus-afrim/build/src
[  0%] Built target _cargo-build_service
[  0%] Built target cargo-build_service
[ 33%] Linking C executable ibus-engine-afrim
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `enigo::platform::x11::Con::new':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:111:(.text._ZN5enigo8platform3x113Con3new17hc622aad86ccaf3e8E+0x143): undefined reference to `xdo_new'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:109:(.text._ZN5enigo8platform3x113Con3new17hc622aad86ccaf3e8E+0x2d0): undefined reference to `xdo_new'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as core::ops::drop::Drop>::drop':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:140:(.text._ZN67_$LT$enigo..platform..x11..Con$u20$as$u20$core..ops..drop..Drop$GT$4drop17ha10ef69ca5f6c75dE+0xa): undefined reference to `xdo_free'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Keyboard>::fast_text':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:157:(.text._ZN61_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Keyboard$GT$9fast_text17h5aa35979197a6c7dE+0x3d5): undefined reference to `xdo_enter_text_window'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Keyboard>::key':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:206:(.text._ZN61_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Keyboard$GT$3key17haf81df5b3a19524eE+0x5bf): undefined reference to `xdo_send_keysequence_window_down'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:220:(.text._ZN61_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Keyboard$GT$3key17haf81df5b3a19524eE+0x832): undefined reference to `xdo_send_keysequence_window_up'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:192:(.text._ZN61_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Keyboard$GT$3key17haf81df5b3a19524eE+0xa97): undefined reference to `xdo_send_keysequence_window'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Mouse>::button':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:249:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$6button17h2014797c142590e3E+0xe8): undefined reference to `xdo_mouse_down'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:253:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$6button17h2014797c142590e3E+0x24f): undefined reference to `xdo_mouse_up'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:257:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$6button17h2014797c142590e3E+0x3bb): undefined reference to `xdo_click_window'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Mouse>::move_mouse':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:274:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$10move_mouse17hdf1e880f3f4515d4E+0x9f): undefined reference to `xdo_move_mouse'
/usr/bin/ld: /var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:270:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$10move_mouse17hdf1e880f3f4515d4E+0x2a2): undefined reference to `xdo_move_mouse_relative'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Mouse>::main_display':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:310:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$12main_display17h9f4d4b3cbfd3ab5bE+0x61): undefined reference to `xdo_get_viewport_dimensions'
/usr/bin/ld: ../src/libservice.a(enigo-b9a8a5e54903c186.enigo.f1a4e1800866da4b-cgu.0.rcgu.o): in function `<enigo::platform::x11::Con as enigo::Mouse>::location':
/var/home/penta/.cargo/registry/src/index.crates.io-6f17d22bba15001f/enigo-0.2.1/src/linux/xdo.rs:325:(.text._ZN58_$LT$enigo..platform..x11..Con$u20$as$u20$enigo..Mouse$GT$8location17h64c3a568bbc4bbeaE+0x7a): undefined reference to `xdo_get_mouse_location2'
collect2: error: ld returned 1 exit status
gmake[2]: *** [apps/CMakeFiles/ibus-engine-afrim.dir/build.make:114: apps/ibus-engine-afrim] Error 1
gmake[1]: *** [CMakeFiles/Makefile2:295: apps/CMakeFiles/ibus-engine-afrim.dir/all] Error 2
gmake: *** [Makefile:136: all] Error 2

I think my error happens because I do not have the static library files for libxdo. I checked it by running these commands:

[penta@toolbox ibus-afrim]$ sudo find /usr -name "libxdo.so"
/usr/lib64/libxdo.so
[penta@toolbox ibus-afrim]$ sudo find /usr -name "libxdo.a"
[penta@toolbox ibus-afrim]$

Do you have the static library files for libxdo? At least on Fedora, I don't think there is a package to get them and you would have to build them yourself. libxdo depends on libxkbcommon libxi and libxtst. These don't typically come preinstalled, so I guess you would want to statically link them too? I didn't find static files for them either, so I guess those would have to be built as well.

When I compare my error with your error, it looks like the libxkbcommon static files might be missing?

I was surprised that you are having these problems because I remembered that you use enigo in another project of yours (afrim). When I looked it up again, I noticed that you use enigo version 1.3 in that project. That version did not depend on xkbcommon. I added it in version 2.0. This is another clue that the cause of your linking issue are the missing files for libxkbcommon.

While investigating this, I found the crate xkbcommon-rs. It is a Rust re-implementation of libxkbcommon. Switching to it would allow us to get rid of another dependency on a C library and would make it easier to build static libraries. It is only three months old and not much used yet, so I need to look into it before switching to it. I created issue https://github.com/enigo-rs/enigo/issues/333 to remind me of it.

pentamassiv commented 3 days ago

In order to debug your other issue, could you please try to run the keyboard.rs example?

git clone https://github.com/enigo-rs/enigo
cd enigo
cargo run --example keyboard    # Use default feature (xdo)
cargo run --example keyboard --features x11rb    # Use x11rb feature

The example should enter the text "Hello World! here is a lot of text ❤️" and select everything. If something was entered when running the example using the default feature, but not with the x11rb feature, we can be sure that the bug is in enigo's code. If that's the case, could you please provide me with more information:

pentamassiv commented 3 days ago

Also, using the default feature (xdo) is pretty reliable, but x11rb still has bugs unfortunately. I just noticed that on my computer for example it only types "ello World! here is a lot of text ❤️".

I hope it won't happen, but there is also the chance that your keymap gets changed incorrectly. A restart of your computer fixes it.

pythonbrad commented 3 days ago

I tested only enigo now.

use enigo::{Enigo, Key, Keyboard};
use std::thread;
use std::time::Duration;

fn main() {
    thread::sleep(Duration::from_secs(5));
    let mut enigo = Enigo::new(&Default::default()).unwrap();

    // write text
    enigo.text("kə̀cɔ̀ nə̀tǐ' !");
}

It works on some applications and others not:

Note: With/without the wayland feature, I have the same behavior.

OS Environment OS: Debian GNU/Linux 12 (bookworm) GNOME Version: 43.9 Windowing System: Wayland

pythonbrad commented 3 days ago

@pentamassiv, thanks, I succeed to build. Instead of use xdo.h, I used libxdo.so.

corrosion_link_libraries(service /usr/lib/x86_64-linux-gnu/libxdo.so)

But I still have this problem of not working on Wayland. Which is not related to this issue.

I think, I can close it now.

pentamassiv commented 3 days ago

TLDR: Your other problem can only be solved either by simulating hardware input (not yet implemented in enigo), updating to a more recent version of Gnome (at least 45) or only using X11.

I am glad you were able to find a solution to the linking issue.

Your other issue can't be solved (with enigo) for now. Unfortunately simulating input on Linux became a mess starting with the transition to Wayland. For a time there was no solution but now we actually have multiple competing solutions. At the beginning there was no Wayland protocol to do it. People resorted to simulating low -level hardware input. Then some compositors created their own protocols such as zwp_input_method_v2 and zwp_virtual_keyboard_v1 on phosh. As far as I know Gnome never implemented them. Starting with Gnome 45 (commit) there is a solution to the problem called libei. It is not a Wayland protocol and I've only implemented the basic functionality for it in engio. Last time I checked, it is the only library that at least has basic/experimental support for it though.

The only way you can simulate input in your version of Gnome is to simulate hardware input e.g with uinput. Unfortunately I did not get to implementing that yet (I am happy about PRs). It is lower level and I am not sure how you can enter chars like "kə̀cɔ̀ nə̀tǐ' !" with it. I think it is only possible to enter keys with it but if you figure out how to change the keymap that could work.

The reason why enigo works for some of your applications is that some of them are X11 applications and the others natively use Wayland. Firefox can use X11 or Wayland but the default on your version is to use X11. If you start Firefox with this command MOZ_ENABLE_WAYLAND=1 firefox it probably won't work to enter text with enigo.

I am sorry that I don't have a solution for you for now, but the future for input simulation on Linux looks bright ;-)

pentamassiv commented 2 days ago

BTW, what does "kə̀cɔ̀ nə̀tǐ' !" mean and which language is it?

pythonbrad commented 2 days ago

Your other problem can only be solved either by simulating hardware input (not yet implemented in enigo), updating to a more recent version of Gnome (at least 45) or only using X11.

I am working with ibus and it's going well. Finally, I will maintain the X version (with Enigo and rdev) and the Wayland version (with IBus).

pythonbrad commented 2 days ago

BTW, what does "kə̀cɔ̀ nə̀tǐ' !" mean and which language is it?

It's an exclamation in Bamileke language to express the surprise.