-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Description
Build scripts place their output in a folder created by Cargo. The path to it is passed in the environment variable OUT_DIR
both to the build script and the main code. Since the file is placed in the directory, we need to add the path separator and then the name of the file. There seems to be no way to call include_bytes!
with a platform-agnostic path separator, inserting /
or \
depending on the host OS.
This works but is not portable: include_bytes!(concat!(env!("OUT_DIR"), "/myfile"));
This doesn't work: include_bytes!(concat!(env!("OUT_DIR"), std::path::MAIN_SEPARATOR, "myfile"));
because MAIN_SEPARATOR
is not a literal, and concat!
only eats literals.
I've tried to to assemble a String
in const fn
, but that doesn't work either because String::push()
requires a mutable borrow which are unsable in const fn
.
#[cfg(unix)]
and #[cfg(windows)]
sort of work, but break on cross-compilation because these cfg
attributes look at the target OS, and we need to add a separator that works on the host OS.
It's weird that this is either impossible to accomplish or the way to do so is very obscure. I'd expect this to be a relatively common operation.
rustc --version --verbose
:
rustc 1.46.0-beta.2 (6f959902b 2020-07-23)
binary: rustc
commit-hash: 6f959902b3103c49ca981fbc01871589c3498489
commit-date: 2020-07-23
host: x86_64-unknown-linux-gnu
release: 1.46.0-beta.2
LLVM version: 10.0
Activity
auditable
breaks cross-compilation from Windows to Unix or vice versa rust-secure-code/cargo-auditable#15retep998 commentedon Aug 2, 2020
Can you use a build script to use
cargo:rustc-env
to set your own environment variable that contains the full path using the host specific path separators and whatnot?Shnatsel commentedon Aug 2, 2020
I'll try it. Thanks for pointing this out!
rodrimati1992 commentedon Aug 2, 2020
You can use cfg-ed macros to pass conditional string literals to
concat!
(I can't say if this code specifically is good enough for cross-platform support)
mati865 commentedon Aug 2, 2020
/
should work on Windows, if it doesn't then that is the issue.Shnatsel commentedon Aug 2, 2020
The
build.rs
trick worked, thanks!I did that, but that only look at the target platform and should break when the host platform is different (i.e. when cross-compiling).
include_bytes!
is explicitly documented to use platform-dependent separators. The documentation doesn't say anything about/
working on Windows. Ifinclude_bytes!
allows/
as the cross-platform separator, it would be great to document that.[-]No way platform-independent way to `include_bytes!` data generated by a build script[/-][+]The way to use `include_bytes!` in a cross-platform way is not discoverable[/+]retep998 commentedon Aug 2, 2020
On Windows if
OUT_DIR
for whatever reason uses\\?\
paths then using/
as the separator will break. While it is nice to support/
in paths as much as we can, we should be pushing to ensure code always uses the correct separator for the platform.mati865 commentedon Aug 2, 2020
Oh that's a bummer, I thought the same parsing here would apply as for
std::path::Path
which allows to use both separators on Windows.retep998 commentedon Aug 2, 2020
Well it is the same parsing. Concatenating
foo/bar
onto aPath
that starts with\\?\
on Windows also runs into the exact same issue.CryZe commentedon Aug 2, 2020
Would it maybe make sense for the include_*! macros to allow syntax like
include_bytes!(env!("OUT_DIR") / "myfile")
?danielhenrymantilla commentedon Aug 10, 2020
cfg
)and then:
[-]The way to use `include_bytes!` in a cross-platform way is not discoverable[/-][+]There is no cross-platform way to use `include_bytes!`[/+][-]There is no cross-platform way to use `include_bytes!`[/-][+]There is no cross-platform way to use `include_*!`[/+]23 remaining items