Function vulkanology::build_utils::concatenate_files [] [src]

pub fn concatenate_files<PI, PO>(file_names: &[PI], write_to: PO) where
    PI: AsRef<Path>,
    PO: AsRef<Path>, 

Concatenates GLSL source files inserting #line statements where necessary.

Motivation

To reuse/reduce duplicate code in shaders and to be able to test certain code parts of shader programs without updating both the actual shaders and the test shaders, one can split the shaders into semantically grouped parts, so-called segments. Prior to building the shaders the build script will have to concatenate the files. Without additional measures the errors of the shader compiler would point to the generated files/lines. Therefore we insert the #line pragma which sets the correct file name and line number in the error reporter. The #line pragma requires enabling the following extension in the shader program:

#extension GL_GOOGLE_cpp_style_line_directive : enable.

Panics

  • If no files were given.
  • If the target directory cannot be created.
  • It a file cannot be opened.
  • Some other file I/O operations fail.

Example

extern crate vulkanology;
use std::fs::{create_dir_all, File};
use std::io::{BufRead, BufReader, Lines, Write};
use std::path::Path;
use vulkanology::build_utils::concatenate_files;

// Working directory.
let target = Path::new("target");
create_dir_all(target).unwrap();

// Input segment paths.
let path_a = target.join("a.in");
let path_b = target.join("b.in");

// Fill segments with some random data
fill_segment_with_random_test_data(&path_a);
fill_segment_with_random_test_data(&path_b);

// Concatenated output path.
let path_c = target.join("c.out");

// Concatenate the files.
concatenate_files(&[&path_a, &path_b], &path_c);

// Check whether the resulting file contains both of the input files and a `#line` pragma.
let file_c = File::open(path_c).unwrap();
let mut lines_c = BufReader::new(&file_c).lines();

// The first file content is not preceeded by a `#line` pragma.
contains_lines(&mut lines_c, path_a);
// Then comes the `#line` pragma ...
let expected_pragma = String::from(r#"#line 1 "target/b.in""#);
let actual_pragma = lines_c.next().unwrap().unwrap();
assert_eq!(expected_pragma, actual_pragma);
// ... and the content of the second file.
contains_lines(&mut lines_c, path_b);