brotzeit / rustic

Rust development environment for Emacs
Apache License 2.0
713 stars 100 forks source link

Directory that binary executed from #509

Open barslmn opened 1 year ago

barslmn commented 1 year ago

Hi, System Info: Debian sid Doomemacs rustic version: 3.4

I am using rustic from orgmode by compiling rust code blocks. I have the following files:

❯ ls -1
aoc2022.org
input1

And I have the following code block in the org file:

#+BEGIN_SRC rust :results output
use std::fs;

fn main() {
    let file_path = "input1";
    let contents = fs::read_to_string(file_path)
        .expect("Should have been able to read the file");
}
#+END_SRC

#+RESULTS:
: thread 'main' panicked at 'Should have been able to read the file: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:7:10

Executing this block from org file gives the no such file error. In order to investigate I run the following block:

#+BEGIN_SRC rust 
use std::env;
fn main() {
    println!("{:?}", env::current_dir());
}
#+END_SRC

#+RESULTS:
: Ok("/tmp/babel-C1Nmcb/cargozPIbXS")

My question is how do I change the directory that binary is executed from /tmp/babel-XXXXXX/cargoXXXXXX to where the org file is? This does not happen with other languages (I tried C, python, shell) that's why I think rustic repo is the right place ask. Thanks, B

ed9w2in6 commented 9 months ago

I face this issue too, which is a bug in my opinion as most if not all other babel executors all honours executing the binary in the directory specified by buffer local variable default-directory.

AFAIK, the current flow of source block execution is:

  1. rustic ultimately uses rustic-babel-eval to build the compiled binary for the src block.
  2. rustic-bable-eval uses rustic--inheritenv which does tries to retain some environment settings.
  3. when constructing command for make-process, rustic-babel-build-sentinel is used for :sentinel later async execution
  4. Finally, another make-process call in rustic-babel-build-sentinel will use '("cargo" toolchain "run" "--quiet") as command, in which toolchain is specified by :toolchain

From 2, we can see that this project does aim to preserve local environment when executing the compiled binary with org-babel framework. So I hope we can agree that we should fix this issue.

Here, the culprit is at step 4. By default, Emacs will start new process with default-directory as current working directory. However, in rustic-babel-build-sentinel we modified it for cargo to build correctly, since rust uses cargo to manage dependencies. This breaks the flow when calling cargo run.

IMO, the correct high level logic is:

  1. somehow change directory to the original default-directory
  2. call make-process with :command as '("cargo" toolchain "run" "--manifest-path" rustic-babel-dir "--quiet")

For 2., I believe just modifying 1 line in rustic-babel-build-sentinel will suffice. For 1., there are multiple ways to do this, but I believe temporarily setting default-directory before make-process is better.

Please note that there are still edge cases for this method, since I do NOT understand them completely and it should NOT affect org-babel (READ: it MAY affect cargo build, so only change this for org-babel!) For details, see: https://github.com/rust-lang/cargo/issues/6142

FYR, the implementation for C, C++ and D is at org-babel-C-execute, which compiled to a specified path and execute the said path WITHOUT ever changing default-directory.