Vulkano: glslang_validator not copied during build correctly

Created on 8 May 2016  路  11Comments  路  Source: vulkano-rs/vulkano

I'm on linux, and trying to compile the examples is failing because glslang_validator is not generating the output file it is supposed to. It turns out that my
...vulkano/examples/target/debug/build/glsl-to-spirv-11036aceadb12936/out/glslang_validator application is 0 bytes. It returns success when you run (apparently), but it doesn't do anything.

If I manually copy ...vulkano/examples/target/debug/build/glsl-to-spirv-11036aceadb12936/out/bin/glslangValidator to ...vulkano/examples/target/debug/build/glsl-to-spirv-11036aceadb12936/out/glslang_validator then it builds.

I assume that is what this code in glsl-to-spirv/build/build.rs is supposed to do:

    if let Err(_) = fs::hard_link(&path, &out_file) {
        fs::copy(&path, &out_file).expect("failed to copy executable");
    }

However I was unable to figure out how to debug that code. (My attempts to print out paths didn't add any output to cargo build).

bug

All 11 comments

I noticed this problem as well, but don't really know what happens and haven't investigated much. It only happens when you update the library, and removing the target/debug/build/glsl* directory fixes it.

If you want to try debug this, you can see the output of the build script in target/debug/build/glsl-to-spirv-xxxxx/output.

Running cargo clean and cargo build works for me. Some state is getting screwed up by specifically building one example (in my case triangle).

I'm using rustc 1.8.0-dev on a 3.16.0-38-generic linux kernel using an Ext4 (version 1.0) file system.

I checked out another copy of the source at a different path, and tried to build it. After doing a cargo build in examples (which worked) I did a cargo build --bin=triangle which did some more building and failed the same way. vulkano2/examples/target/debug/build/glsl-to-spirv-23741bf12647e3c7/out/bin/glslangValidator is 0 bytes this time though. So maybe the copy/hard link did work, but the thing it was copying from was empty. Doing cargo build again fixed it and cargo build --bin=triangle broke it again. After that it seems to be in a fixed point and building either config no longer has any effect.

I think the creepy stateful thing may be build order related, with some part of the build invalidating some other part of the build. I think the build is palatalized, so may be non-deterministic.

Repro steps (this has worked for me at least twice):
in examples:
cargo clean
cargo build (works)
cargo build --bin triangle (this builds more things and fails)
cargo build (this fails now with same error)

output from cargo build --bin triangle:

vulkano2/examples $ cargo build --bin triangle
Compiling tempfile v2.1.3
Compiling glsl-to-spirv v0.1.1 (file:///mnt/DATA/Scratch/vulkano2/examples)
Compiling wayland-window v0.2.3
Compiling vulkano-shaders v0.1.0 (file:///mnt/DATA/Scratch/vulkano2/examples)
Compiling winit v0.5.0
... (lots of warnings)
Compiling examples v0.1.0 (file:///mnt/DATA/Scratch/vulkano2/examples)
Build failed, waiting for other jobs to finish...
failed to run custom build command for examples v0.1.0 (file:///mnt/DATA/Scratch/vulkano2/examples)
Process didn't exit successfully: /mnt/DATA/Scratch/vulkano2/examples/target/debug/build/examples-dee7d6d1fef8a51c/build-script-build (exit code: 101)
--- stdout
cargo:rerun-if-changed=src/bin/triangle_vs.glsl

--- stderr
thread '

' panicked at 'failed to open SPIR-V output file: Error { repr: Os { code: 2, message: "No such file or directory" } }', src/libcore/result.rs:746
note: Run with RUST_BACKTRACE=1 for a backtrace.

Ping @alexcrichton if you have some time? Since you wrote both Cargo and cmake-rs, maybe you have an idea?
Link to the problematic build script: https://github.com/tomaka/vulkano/blob/c9ccec44854dd95131314075bf9ac62cabd13099/glsl-to-spirv/build/build.rs

Unfortunately I may be missing some context here, could you summarize what's going on perhaps?

@alexcrichton Basically the glsl-to-spirv crate contains the source code of a C program named glslang.
The build script of that crate runs cmake on that source code, then links or copies the executable to OUT_DIR. The crate itself then invokes that executable. So far so good.

Everything works fine so far.

The problem is that if you do a small modification to the build script itself for example, then the executable that lands in OUT_DIR is of size 0. For some reason running it does not produce any error either. The executable in CMake's output directory looks correct however.

Ah it just struck me that maybe CMake rebuilds the executable anyway, which causes the link to become invalid? I'm not sure if that's true for hard links. I'm not familiar enough with Linux.

Someone on IRC suggested that CMake maybe does ftruncate the old executable.

Maybe we should just forget about linking and just copy.

Hm interesting! If you run cmake twice by hand does this reproduce?

Possibly related: I frequently get the following error when upating on Windows, but rerunning cargo build always fixes it:

error: failed to run custom build command for `glsl-to-spirv v0.1.2`
process didn't exit successfully: `C:\Users\Ralith\src\sg2-client\target\debug\build\glsl-to-spirv-4f198926f60b2e06\build-script-build` (exit code: 101)
--- stdout
cargo:rerun-if-changed=build/glslangValidator.exe

--- stderr
thread 'main' panicked at 'failed to copy executable: Error { repr: Os { code: 32, message: "The process cannot access the file because it is being used by another process." } }', src\libcore\result.rs:859
stack backtrace:
   0: std::sys_common::backtrace::_print
             at C:\projects\rust\src\libstd\sys_common\backtrace.rs:94
   1: std::panicking::default_hook::{{closure}}
             at C:\projects\rust\src\libstd\panicking.rs:354
   2: std::panicking::default_hook
             at C:\projects\rust\src\libstd\panicking.rs:371
   3: std::panicking::rust_panic_with_hook
             at C:\projects\rust\src\libstd\panicking.rs:549
   4: std::panicking::begin_panic<collections::string::String>
             at C:\projects\rust\src\libstd\panicking.rs:511
   5: std::panicking::begin_panic_fmt
             at C:\projects\rust\src\libstd\panicking.rs:495
   6: std::panicking::rust_begin_panic
             at C:\projects\rust\src\libstd\panicking.rs:471
   7: core::panicking::panic_fmt
             at C:\projects\rust\src\libcore\panicking.rs:69
   8: core::result::unwrap_failed<std::io::error::Error>
             at C:\projects\rust\src\libcore\macros.rs:29
   9: core::result::Result<u64, std::io::error::Error>::expect<u64,std::io::error::Error>
             at C:\projects\rust\src\libcore\result.rs:761
  10: build_script_build::main
             at .\build\build.rs:27
  11: panic_unwind::__rust_maybe_catch_panic
             at C:\projects\rust\src\libpanic_unwind\lib.rs:98
  12: std::rt::lang_start
             at C:\projects\rust\src\libstd\rt.rs:50
  13: main
  14: __scrt_common_main_seh
             at f:\dd\vctools\crt\vcstartup\src\startup\exe_common.inl:259
  15: BaseThreadInitThunk

Build failed, waiting for other jobs to finish...
error: build failed

I've hit this a few times in the past couple weeks - I think there's enough context in this ticket for me to take a stab at it.

I think I've tracked this down. It's fun!

On an initial build, here's what happens:

  • Run cmake
  • Run make install
  • hard link bin/glslangValidator to glslang_validator

On a rebuild, here's what happens

  • Run cmake (no-op)
  • Run make install (no-op)
  • Fail at hardlinking, since the link already exists
  • copy bin/glslangValidator to glslang_validator :boom:

The first thing Rust's copy routine does is truncate the destination... which in this case is also the source. (see https://github.com/rust-lang/rust/blob/master/src/libstd/sys/unix/fs.rs#L764-L778 and https://github.com/rust-lang/rust/blob/master/src/libstd/fs.rs#L261-L263 )

Getting rid of the hard link seems like the best solution here (and possibly also filing a bug about how rust's copy interacts with hard links!). If we're worried about the disk usage (about 20M) of a copy, would just renaming the executable be a sane option?

EDIT: Oh, the rename won't work on windows where we have a static file in the crate source. I'm just gonna open up a PR to remove the hardlinking code and use a copy unconditionally

Was this page helpful?
0 / 5 - 0 ratings