helix icon indicating copy to clipboard operation
helix copied to clipboard

Can't use `cargo test`

Open alyssais opened this issue 7 years ago • 5 comments

When using Helix, I do most of my testing from Ruby. Sometimes, however, I want to test behaviour that I don't want to expose to Ruby, but still involves Helix objects. To do this, I expected to be able to use cargo test, something like this:

#[macro_use]
extern crate helix;

ruby! {
    class HelixTest {
        struct {
            message: String,
        }

        def initialize(helix, message: String) {
            HelixTest { helix, message }
        }
    }
}

#[test]
fn hello() {
    HelixTest::new("hello world".to_string());
}

cargo test manages to compile this, but it won't run:


cargo test --verbose
       Fresh cstr-macro v0.1.0
       Fresh libc v0.2.22
       Fresh cslice v0.3.0
       Fresh libcruby-sys v0.6.0
       Fresh helix v0.6.0
   Compiling helix_test v0.1.0 (file:///Users/alyssa/desktop/helix_test)
     Running `rustc --crate-name helix_test src/lib.rs --emit=dep-info,link -C debuginfo=2 --test -C metadata=0feaea9da66f2f4d -C extra-filename=-0feaea9da66f2f4d --out-dir /Users/alyssa/desktop/helix_test/target/debug/deps -L dependency=/Users/alyssa/desktop/helix_test/target/debug/deps --extern helix=/Users/alyssa/desktop/helix_test/target/debug/deps/libhelix-a44d38b1cc8a9eb4.rlib`
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-L" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/alyssa/desktop/helix_test/target/debug/deps/helix_test-0feaea9da66f2f4d.0.o" "-o" "/Users/alyssa/desktop/helix_test/target/debug/deps/helix_test-0feaea9da66f2f4d" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/alyssa/desktop/helix_test/target/debug/deps" "-L" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/alyssa/desktop/helix_test/target/debug/deps/libhelix-a44d38b1cc8a9eb4.rlib" "/Users/alyssa/desktop/helix_test/target/debug/deps/liblibcruby_sys-51b4faec2edea8c0.rlib" "/Users/alyssa/desktop/helix_test/target/debug/deps/libcslice-e35cab80719fd98e.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libtest-85fd397c1b504b69.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libterm-95ba05952512bff3.rlib" "/Users/alyssa/desktop/helix_test/target/debug/deps/liblibc-026076ef8cc90032.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-ffed193a1399c490.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-d19edcdb8b3582f0.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-35809200ab841b7b.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-dd5cb334048ac204.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librand-eb0e42c8ae609eea.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcollections-6fcbe3ecfbfa6629.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-7f2c52501770c1c7.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc_jemalloc-ea49ffd3fee5264c.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-4ac31620c28c3400.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd_unicode-7e35037032e227eb.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-10c94a1f2bd23f41.rlib" "/Users/alyssa/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-1afcf087346e8edb.rlib" "-l" "System" "-l" "pthread" "-l" "c" "-l" "m"
  = note: Undefined symbols for architecture x86_64:
            "_HELIX_Qnil", referenced from:
                helix_test::Init_native::_$LT$impl$u20$helix_test..HelixTest$GT$::new::h199cb45eb4b33d59 in helix_test-0feaea9da66f2f4d.0.o
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)

error: aborting due to previous error

error: Could not compile helix_test.

Caused by: process didn't exit successfully: rustc --crate-name helix_test src/lib.rs --emit=dep-info,link -C debuginfo=2 --test -C metadata=0feaea9da66f2f4d -C extra-filename=-0feaea9da66f2f4d --out-dir /Users/alyssa/desktop/helix_test/target/debug/deps -L dependency=/Users/alyssa/desktop/helix_test/target/debug/deps --extern helix=/Users/alyssa/desktop/helix_test/target/debug/deps/libhelix-a44d38b1cc8a9eb4.rlib (exit code: 101)

alyssais avatar May 10 '17 11:05 alyssais

This is going to be because we're excepting that the helix_runtime C library will be loaded already. The solution here would be to have cargo somehow load it from the gem directory. This isn't my area of expertise so I'm not sure how easy or hard that would be be.

wagenet avatar May 10 '17 14:05 wagenet

After much experimentation and learning, I was able to link to Helix from a C program using clang on macOS:

#include <dlfcn.h>
#include <stdio.h>

int main() {
    void *handle = dlopen("./native.bundle", RTLD_NOW);
    if (!handle) goto end;

    dlsym(handle, "HELIX_Qnil");

end:;
    char *error = dlerror();
    if (error) printf("%s\n", error);
    dlclose(handle);

    return !!error;
}
clang -Wl,-force_load,/Users/alyssa/.rubies/ruby-2.4.1/lib/libruby-static.a \
    -framework CoreFoundation -lgmp test.c

I'll look more into this and see if I can reproduce it in Rust, and then try to make it more portable.

alyssais avatar May 10 '17 16:05 alyssais

Nice! I think with Rust you might just be able to set a linker argument (probably with build.rs) to point to the helix_runtime native bundle.

wagenet avatar May 10 '17 16:05 wagenet

I think we might want to expose a Cargo "feature" called no_init, and then guard the Init_native function with a #[cfg]. @wagenet do you know how to do that?

wycats avatar May 10 '17 18:05 wycats

Further investigation on my part reveals that even if I do manage to get cargo test to link properly, I can't run the tests because Init_native runs before I get a chance to dynamically load the library.

@wycats's solution sounds like it would solve the problem, but I wonder if it might be a good idea to try to load helix_runtime from Rust in Init_native if it isn't present? (Is that even possible?)

For future reference (maybe if someone's Googling obscure combinations of Rust commands and linker flags like I have been for the past few hours), here is the Cargo configuration I used to get it to link:

[build]
rustflags = [
  "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup",
  "-C", "link-arg=-rdynamic",
  "-C", "link-arg=-force_load",
  "-C", "link-arg=/Users/alyssa/.rubies/ruby-2.4.1/lib/libruby-static.a",
  "-C", "link-arg=-framework",
  "-C", "link-arg=CoreFoundation",
  "-C", "link-arg=-lgmp",
]

alyssais avatar May 10 '17 18:05 alyssais