-
Notifications
You must be signed in to change notification settings - Fork 467
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Append freebsd-version
to all --target=*-freebsd if executed on FreeBSD.
#788
Conversation
…eBSD. It's a formally ambiguous thing to do, to assume that FreeBSD-on-FreeBSD cross-compilation targets the same version, but without it it doesn't work at all...
Some additional information. The problem appears to be C++-specific and depends on an include C++ search path being omitted if clang++ is invoked with version-less triplet. EDIT. And for this reason one can wonder if it would be appropriate to extend the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the reason it doesn't happen for C is just because who provides the C++ headers. Anyway, I'm a little concerned that we don't fully understand what's going on here, but I'm fine landing this in the meantime, since it's consistent/coherent with the other change I accepted for freebsd versions.
Ideally I would like a better solution here but I don't know what one looks like. Maybe checking clang's version, but that's pretty gnarly too, tbh. I'll try and look around to see what some programs do to solve this, but this is fine in the meantime.
The only observable difference in C is
It should be noted that as long as CXX is not set to |
Hmmm, I realized that it might happen that it holds true only for Tier 1 and Tier 2 FreeBSD platforms out-of-the-box. Though Tier 3 would require a cross-linker specified, which should show up as a compiler through RUSTC_LINKER, in which case not passing --target would work out. [And as already mentioned elsewhere I would advocate for a warning in case prefixed compiler command, a-b-c-cc, does not match Rust x-y-z target.] |
Hmm, I'm still somewhat concerned given that BSDs are often not ABI-stable across major versions. Also, I do not know what things in system headers might change based on the value of I guess I should set up a couple FreeBSD VMs of different versions to check some of this and verify my own assumptions.
This is tricky because it requires a more complete matching impl than we have. It's very common for cross toolchains to end up with a slightly weird CROSS_COMPILE prefix, even if they're actually the same target. In a lot of cases folks won't see warnings we emit anyway, since it won't be in the same workspace as e.g. the build script running I suppose warning in obviously wrong cases isn't unreasonable though. |
Of course. I merely attempted to provide some colour to the answer to the original what's-up-with-C question. Recall that my suggestion is to avoid passing --target whenever possible, most notably in non-cross-compile cases and to prefixed command lines.
I'm not saying that it's trivial, but that it would be a sensible thing to do. The "warning in obviously wrong cases isn't unreasonable though" remark seems to indicate that we agree :-) |
My preference would be to err on the side of caution and having the compiler error out (as it did before this) and the user realizing (somehow.. because we don't emit a warning!) they need to override the (compiler's, not cargo's) This patch "just works" in more cases than before, but at the cost of some guesswork - unless I'm misunderstanding something, of course. #785 was a lot cleaner because 99.9% of the cases it affected were no cross-compilation at all; the edge case would be "cross compiling for FreeBSD 13 x86_64 on a FreeBSD 14 x86_64 host" and if there were a clean way to detect at the patch site whether or not cargo was executed with a cross-compilation option at all or not, I would use it to make even that error out. |
Yeah, so I think I've become kind of convinced this whole line of fixes is wrong. The first clue being that clang++ 14's fix was not to use the host's A particularly damning thing is that it seems that we're the reason clang had to tweak in 14 this in the first place (https://bugzilla.mozilla.org/show_bug.cgi?id=1628567 is linked from that clang patch, and is an error coming from cc-rs... target doesn't have a version either, so it's not really like we had the info and lost it). In either case, I think given that clang went out of it's way to unbreak us, and even to push us to this behavior, we should have a good reason for not following their approach. Thankfully, following the logic in https://reviews.llvm.org/D77776 seems straightforward:
Thoughts? |
I think your sequence is correct. I agree with the "if the c++ stdlib has not been explicitly configured" for the reasons below. (unless there's a chance that some other tool might incorrectly configure the stdlib before cc-rs enters the picture?) As I understand it,
In both these cases, all that does is get clang++ to use libc++ instead of libstdc++. Explicitly passing in That last caveat is why we should (if we can) include your "If the c++ stdlib has not been explicitly configured already" step - one could theoretically cross-compile C++98 code on a FreeBSD 14 host with cc-rs, targeting FreeBSD 9, and have it work ok by explicitly specifying (I can confirm that replacing the recently added "append freebsd-version to triple" patch with "add For reference: https://wiki.freebsd.org/NewC++Stack |
Well, it's not more incorrect than the originating #785 :-) It's arguably less incorrect, because the originating PR left even the simplest case of cross-compilation in the cold :-) Either way, I would still argue for not passing any --target assuming that the commands found on user $PATH meet the user's expectations. And if the user wants finer control, it would be up to the user. Want to target FreeBSD-N on FreeBSD-M? Pass corresponding --target in the build script or adjust C[XX]FLAGS accordingly. As for (*) After all, the corresponding FreeBSD versions went out of support prior this project's MSRV was released. |
I'm of the opinion that "always erroring out" is more correct than "sometimes works, sometimes introduces subtle issues," so perhaps you're right if you look at it from your perspective and not mine. But in this case, we actually do know the right thing to do so there's no reason to punt on this. In all cases, not passing in anything (neither |
This avoids certain corner cases where supplying the same llvm triple used by rust for clang++ can cause native (host == target) C++ builds to break. This fix supersedes rust-lang#785. See relevant discussions in rust-lang#785 and rust-lang#788.
When cross compiling, we are forced to emit the `--target=<triple>` compiler flag, but this can break clang++ C++ builds on FreeBSD if the triple isn't set to a value that causes clang++ to infer the use of libc++ instead of libstdc++ (the latter of which does not support C++11 and beyond on FreeBSD). By manually specifying the usage of `-std=libc++` we avoid the need to know which version of FreeBSD we are targeting (as we do not have that information from the rust target triple and cannot infer it from the host as we are cross-compiling). Note that we were already specifying a default stdlib value libc++ for `cpp_link_stdlib` under FreeBSD but that is not sufficient. This fix supersedes rust-lang#788. See relevant discussions in rust-lang#785 and rust-lang#788.
See #794 |
When cross compiling, we are forced to emit the `--target=<triple>` compiler flag, but this can break clang++ C++ builds on FreeBSD if the triple isn't set to a value that causes clang++ to infer the use of libc++ instead of libstdc++ (the latter of which does not support C++11 and beyond on FreeBSD). By manually specifying the usage of `-std=libc++` we avoid the need to know which version of FreeBSD we are targeting (as we do not have that information from the rust target triple and cannot infer it from the host as we are cross-compiling). Note that we were already specifying a default stdlib value libc++ for `cpp_link_stdlib` under FreeBSD but that is not sufficient. There are other solutions that would work when not cross compiling such as omitting the `--target` altogether, but there's no compelling reason to add more code if this solution works for both native and cross-compiling cases. This fix supersedes rust-lang#788. See relevant discussions in rust-lang#785 and rust-lang#788.
When cross compiling, we are forced to emit the `--target=<triple>` compiler flag, but this can break clang++ C++ builds on FreeBSD if the triple isn't set to a value that causes clang++ to infer the use of libc++ instead of libstdc++ (the latter of which does not support C++11 and beyond on FreeBSD). By manually specifying the usage of `-std=libc++` we avoid the need to know which version of FreeBSD we are targeting (as we do not have that information from the rust target triple and cannot infer it from the host as we are cross-compiling). Note that we were already specifying a default stdlib value libc++ for `cpp_link_stdlib` under FreeBSD but that is not sufficient. There are other solutions that would work when not cross compiling such as omitting the `--target` altogether, but there's no compelling reason to add more code if this solution works for both native and cross-compiling cases. This fix supersedes rust-lang#788. See relevant discussions in rust-lang#785 and rust-lang#788.
It's a formally ambiguous thing to do, to assume that FreeBSD-on-FreeBSD cross-compilation targets the same version, but without it it doesn't work at all...