Conversation
|
thanks! |
2bcd066 to
2518e32
Compare
|
Rebased and fixed merge conflict. |
build.rs
Outdated
| fn join_components_with_forward_slashes(path: &Path) -> OsString { | ||
| let parts = path.components().map(|c| c.as_os_str()).collect::<Vec<_>>(); | ||
| let mut parts = path.components().map(|c| c.as_os_str()).collect::<Vec<_>>(); | ||
| if env::var(&env::HOST).unwrap().contains("cygwin") { |
There was a problem hiding this comment.
What is the problem that you are trying to solve here? Could you add a #[test] that demonstrates it? Isn't it something that would also affect regular Windows builds?
There was a problem hiding this comment.
The problem is explained in the comment below. Without this hack, the build hangs and eventually fails. \\path in Windows denotes a UNC path (which can be an IP or a hostname), which Cygwin preserves in its emulation of Unix paths (in this case, turning it into //path), as allowed by POSIX. Thus, //path will try to access a network share with a hostname of path (looking like a hang in the meantime) and fail. This often trips up scripts that assume the Linux behavior. This is not a problem for Windows builds because it uses the traditional DOS paths. What the #[test] be for? Checking the input and output of the path transformation?
There was a problem hiding this comment.
Checking the input and output of the path transformation?
Yes, in particular for an input that does the wrong thing without your patch.
There was a problem hiding this comment.
Hmm, it seems I cannot put #[test]s inside build.rs directly. Do you have a suggestion on where to put it?
There was a problem hiding this comment.
I've used a simple assert_eq! and assert_ne! for now.
There was a problem hiding this comment.
I refactored build.rs to make it more testable in PR #2807.
Branch b/join_components_with_forward_slashes-2, based on that PR, demonstrates where to put the tests.
There was a problem hiding this comment.
I think the refactor has moved/transformed the problem too:
- that function is needed/used only at build time
- but it is tested like it will be used at runtime
- and now it cannot test the host, which is the important bit
For now I've used the target (and thus assuming HOST == TARGET / target_os) but I don't think this is ideal.
|
Can squash/cleanup commits if desired. |
build.rs
Outdated
| define_env! { pub CARGO_PKG_VERSION_PATCH: SetByCargo } | ||
| define_env! { pub CARGO_PKG_VERSION_PRE: SetByCargo } | ||
| define_env! { pub DEBUG: SetByCargo } | ||
| define_env! { pub HOST: SetByCargo } |
There was a problem hiding this comment.
It might still be needed, the build.rs refactoring has moved/transformed the problem as explained elsewhere.
build.rs
Outdated
| fn join_components_with_forward_slashes(path: &Path) -> OsString { | ||
| let parts = path.components().map(|c| c.as_os_str()).collect::<Vec<_>>(); | ||
| let mut parts = path.components().map(|c| c.as_os_str()).collect::<Vec<_>>(); | ||
| if env::var(&env::HOST).unwrap().contains("cygwin") { |
There was a problem hiding this comment.
I refactored build.rs to make it more testable in PR #2807.
Branch b/join_components_with_forward_slashes-2, based on that PR, demonstrates where to put the tests.
fb322c7 to
2e385a1
Compare
|
Please check out PR #2808 and see if that resolves the path mangling issue you can into. IIUC, basically we were always rewriting a leading slash ("/") or backslash ("\") into two forward slashes ("//"), and instead we should just rewrite them to a single forward slash, regardless of OS. (And also there are some kinds of paths that we shouldn't try to rewrite, "verbatim" paths.) |
|
rust-lang/rust#141864 has details on Cygwin path handling and Cygwin's implementation of |
|
I would like to understand, though, why are we even rewriting paths? Unfortunately the original commit doesn't tell much about why, and the original PR review only reports a vague failure, with a dead reference to a CI run. I would love to know more details about the root cause of that failure, I don't think it is likely patching paths was the only/correct solution. |
I think it boils down to an unwillingness to modify the Perl code to do the right thing, or to even read its regex-y stuff to understand why it failed in that scenario. I don't even really know any more. |
Do we really need to handle them? AFAICT we always get a traditional DOS path.
The pattern is indeed pervasive, and modifications are probably ideally done upstream.
It seems to be a handrolled
That method of locating |
|
OK, go ahead and rebase this on |
|
Hmm, I was thinking as simple as a dumb byte replace, simply flipping any |
My expectation that the new logic that's already in the
In the main branch we already punt on all verbatim paths. My understanding is that the new handling absolute paths should be good for what you need, and the new support for UNCs shouldn't get in the way of your work either. I.e. I am hoping you don't need to change anything in the new path.rs. |
|
Also, to help understand the philosophy here, my goal is to have as few Cygwin-specific bits as possible. In general we try to not have OS- and Arch- specific logic unless there is a performance benefit to it. That is why, for example, I just fixed the path mangling for all targets instead of adding a workaround specific to Cygwin; the improvement was, AFAICT, more aesthetic than it was practically useful for other targets, but that aesthetic improvement fixes (IIUC) the problem Cygwin had, in a universal way. |
Unfortunately, that is not the case, with no changes, this is what happens: And if I change Line 22 in 9bf10ab -pub const TARGET_SUPPORTS_UNCS_AND_BACKSLASHES: bool = cfg!(target_os = "windows");
+pub const TARGET_SUPPORTS_UNCS_AND_BACKSLASHES: bool = cfg!(any(target_os = "windows", target_os = "cygwin"));then I get less but still some failures:
Sure, I can understand that.
My idea was something like: pub fn join_components_with_forward_slashes(path: &Path) -> OsString {
unsafe {
OsString::from_encoded_bytes_unchecked(
path
.as_os_str()
.to_owned()
.into_encoded_bytes()
.iter()
.map(|&x| if x == b'\\' { b'/' } else { x })
.collect()
)
}
}I was also questioning the utility of this function in #2730 (comment), because I tried something like: pub fn join_components_with_forward_slashes(path: &Path) -> OsString {
path.as_os_str().to_owned()
}and found no issues with my local setup. Then again I only have x86 machines, but I don't see why it should be arch specific problem. |
It seems like libstd on Windows parses this as a UNC prefix "\foo\bar" follow by a "root", but on Cygwin it parses it in a Unixy way. Which version of the Rust toolchain are you using? It seems like the handling of Windows prefixes was added in 1.89? |
|
|
Well, |
|
This code: fn main() {
println!("{:?}", std::path::Path::new("//server/path").components());
}prints |
|
I'll push my rebase in the meantime. |
f62158b to
3281553
Compare
briansmith
left a comment
There was a problem hiding this comment.
PR #2811 is intended to address the weird parsing of "//" on Cygwin.
3281553 to
0e5a697
Compare
|
Rebased. |
briansmith
left a comment
There was a problem hiding this comment.
OK, this is just about as minimal as I can expect. Just one (x3) nit here.
Does the new logic in path.rs work for you?
|
0e5a697 to
fc857a7
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #2730 +/- ##
=======================================
Coverage 96.49% 96.49%
=======================================
Files 207 207
Lines 20430 20430
Branches 520 520
=======================================
Hits 19713 19713
Misses 599 599
Partials 118 118 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
cargo test --release --all-featurespasses onx86_64-pc-windows-gnu,x86_64-pc-cygwin, andx86_64-unknown-linux-gnu, at least on my machine.