pest-parser / pest

The Elegant Parser
https://pest.rs
Apache License 2.0
4.59k stars 257 forks source link

Using `pest_derive` without `std` under a workspace fails in Windows. #996

Closed Shaddy closed 2 weeks ago

Shaddy commented 5 months ago

Describe the bug

I have a project that requires no_std, using following dependencies in Cargo.toml

pest = { git = "https://github.com/pest-parser/pest.git", version = "2.7.8", default-features = false }
pest_derive = { git = "https://github.com/pest-parser/pest.git", version = "2.7.8", default-features = false, features = ["not-bootstrap-in-src"] }

That fails to locate the bootstrap file under Windows, while in MacOS or Linux is working properly.

To Reproduce

NOTE: I can provide a project to reproduce the bug if necessary.

Expected behavior

pest_bootstrap.exe not panicking trying to locate /meta/src/grammar.pest

Additional context

After debugging generated pest_bootstrap.exe I came to the conclusion that the problematic part is the path retrieved by env!("CARGO_MANIFEST_DIR") here:

    let pest = Path::new(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/../meta/src/grammar.pest"
    ));

It seems to prepend \\?\ to the Path, making it fail when trying to resolve the relative "../meta" path.

I managed to fix this issue here:

https://github.com/Shaddy/pest/commit/9ea1515c8f747de2444f4704e5e610b7f84b3580

But probably is not the best way to do it, it is just a workaround.

tomtau commented 5 months ago

I wonder why that would be: is it this https://superuser.com/questions/1069055/what-is-the-function-of-question-marks-in-file-system-paths-in-windows-registry ?

I have seen the \?\C:... path used a lot to get access to files/paths longer than 260 characters. At least when dealing with Win32 API calls. (...)

It could also be a bug in Cargo / Rust tooling in how it populates those env vars on Windows?

tomtau commented 5 months ago

https://github.com/rust-lang/cargo/issues/9770

tomtau commented 5 months ago

Maybe a proper fix is to use something like normpath: https://github.com/wasmCloud/wasmCloud/commit/8b876f1533dac0b622a835d2c883d338addbb172 ?

tomtau commented 5 months ago

or call canonicalize on env!("CARGO_MANIFEST_DIR") and then use .push(es) to construct the path?

Shaddy commented 5 months ago

or call canonicalize on env!("CARGO_MANIFEST_DIR") and then use .push(es) to construct the path?

I tried with canonicalize but it has the same problem, as soon as you enter relative path with the prefix "canonicalize" it simply does not find the file. And if the prefix is already there, it won't be removed.

I also don't understand that if I create a simple project with a build.rs and load the CARGO_MANIFEST_DIR path is not prepended with \\?\, but that's another story (tested just in case, if was because the Cargo.toml rustc version but it seems only happens when running from a different directory).

normpath sounds like the best approach probably at this moment

tomtau commented 1 month ago

@Shaddy did you manage to fix it? I tried to reproduce it and found that the issue is with the pest_bootstrap executable path:

Bootstrap failed: process didn't exit successfully: `\\?\C:\...\.cargo\git\checkouts\pest-00764f90b4d25bc4\5e96e41\target\debug\pest_bootstrap.exe ...

but that's invoked by the cargo crate: https://github.com/pest-parser/pest/blob/21287a93a41733b762f28cd4c0043b9c35bcd9a8/meta/build.rs#L94

Shaddy commented 3 weeks ago

@Shaddy did you manage to fix it? I tried to reproduce it and found that the issue is with the pest_bootstrap executable path:

Bootstrap failed: process didn't exit successfully: `\\?\C:\...\.cargo\git\checkouts\pest-00764f90b4d25bc4\5e96e41\target\debug\pest_bootstrap.exe ...

but that's invoked by the cargo crate:

https://github.com/pest-parser/pest/blob/21287a93a41733b762f28cd4c0043b9c35bcd9a8/meta/build.rs#L94

Yes! I did the workaround I mention in the first comment, to just normalize the path (https://github.com/Shaddy/pest/commit/9ea1515c8f747de2444f4704e5e610b7f84b3580) but in my case I kept the project local. I could try to reproduce this back if you want

tomtau commented 3 weeks ago

@Shaddy I tried

use normpath::PathExt;
//....
    let pest = Path::new(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/../meta/src/grammar.pest"
    )).normalize().expect("normalize path").into_path_buf();

and it didn't seem to help