paulyoung
(Paul Young)
February 25, 2023, 1:29am
#1
I managed to link and load a dynamic library when using the simulator on macOS:
opened 01:05AM - 25 Feb 23 UTC
tl; dr
It seems possible to use dynamically linked libraries with the simulat… or but I can't figure out how to modify the search paths.
Hopefully this is doable on device as well or this is all moot.
***
I'm depending on a crate that provides bindings for a library, and it expects the library to be dynamically linked.
At first I was getting `Undefined symbols for architecture` with `crank build`. I've addressed that with the following `build.rs`:
```rust
use std::{env, path::Path};
fn main() {
let cargo_manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
// This approach doesn't work because the library is named `foo_libqux.dylib`
/*
println!(
"cargo:rustc-link-search=all={}",
Path::new(&cargo_manifest_dir).join("lib").display()
);
println!("cargo:rustc-link-lib=dylib=retro");
*/
println!(
"cargo:rustc-link-arg={}",
Path::new(&cargo_manifest_dir).join("lib/foo_libqux.dylib").display()
);
}
```
However, `crank build --run` results in this error at runtime:
```
dlopen(/Users/py/projects/paulyoung/MyProject/main/target/My Project.pdx/pdex.dylib, 0x0006): Library not loaded: foo_libqux.dylib
Referenced from: /Users/py/projects/paulyoung/MyProject/main/target/My Project.pdx/pdex.dylib
Reason: tried: '/nix/store/g8b81w9kpb82gm7702ca692mp5flm7pf-apple-framework-CoreFoundation-11.0.0/Library/Frameworks/foo_libqux.dylib' (no such file), '/nix/store/g8b81w9kpb82gm7702ca692mp5flm7pf-apple-framework-CoreFoundation-11.0.0/Library/Frameworks/foo_libqux.dylib' (no such file), '/usr/lib/swift/foo_libqux.dylib' (no such file), '/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib' (no such file), '/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib' (no such file), '/usr/lib/swift/foo_libqux.dylib' (no such file), '/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib' (no such file), '/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib' (no such file), 'foo_libqux.dylib' (no such file), '/usr/local/lib/foo_libqux.dylib' (no such file), '/usr/lib/foo_libqux.dylib' (no such file), '//foo_libqux.dylib' (no such file), '/usr/local/lib/foo_libqux.dylib' (no such file), '/usr/lib/foo_libqux.dylib' (no such file)
```
<details>
<summary>(expand for a bulleted list of search paths)</summary>
<ul>
<li><code>/nix/store/g8b81w9kpb82gm7702ca692mp5flm7pf-apple-framework-CoreFoundation-11.0.0/Library/Frameworks/foo_libqux.dylib</code></li>
<li><code>/nix/store/g8b81w9kpb82gm7702ca692mp5flm7pf-apple-framework-CoreFoundation-11.0.0/Library/Frameworks/foo_libqux.dylib</code></li>
<li><code>/usr/lib/swift/foo_libqux.dylib</code></li>
<li><code>/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib</code></li>
<li><code>/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib</code></li>
<li><code>/usr/lib/swift/foo_libqux.dylib</code></li>
<li><code>/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib</code></li>
<li><code>/Users/py/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/MacOS/../Frameworks/foo_libqux.dylib</code></li>
<li><code>foo_libqux.dylib</code></li>
<li><code>/usr/local/lib/foo_libqux.dylib</code></li>
<li><code>/usr/lib/foo_libqux.dylib</code></li>
<li><code>//foo_libqux.dylib</code></li>
<li><code>/usr/local/lib/foo_libqux.dylib</code></li>
<li><code>/usr/lib/foo_libqux.dylib</code></li>
</ul>
</details>
I've tried setting `LD_LIBRARY_PATH=./lib`, `DYLD_LIBRARY_PATH=./lib`, and `DYLD_FALLBACK_LIBRARY_PATH=./lib` when invoking `crank` but it doesn't make a difference to the search paths. I tried the same thing with `open -a "Playdate Simulator" ./target/My\ Project.pdx` but that didn't change anything either.
I also tried adding those environment variables via `cmd.env` in `run_pdc` and `run_simulator` in `main.rs` but still no change.
This obviously isn't a solution, but I copied the library and made it available at `~/Developer/PlaydateSDK/bin/Playdate Simulator.app/Contents/Frameworks/foo_libqux.dylib` and things appear to work.
It at least seems to demonstrate that this should work for the simulator as long as the search paths are set correctly. I don't have a device yet and I'm not sure where to begin on making this work there but hopefully there's nothing preventing this.
If I could get some insight or advice on how to go about this properly I'd be very grateful. Happy to make a PR to propose changes or document what I've found as a result.
I'm wondering if this is possible on devices. I don't have a device yet so I can't experiment.
I'm hoping someone could provide some insight on that so I can consider moving forward using the simulator for now and figure out static build later.
paulyoung
(Paul Young)
February 25, 2023, 1:38am
#2
I explained in the linked GitHub issue that I wasn't able to figure out how to modify the search paths for the simulator.
If anyone has any info on how to do that, I'd appreciate it.
samdze
(Samuele Zolfanelli)
February 25, 2023, 5:53pm
#3
As far as I remember FreeRTOS (the OS the Playdate runs) doesn't support dynamic linking, sadly.
1 Like
paulyoung
(Paul Young)
February 26, 2023, 5:14am
#4
Thanks. I didn’t know about FreeRTOS.
I found an old support thread from 2011 that says the same.
dave
(Dave Hayden)
February 27, 2023, 3:33am
#5
The current C API loader requires code to be compiled for a specific address, but we do have a new loader in the works that does relocation. I think that's all we'll need in order to support dynamic libraries on the device, but no promises
2 Likes
paulyoung
(Paul Young)
February 27, 2023, 7:26am
#6
Thanks, thats good to know!
Creating a static library looks more promising than I first thought in this case, but still a non-zero amount of effort.
Dynamic library support would be good in general.
paulyoung
(Paul Young)
March 4, 2023, 3:35am
#7