tree-sitter/rust-tree-sitter

unresolved external symbol

Cyberduc-k opened this issue · 2 comments

I just copied the example code from the readme and I'm getting this error:

error: linking with `C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\HostX64\x64\link.exe` failed: exit code: 1120
 = note: libhighlights-6d10d8ef55039a48.rlib(highlights-6d10d8ef55039a48.5ptoq1vovgegxtw.rcgu.o) : error LNK2019: unresolved external symbol tree_sitter_rust referenced in function _ZN10highlights11Highlighter3new17h5a2c4522f1121318E
          G:\syntax highlighting\rust\highlights\target\debug\deps\highlights-2195fc3ea40e8e40.exe : fatal error LNK1120: 1 unresolved externals

I'm assuming this is because I do not have the language installed, but there is no documentation on how to do so in rust. If there is a solution for this problem that would be greatly appreciated.

Yeah, that's a linker error. It's happening because you're not including tree_sitter_rust in your program. Tree-sitter parser libraries like tree_sitter_rust are written in C, so in order to use them in a rust program, you either need to either:

  1. Compile them separately as dynamic libraries and then load them dynamically using something like rust-dlopen.
  2. Link them into your rust program at build time.

Option 2 is easier; the README assumes that you're doing that. For some general information about including C files in a rust program, see the Build Scripts chapter of the Rust book.

More specifically, you're going to want to use The cc-rs crate to compile the C code as part of building your crate. In your build.rs file, you'll compile the two source files of tree_sitter_rust:

extern crate cc;

use std::path::PathBuf;

fn main() {
    let tree_sitter_rust: PathBuf = ["path", "to", "tree_sitter_rust", "src"].iter().collect();

    cc::Build::new()
        .include(&tree_sitter_rust)
        .file(tree_sitter_rust.join("parser.c"))
        .file(tree_sitter_rust.join("scanner.cc"))
        .compile("some_output_filename");
}

I fix this setting

$ export RUST_TREE_SITTER_TEST=true

Adding this src/main.rs

extern crate tree_sitter;
use tree_sitter::{Parser, Language};

fn main() {
  let mut parser = Parser::new();
  
  extern "C" { fn tree_sitter_rust() -> Language; }
  
  let language = unsafe { tree_sitter_rust() };
  parser.set_language(language).unwrap();
  
  let source_code = "fn test() {}";
  let tree = parser.parse_str(source_code, None).unwrap();
  let root_node = tree.root_node();
 
  println!("{}", source_code);
  println!("{}", root_node.to_sexp());
  assert_eq!(root_node.kind(), "source_file");
  assert_eq!(root_node.start_position().column, 0);
  assert_eq!(root_node.end_position().column, 12);
}

Notice the unwrap in let tree = parser.parse_str(source_code, None).unwrap();

and running:

$ cargo run