fn invoke_rustc(builder: &SpirvBuilder, multimodule: bool) -> Result<PathBuf, SpirvBuilderError> {
    // Okay, this is a little bonkers: in a normal world, we'd have the user clone
    // rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab
    // the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user
    // needs to clone rustc_codegen_spirv and tell us its path! So instead, we *directly reference
    // rustc_codegen_spirv in spirv-builder's Cargo.toml*, which means that it will get built
    // alongside build.rs, and cargo will helpfully add it to LD_LIBRARY_PATH for us! However,
    // rustc expects a full path, instead of a filename looked up via LD_LIBRARY_PATH, so we need
    // to copy cargo's understanding of library lookup and find the library and its full path.
    let rustc_codegen_spirv = find_rustc_codegen_spirv();
    let mut target_features = Vec::new();
    // these must match codegen_cx/mod.rs
    if let Some((major, minor)) = builder.spirv_version {
        target_features.push(format!("+spirv{}.{}", major, minor));
    }
    if let Some(memory_model) = &builder.memory_model {
        target_features.push(
            match memory_model {
                MemoryModel::Simple => "+simple",
                MemoryModel::Vulkan => "+vulkan",
                MemoryModel::GLSL450 => "+glsl450",
            }
            .to_string(),
        );
    }
    let feature_flag = if target_features.is_empty() {
        String::new()
    } else {
        format!(" -C target-feature={}", target_features.join(","))
    };
    let llvm_args = if multimodule {
        " -C llvm-args=--module-output=multiple"
    } else {
        ""
    };
    let rustflags = format!(
        "-Z codegen-backend={} -Z symbol-mangling-version=v0{}{}",
        rustc_codegen_spirv.display(),
        feature_flag,
        llvm_args,
    );
    let mut cargo = Command::new("cargo");
    cargo.args(&[
        "build",
        "--message-format=json-render-diagnostics",
        "-Z",
        "build-std=core",
        "--target",
        "spirv-unknown-unknown",
    ]);
    if builder.release {
        cargo.arg("--release");
    }

    // If we're nested in `cargo` invocation, use a different `--target-dir`,
    // to avoid waiting on the same lock (which effectively dead-locks us).
    // This also helps with e.g. RLS, which uses `--target target/rls`,
    // so we'll have a separate `target/rls/spirv-builder` for it.
    if let (Ok(profile), Some(mut dir)) = (
        env::var("PROFILE"),
        env::var_os("OUT_DIR").map(PathBuf::from),
    ) {
        // Strip `$profile/build/*/out`.
        if dir.ends_with("out")
            && dir.pop()
            && dir.pop()
            && dir.ends_with("build")
            && dir.pop()
            && dir.ends_with(profile)
            && dir.pop()
        {
            cargo.arg("--target-dir").arg(dir.join("spirv-builder"));
        }
    }

    let build = cargo
        .stderr(Stdio::inherit())
        .current_dir(&builder.path_to_crate)
        .env("RUSTFLAGS", rustflags)
        .output()
        .expect("failed to execute cargo build");

    // `get_last_artifact` has the side-effect of printing invalid lines, so
    // we do that even in case of an error, to let through any useful messages
    // that ended up on stdout instead of stderr.
    let stdout = String::from_utf8(build.stdout).unwrap();
    let artifact = get_last_artifact(&stdout);

    if build.status.success() {
        if builder.print_metadata {
            print_deps_of(&artifact);
        }
        Ok(artifact)
    } else {
        Err(SpirvBuilderError::BuildFailed)
    }
}
// Note: in case of multimodule, returns path to the metadata json
in case of multimodule, returns path to the metadata json
in case of multimodule returns path to the metadata json
fn invoke_rustc(builder: &SpirvBuilder, multimodule: bool) -> Result<PathBuf, SpirvBuilderError> {
    // Okay, this is a little bonkers: in a normal world, we'd have the user clone
    // rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab
    // the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user
    // needs to clone rustc_codegen_spirv and tell us its path! So instead, we *directly reference
    // rustc_codegen_spirv in spirv-builder's Cargo.toml*, which means that it will get built
    // alongside build.rs, and cargo will helpfully add it to LD_LIBRARY_PATH for us! However,
    // rustc expects a full path, instead of a filename looked up via LD_LIBRARY_PATH, so we need
    // to copy cargo's understanding of library lookup and find the library and its full path.
    let rustc_codegen_spirv = find_rustc_codegen_spirv();
    let mut target_features = Vec::new();
    // these must match codegen_cx/mod.rs
    if let Some((major, minor)) = builder.spirv_version {
        target_features.push(format!("+spirv{}.{}", major, minor));
    }
    if let Some(memory_model) = &builder.memory_model {
        target_features.push(
            match memory_model {
                MemoryModel::Simple => "+simple",
                MemoryModel::Vulkan => "+vulkan",
                MemoryModel::GLSL450 => "+glsl450",
            }
            .to_string(),
        );
    }
    let feature_flag = if target_features.is_empty() {
        String::new()
    } else {
        format!(" -C target-feature={}", target_features.join(","))
    };
    let llvm_args = if multimodule {
        " -C llvm-args=--module-output=multiple"
    } else {
        ""
    };
    let rustflags = format!(
        "-Z codegen-backend={} -Z symbol-mangling-version=v0{}{}",
        rustc_codegen_spirv.display(),
        feature_flag,
        llvm_args,
    );
    let mut cargo = Command::new("cargo");
    cargo.args(&[
        "build",
        "--message-format=json-render-diagnostics",
        "-Z",
        "build-std=core",
        "--target",
        "spirv-unknown-unknown",
    ]);
    if builder.release {
        cargo.arg("--release");
    }
    // If we're nested in `cargo` invocation, use a different `--target-dir`,
    // to avoid waiting on the same lock (which effectively dead-locks us).
    // This also helps with e.g. RLS, which uses `--target target/rls`,
    // so we'll have a separate `target/rls/spirv-builder` for it.
    if let (Ok(profile), Some(mut dir)) = (
        env::var("PROFILE"),
        env::var_os("OUT_DIR").map(PathBuf::from),
    ) {
        // Strip `$profile/build/*/out`.
        if dir.ends_with("out")
            && dir.pop()
            && dir.pop()
            && dir.ends_with("build")
            && dir.pop()
            && dir.ends_with(profile)
            && dir.pop()
        {
            cargo.arg("--target-dir").arg(dir.join("spirv-builder"));
        }
    }
    let build = cargo
        .stderr(Stdio::inherit())
        .current_dir(&builder.path_to_crate)
        .env("RUSTFLAGS", rustflags)
        .output()
        .expect("failed to execute cargo build");
    // `get_last_artifact` has the side-effect of printing invalid lines, so
    // we do that even in case of an error, to let through any useful messages
    // that ended up on stdout instead of stderr.
    let stdout = String::from_utf8(build.stdout).unwrap();
    let artifact = get_last_artifact(&stdout);
    if build.status.success() {
        if builder.print_metadata {
            print_deps_of(&artifact);
        }
        Ok(artifact)
    } else {
        Err(SpirvBuilderError::BuildFailed)
    }
}
fn invoke_rustc ( builder : & SpirvBuilder , multimodule : bool ) -> Result < PathBuf , SpirvBuilderError > { // Okay, this is a little bonkers: in a normal world, we'd have the user clone // rustc_codegen_spirv and pass in the path to it, and then we'd invoke cargo to build it, grab // the resulting .so, and pass it into -Z codegen-backend. But that's really gross: the user // needs to clone rustc_codegen_spirv and tell us its path! So instead, we *directly reference // rustc_codegen_spirv in spirv-builder's Cargo.toml*, which means that it will get built // alongside build.rs, and cargo will helpfully add it to LD_LIBRARY_PATH for us! However, // rustc expects a full path, instead of a filename looked up via LD_LIBRARY_PATH, so we need // to copy cargo's understanding of library lookup and find the library and its full path. let rustc_codegen_spirv = find_rustc_codegen_spirv ( ) ; let mut target_features = Vec :: new ( ) ; // these must match codegen_cx/mod.rs if let Some ( ( major , minor ) ) = builder . spirv_version { target_features . push ( format ! ( " " major minor ) ) ; } if let Some ( memory_model ) = & builder . memory_model { target_features . push ( match memory_model { MemoryModel :: Simple => " " , MemoryModel :: Vulkan => " " , MemoryModel :: GLSL450 => " " , } . to_string ( ) , ) ; } let feature_flag = if target_features . is_empty ( ) { String :: new ( ) } else { format ! ( " " target_features join ( " " ) ) } ; let llvm_args = if multimodule { " " } else { " " } ; let rustflags = format ! ( " " rustc_codegen_spirv display ( ) feature_flag llvm_args ) ; let mut cargo = Command :: new ( " " ) ; cargo . args ( & [ " " , " " , " " , " " , " " , " " , ] ) ; if builder . release { cargo . arg ( " " ) ; } // If we're nested in `cargo` invocation, use a different `--target-dir`, // to avoid waiting on the same lock (which effectively dead-locks us). // This also helps with e.g. RLS, which uses `--target target/rls`, // so we'll have a separate `target/rls/spirv-builder` for it. if let ( Ok ( profile ) , Some ( mut dir ) ) = ( env :: var ( " " ) , env :: var_os ( " " ) . map ( PathBuf :: from ) , ) { // Strip `$profile/build/*/out`. if dir . ends_with ( " " ) && dir . pop ( ) && dir . pop ( ) && dir . ends_with ( " " ) && dir . pop ( ) && dir . ends_with ( profile ) && dir . pop ( ) { cargo . arg ( " " ) . arg ( dir . join ( " " ) ) ; } } let build = cargo . stderr ( Stdio :: inherit ( ) ) . current_dir ( & builder . path_to_crate ) . env ( " " , rustflags ) . output ( ) . expect ( " " ) ; // `get_last_artifact` has the side-effect of printing invalid lines, so // we do that even in case of an error, to let through any useful messages // that ended up on stdout instead of stderr. let stdout = String :: from_utf8 ( build . stdout ) . unwrap ( ) ; let artifact = get_last_artifact ( & stdout ) ; if build . status . success ( ) { if builder . print_metadata { print_deps_of ( & artifact ) ; } Ok ( artifact ) } else { Err ( SpirvBuilderError :: BuildFailed ) } }
Note: in case of multimodule, returns path to the metadata json
Note : in case of multimodule returns path to the metadata json
builder
&SpirvBuilder
multimodule
bool